在游戏开发中,动画系统是赋予角色和物体生命的关键组件。Unity提供了两套核心动画工具:Animation和Animator。Animation是基础动画系统,适合简单的单一动画剪辑;而Animator则是更高级的状态机系统,能够处理复杂的动画过渡和混合。
重要提示:Unity 2021 LTS版本后,Animation系统已被标记为Legacy(旧版),但理解其工作原理对于掌握动画基础仍然很有帮助。
在开始制作动画前,需要确保:
为GameObject添加动画的步骤:
注意:如果物体没有Animator组件,Unity会自动添加一个。这是新版动画系统的标准组件。
Animation窗口包含以下关键功能区域:
设置初始关键帧:
添加中间关键帧:
曲线编辑器使用:
动画事件允许在特定时间点触发代码:
csharp复制public void OnAnimationEvent(string message)
{
Debug.Log("动画事件触发: " + message);
}
Animator Controller是动画状态机的可视化工具:
Solo和Mute:
Has Exit Time:
Write Defaults:
混合树允许根据参数值混合多个动画:
csharp复制// 控制1D混合树
animator.SetFloat("BlendParam", 0.5f);
Animator支持四种参数类型:
csharp复制public class PlayerAnimation : MonoBehaviour
{
private Animator anim;
private float moveSpeed;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
moveSpeed = Input.GetAxis("Vertical");
anim.SetFloat("Speed", moveSpeed);
if(Input.GetKeyDown(KeyCode.Space))
{
anim.SetTrigger("Jump");
}
}
}
创建Avatar Mask:
设置动画层:
通用人形动画重定向步骤:
使用动画压缩:
优化过渡条件:
使用动画合批:
排查步骤:
优化方法:
检查点:
实现步骤:
csharp复制void Update()
{
float speed = Mathf.Abs(Input.GetAxis("Horizontal"));
anim.SetFloat("Speed", speed);
if(speed > 0.1f)
{
transform.Translate(Vector3.right * speed * Time.deltaTime);
}
}
实现方法:
csharp复制void Attack()
{
if(!anim.GetCurrentAnimatorStateInfo(0).IsName("Attack"))
{
anim.SetTrigger("Attack1");
}
else if(anim.GetCurrentAnimatorStateInfo(0).normalizedTime > 0.5f)
{
anim.SetTrigger("Attack2");
}
}
| 方法 | 描述 | 示例 |
|---|---|---|
| Play | 直接播放指定状态 | anim.Play("Run") |
| SetTrigger | 触发一次性动画 | anim.SetTrigger("Jump") |
| CrossFade | 平滑过渡到新动画 | anim.CrossFade("Fall", 0.2f) |
| GetCurrentAnimatorStateInfo | 获取当前状态信息 | anim.GetCurrentAnimatorStateInfo(0) |
通过AnimatorStateInfo可获取:
csharp复制AnimatorStateInfo state = anim.GetCurrentAnimatorStateInfo(0);
if(state.IsName("Jump") && state.normalizedTime > 0.9f)
{
// 跳跃动画即将结束
}
Profiler窗口:
Frame Debugger:
可视化调试:
日志输出:
csharp复制void OnAnimatorMove()
{
Debug.Log("动画位移: " + anim.deltaPosition);
}
在实际项目开发中,我发现合理使用动画层和遮罩可以显著提升动画系统的灵活性。例如,将基础移动放在第0层,特殊动作放在第1层,通过权重控制混合效果。同时,对于复杂的角色动画,建议先设计好状态机流程图,再在Unity中实现,这样可以避免后期混乱。