在游戏开发中,动画是赋予角色和场景生命力的关键要素。Unity提供了两套核心动画系统:Legacy Animation系统和Mecanim系统。前者适用于简单的线性动画播放,而后者(通过Animator组件实现)则是目前主流的动画状态机解决方案。
我最早接触Unity动画是在2014年开发一款横版跑酷游戏时,当时被Animator Controller的状态转换逻辑深深吸引。经过这些年的项目积累,我发现90%的动画相关问题都源于对基础概念理解不透彻。本文将基于5个商业项目实战经验,带你系统掌握这两套系统的使用精髓。
在Hierarchy中选中需要添加动画的GameObject,通过Component > Miscellaneous > Animation添加基础动画组件。关键属性解析:
csharp复制// 典型的基础播放代码
GetComponent<Animation>().Play("run");
注意:Legacy系统使用的动画文件扩展名为.anim,不同于Mecanim的.controller文件
动画混合(Blend)是解决动作过渡生硬的关键技术。通过Animation.Blend()方法可以实现:
csharp复制// 将walk动画在0.3秒内淡出
GetComponent<Animation>().Blend("walk", 0, 0.3f);
// 同时让run动画在0.5秒内淡入
GetComponent<Animation>().Blend("run", 1, 0.5f);
实测发现混合时间控制在0.2-0.5秒效果最佳。太短会导致抽搐,太长会产生"滑步"现象。
在Animation窗口添加事件标记后,需要在脚本中实现对应方法:
csharp复制void FootStepSound() {
// 脚步声处理逻辑
audioSource.PlayOneShot(footstepClip);
}
常见问题排查:
专业建议:建议按"角色类型_动作类型"命名控制器,如"Player_Combat.controller"
根据项目经验,优秀的状态机应符合:
csharp复制// 典型的状态切换代码
animator.SetFloat("Speed", moveSpeed);
animator.SetBool("IsGrounded", isGrounded);
Animator支持的参数类型包括:
实测性能对比:
通过Layer Weight实现武器切换效果:
csharp复制// 第一层权重设为0时完全使用基础层动画
animator.SetLayerWeight(1, isAiming ? 1 : 0);
典型分层方案:
在Animation Clip中添加曲线可以实现:
提取曲线数据的方法:
csharp复制float curveValue = animator.GetFloat("WeaponSwingCurve");
实现不同体型模型共享动画的步骤:
常见问题解决方案:
使用Unity Profiler重点监控:
优化方案:
csharp复制// 设置动画更新模式
animator.updateMode = AnimatorUpdateMode.UnscaledTime;
问题1:动画播放卡顿
问题2:过渡不自然
问题3:Root Motion异常
完整的状态机应包含:
csharp复制// 典型移动控制代码
float moveSpeed = Mathf.Clamp(velocity.magnitude, 0, 1);
animator.SetFloat("MoveSpeed", moveSpeed, 0.1f, Time.deltaTime);
实现攀爬系统的关键步骤:
csharp复制void OnAnimatorIK(int layerIndex) {
if (isClimbing) {
animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandTarget);
animator.SetIKWeight(AvatarIKGoal.LeftHand, 1);
}
}
在最近开发的MMO项目中,通过优化动画状态机层级,我们将主角的Animator.Update耗时从2.3ms降低到了0.7ms。关键是把20多个Bool参数重构为3个Float参数,并用Sub-State Machine组织相似状态。