【Unity2D】【3】2D的灵魂-艺术与动画

Unity 2D动画核心技术详解

Unity 2D 从零精通:第三阶段 - 2D的灵魂,艺术与动画

引言:从功能到体验的飞跃

在前两篇文章中,我们构建了游戏的核心骨架:移动、物理、碰撞、交互。我们的飞船可以飞行、射击,行星可以被摧毁,分数会增加。从功能上讲,它已经是一个完整的“游戏”了。

然而,它缺乏“灵魂”。飞船的移动生硬得像滑动一个图标,爆炸只是简单的消失。真正的游戏通过动画(Animation) 来传递感觉、重量和反馈,它是让玩家沉浸其中的关键。一个简单的摇晃可以表达冲击力,一个粒子效果可以传达爆炸的震撼,角色流畅的跑动跳跃能极大地提升操作手感。

在这一篇,我们将为我们冰冷的机械世界注入生命。我们将学习Unity强大且灵活的动画系统,让我们的飞船不仅能动,而且能“活灵活现”地动。我们将从处理静态图片开始,直到创造出由代码控制的复杂状态动画。

第一章:艺术的基石——深入Sprite Editor

在制作动画前,我们必须确保我们的原始素材(Sprites)被正确设置。Unity的Sprite Editor就是为此而生的瑞士军刀。

1.1 切片(Slicing)精灵图集(Sprite Atlas)

艺术家们通常会在一张大图上绘制所有相关的帧,这种图被称为精灵图集雪碧图(Sprite Sheet)。我们需要将它切割成单个的Sprite才能使用。

  1. 准备图集:假设我们有一张图片(ship_sheet.png),它包含了飞船 idle(待机)和 thrust(推进)两个动画,每个动画有4帧,水平排列。

  2. 导入设置:在Project窗口中选中这张图片,在Inspector中进行以下关键设置:

    • Texture Type:必须设置为 Sprite (2D and UI)
    • Sprite Mode:因为我们有多个帧,所以必须设置为 Multiple(如果是单个Sprite,则用Single)。
    • 点击Apply
  3. 打开Sprite Editor:点击Sprite Editor按钮。

  4. 自动切片

    • 在打开的窗口中,点击顶部工具栏的Slice按钮。
    • 在弹窗中,Type选择Grid By Cell Count(按单元格数量)或Grid By Cell Size(按单元格大小)。根据你的图集结构选择。
    • 例如,如果你的图集是2行4列(2个动画,每个4帧),你可以选择Grid By Cell Count,并设置C(列)为 4R(行)为 2
    • 点击Slice,Unity会自动根据网格切割图片。你可以手动拖拽绿色边框微调每个Sprite的范围。
  5. 应用并命名:点击Apply,关闭Sprite Editor。现在在你的图片资源下,可以看到所有被切好的单个Sprites。建议为它们重命名,例如ship_idle_1, ship_idle_2, ship_thrust_1, ship_thrust_2等。良好的命名是高效动画制作的第一步。

1.2 枢轴点(Pivot)的重要性

枢轴点是Sprite旋转和缩放所围绕的点。一个错误的枢轴点会导致动画看起来极其怪异。

  • 如何设置:在Sprite Editor中,点击任意一个切好的Sprite,你可以在右侧设置它的Pivot。常用的预设是:
    • Center:对于行星、子弹等对称物体。
    • Bottom:对于站在地面上的角色。
    • Custom:可以手动精确定位。对于飞船,枢轴点通常设置在它的中心或尾部(如果它要围绕尾部旋转)。
第二章:创造生命——Animation窗口与逐帧动画

Unity提供了两种主要的2D动画制作方式:逐帧动画(Frame-by-Frame)骨骼动画(Cutout/骨骼动画)。我们先从最直观的逐帧动画开始。

目标:为我们的飞船创建一个“推进器”动画,当玩家移动时播放。

2.1 创建Animation Clip(动画片段)
  1. 选中对象:在Hierarchy中,选中你要添加动画的GameObject——我们的PlayerShip
  2. 打开动画窗口Window -> Animation -> Animation(快捷键Ctrl+6)。将窗口停靠在方便的位置(通常与Game视图并排)。
  3. 创建新动画:在Animation窗口中,点击Create按钮。Unity会提示你保存一个新的.anim文件。在项目Assets中创建一个Animations文件夹,并将文件命名为ShipThrust.anim这创建了一个新的Animation Clip(动画片段)
2.2 制作逐帧动画
  1. 认识时间轴:Animation窗口打开后,会显示一个时间轴。水平轴是时间(帧),垂直轴是属性(如Sprite Renderer.sprite)。
  2. 录制动画
    • 确保红色的录制按钮是按下状态。
    • 将时间轴播放头(那条红色的线)移动到0:00的位置。
    • 在Project窗口中,找到ship_thrust_1这张Sprite,拖拽到Animation窗口的时间轴上。Unity会自动为Sprite Renderer组件的Sprite属性创建一个关键帧。
    • 将播放头移动到第0:05(表示第5帧,Unity默认每秒60帧,所以这是约0.083秒)。
    • ship_thrust_2拖拽到时间轴上,创建第二个关键帧。
    • 重复这个过程,将ship_thrust_3, ship_thrust_4也依次放入,间隔相同。
  3. 预览动画:点击Animation窗口上的播放按钮,你可以在Scene视图或Game视图中看到飞船的推进器开始闪烁动画!
  4. 调整速度:如果你的动画播放得太快或太慢,你可以缩放整个时间轴。选中所有关键帧(在时间轴上拖拽框选),然后将它们整体向右拖拽,增加间隔,动画就会变慢。
2.3 设置默认状态(Idle)

现在,只要你运行游戏,飞船就会一直播放推进动画。我们需要一个默认的、不推进时的“待机”(Idle)状态。

  1. 创建Idle动画:再次点击Animation窗口中的Create按钮(它现在可能显示为ShipThrust),创建一个新的动画片段,命名为ShipIdle.anim。用同样的方法,将ship_idle_1, ship_idle_2等Sprite拖入,制作一个缓慢循环的待机动画(比如两帧切换)。
  2. 了解Animator Controller:当你创建第一个动画时,Unity自动做了一件重要的事:它为PlayerShip对象添加了一个Animator组件,并创建了一个Animator Controller资源(通常和第一个动画在同一目录,名为PlayerShip)。
    • Animator组件:是播放动画的“播放器”。
    • Animator Controller:是控制播放哪个动画的“大脑”或“状态机”。
第三章:控制大脑——Animator Controller与状态机

现在我们有了两个动画片段(Idle和Thrust),我们需要一个逻辑来告诉Unity何时播放哪一个。这就是Animator Controller状态机(State Machine) 的工作。

3.1 理解状态机

双击Project窗口中的Animator Controller资源(如PlayerShip),会打开Animator窗口Window -> Animation -> Animator)。

你会看到一个流程图,这就是状态机。它包含了:

  • 状态(States):橙色的Any State,黄色的EntryExit是系统状态。蓝色的方块(如ShipIdle)是你创建的动画状态。其中一个状态是橙色的,这是默认状态(通常是Entry指向的那个)。
  • 转换(Transitions):状态之间的箭头。它定义了从一个状态切换到另一个状态的条件。
3.2 创建转换与参数(Parameters)

我们的逻辑是:当玩家按下移动键时,播放Thrust动画;不按的时候,播放Idle动画。

  1. 创建参数:在Animator窗口的左上方,有一个Parameters标签页。点击+号,选择Bool(布尔值),创建一个新参数,命名为IsThrusting。这个参数将由我们的代码控制。
  2. 创建转换
    • 右键点击ShipIdle状态 -> Make Transition。然后将出现的箭头拖到ShipThrust状态上。这创建了一个“从Idle到Thrust”的转换。
    • 同样地,右键点击ShipThrust状态 -> Make Transition,创建一条指向ShipIdle的箭头。这是“从Thrust回到Idle”的转换。
  3. 设置转换条件
    • 点击从Idle到Thrust的箭头。在Inspector中,你会看到Conditions列表。点击+,设置条件为:IsThrusting True
    • 点击从Thrust到Idle的箭头。在Inspector中,设置条件为:IsThrusting False
  4. 取消勾选:在两条转换线的Inspector中,找到Has Exit Time取消勾选。Exit Time会等待当前动画播放完才转换,我们希望输入能立即得到响应,所以必须取消它。

现在,你的状态机逻辑已经清晰:IsThrustingfalse时,播放Idle动画;为true时,立即切换到Thrust动画。

3.3 用代码控制动画状态

最后一步,我们需要修改PlayerMovement脚本,根据玩家的输入来设置Animator中的IsThrusting参数。

  1. 获取Animator组件引用:打开PlayerMovement脚本,我们需要在代码中访问Animator组件。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float horizontalLimit = 8f;
    public GameObject bulletPrefab;
    public Transform firePoint;
    public float fireRate = 0.5f;
    private float nextFireTime = 0f;

    // 新增:声明一个变量来引用Animator组件
    private Animator shipAnimator;

    // Start在第一次帧更新之前调用,用于初始化
    void Start()
    {
        // 新增:在游戏开始时,获取挂载在同一GameObject上的Animator组件
        shipAnimator = GetComponent<Animator>();
        // 安全检查:确保获取到了组件
        if (shipAnimator == null)
        {
            Debug.LogError("Animator component not found on the player ship!");
        }
    }

    void Update()
    {
        HandleMovement();
        HandleShooting();
    }

    void HandleMovement()
    {
        float horizontalInput = Input.GetAxis("Horizontal");
        Vector3 movement = new Vector3(horizontalInput, 0f, 0f);
        transform.Translate(movement * moveSpeed * Time.deltaTime);

        Vector3 currentPosition = transform.position;
        currentPosition.x = Mathf.Clamp(currentPosition.x, -horizontalLimit, horizontalLimit);
        transform.position = currentPosition;

        // 新增:根据是否有水平输入,来设置Animator的参数
        // 即使输入很小(> 0.1 或 < -0.1),我们也认为玩家在尝试移动
        bool isMoving = Mathf.Abs(horizontalInput) > 0.1f;
        shipAnimator.SetBool("IsThrusting", isMoving);
    }

    // ... HandleShooting和Shoot方法保持不变 ...
}
  1. 保存脚本并测试:返回Unity,播放游戏。现在,当你按下A或D键移动飞船时,你应该能看到飞船的Sprite切换为推进动画!松开按键,它又回到待机状态。

恭喜!你已经成功创建了一个由玩家输入驱动的状态动画!

第四章:进阶技术——2D骨骼动画简介

对于复杂的角色(如人类、动物),逐帧动画工作量大且不易修改。Unity提供了更强大的2D骨骼动画系统,它像操控木偶一样,通过移动“骨骼”来驱动“皮肤”(Sprite),从而产生流畅的动画。

4.1 准备工作:PSB与骨骼工具
  1. 资源要求:骨骼动画需要角色各个部分(身体、手臂、腿等)是分层的PSDPSB文件(Photoshop格式)。Unity对PSB支持更好。确保在导入PSB文件时,Texture Type设置为Sprite (2D and UI)Sprite Mode设置为Multiple,然后使用Sprite Editor正确切片。
  2. 打开窗口Window -> Animation -> Animation(如果之前是Animation窗口,请切换到Animator旁边的Animation选项卡)Window -> 2D -> PSD Importer
4.2 快速工作流
  1. 生成骨骼:在Project中选中分好层的PSB文件,在Inspector中点击Sprite Editor。在Sprite Editor中,选择Skinning Editor(蒙皮编辑器)。这里你可以使用自动骨骼生成工具手动创建骨骼
  2. 绑定蒙皮:创建骨骼后,你需要将不同的Sprite(皮肤)绑定(Bind) 到影响它们的骨骼上。这可以通过自动权重或手动绘制权重来完成。
  3. 制作动画:绑定完成后,你就可以像在3D中一样,在Animation窗口中通过在不同时间点旋转、移动骨骼来制作动画了,而不是切换整张Sprite。这使得制作“转身”、“挥手”等动画变得异常简单和高效。

虽然本篇不会深入每一步,但了解这个强大工具的存在至关重要。对于复杂的2D角色,骨骼动画是行业标准。

第五章:总结与展望

你在本篇掌握的动画之力:

  1. 精通了Sprite Editor:学会了如何切片精灵图集和正确设置枢轴点。
  2. 掌握了逐帧动画:使用Animation窗口创建了基于Sprite切换的动画片段(Animation Clip)。
  3. 理解了核心概念:学会了使用Animator Controller状态机(State Machine) 来逻辑性地管理多个动画。
  4. 实现了代码控制:通过C#脚本Animator.SetBool()动态控制动画状态的切换,使游戏逻辑与视觉反馈完美结合。
  5. 窥见了未来:了解了更高级的2D骨骼动画工作流。

你的飞船不再是一个简单的移动图片,而是一个能够响应你操作、拥有不同状态的活生生的实体。这种视觉反馈极大地提升了游戏的质感和玩家的沉浸感。

下一篇预告:《第四阶段:构建你的世界——关卡设计与Tilemap》
在下一篇文章中,我们将离开单个对象,放眼整个游戏世界。我们将学习:

  • Unity强大的Tilemap系统,用于快速、高效地绘制大型游戏关卡。
  • 规则瓦片(Rule Tiles)随机瓦片(Random Tiles) 等高级技巧,让关卡设计变得有趣且多样。
  • 如何解决图层排序(Sorting Layers和Order in Layer) 问题,确保物体正确遮挡。
  • 使用CinemaMachine实现平滑的摄像机跟随。
  • 最终,我们将构建一个完整的平台跳跃游戏关卡!

练习与思考:

  1. 为行星被子弹击中创建一个简单的“爆炸”动画(可以是一个缩放消失或几帧闪烁的动画),并把它做进状态机里。(提示:你需要修改Bullet脚本,触发行星播放动画而不是直接Destroy它)。
  2. 尝试为你飞船的idle状态添加更多帧,让它看起来像是在太空中轻微浮动,而不仅仅是两张图切换。
  3. 探索Animation窗口中的曲线(Curves) 功能,尝试让Sprite的透明度(Alpha)随时间变化,制作一个淡入淡出的效果。

世界正在你的手中变得鲜活。准备好画笔,我们下次将绘制更广阔的天地!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值