Unity 5.0 中酷炫的新动画功能详解
Unity 动画团队齐心协力、不懈努力,为 Unity 5.0 打造了令人印象深刻的功能集。本文将为您简要概述这些新动画功能,希望能对 Unity 用户有所帮助。
状态机行为
在 Unity 5 中,您可以将 StateMachineBehaviour 脚本添加到状态中。当状态播放时,您会收到以下回调:
OnStateEnterOnStateUpdateOnStateExitOnStateMoveOnStateIK
您可以根据需求在“状态”中添加多个 StateMachineBehaviour。若要在“状态”上添加 IK 或执行自定义逻辑,只需将 StateMachineBehaviour 脚本拖到该状态上即可。
基本上,游戏中任何需要某种状态机(StateMachine)逻辑的对象,无论是否有动画,都可以使用这种方式。
这一功能的一大优势在于,您无需编写大量类似如下的代码:
if(animator.GetCurrentAnimatorStateInfo(0).IsName("Idle"))
DoStuff();
(相信您的代码中存在不少这样的代码),使用 StateMachineBehaviour 就能轻松解决问题。
状态机转换
随着状态机变得日益复杂,我们引入了“状态机转换”的概念,旨在为状态机(StateMachine)逻辑提供更高层次的抽象表示。
在 Unity 5 中,我们在状态机(StateMachine)中添加了“进入”和“退出”节点,这两种节点都会在状态机转换中发挥作用。
- 进入:当您转换到状态机(StateMachine)时,动画系统会评估“进入”节点,并转到条件满足的目的地。
- 退出:当转到“退出”节点时,动画系统会查看正在进行的状态机转换,并转到合适的目的地。
需要注意的是,您可以进行混合转换,例如:状态(State) -> 状态(State)、状态(State) -> 状态机(StateMachine)、状态机(StateMachine) -> 状态机(StateMachine)等。
此外,我们还对工具的用户界面(UI)进行了修改,现在您可以对参数和层进行重新排序。
资源创建 API
在 Unity 5 中,您可以使用编辑器中的脚本创建动画资源,如状态机(StateMachine)、状态(State)、控制器(Controller)、图层(Layer)、混合树(BlendTree)等。
这里有两种 API 可供使用:
- 高级 API:由 Unity 负责管理资源。
- 低级 API:您可以手动管理资源,并进行外部引用。
这两种 API 都有相关文档记录,在本文结尾处,我会提供一个使用 API 的小示例。
直接混合树
我们新增了一种新型的混合树(BlendTree),您可以将动画器参数直接映射到混合树子级的权重上。如果您正在使用 BlendShape 动画或附加动画,这种功能会非常实用。
根动作创作(常规模式下)
Unity 5 允许您为动画制作动画效果,并将它们的动画器转化为根动作(即 Delta Animation)。您只需在对象的最顶层转换上创建动画(平移/旋转),然后在动画剪辑(AnimationClip)检查器中单击“Generate Root Motion Curve”(生成根动作曲线)即可。
更多功能,让动画制作更轻松
- 改进的动画预览器相机:该相机现在具备像场景查看器一样的摇镜头、沿轨道运行和缩放功能。
- 对参数的运行时访问:您可以在运行时访问参数的名称、默认值等信息。
- 场景视图中的小工具(Gizmo):可以在场景视图中显示根位置、IK 位置等信息。
- 改进的重新定位目标引擎:提升了重新定位目标的性能。
- 运行时优化:优化了动画在运行时的性能。
- 大量的漏洞修复:修复了许多已知的动画相关漏洞。
资源创建 API 示例代码
// 创建控制器
var controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/Mecanim/StateMachineTransitions.controller");
// 添加参数
controller.AddParameter("TransitionNow", UnityEditor.Animations.AnimatorControllerParameterType.Trigger);
controller.AddParameter("Reset", UnityEditor.Animations.AnimatorControllerParameterType.Trigger);
controller.AddParameter("GotoB1", UnityEditor.Animations.AnimatorControllerParameterType.Trigger);
controller.AddParameter("GotoC", UnityEditor.Animations.AnimatorControllerParameterType.Trigger);
// 添加状态机
var rootStateMachine = controller.layers[0].stateMachine;
var stateMachineA = rootStateMachine.AddStateMachine("smA");
var stateMachineB = rootStateMachine.AddStateMachine("smB");
var stateMachineC = stateMachineB.AddStateMachine("smC");
// 添加状态
var stateA1 = stateMachineA.AddState("stateA1");
var stateB1 = stateMachineB.AddState("stateB1");
var stateB2 = stateMachineB.AddState("stateB2");
stateMachineC.AddState("stateC1");
var stateC2 = stateMachineC.AddState("stateC2"); // 不添加进入转换,默认进入该状态
// 添加转换
var exitTransition = stateA1.AddExitTransition();
exitTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "TransitionNow");
exitTransition.duration = 0;
var resetTransition = stateMachineA.AddAnyStateTransition(stateA1);
resetTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "Reset");
resetTransition.duration = 0;
var transitionB1 = stateMachineB.AddEntryTransition(stateB1);
transitionB1.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "GotoB1");
stateMachineB.AddEntryTransition(stateB2);
stateMachineC.defaultState = stateC2;
var exitTransitionC2 = stateC2.AddExitTransition();
exitTransitionC2.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "TransitionNow");
exitTransitionC2.duration = 0;
var stateMachineTransition = rootStateMachine.AddStateMachineTransition(stateMachineA, stateMachineC);
stateMachineTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "GotoC");
rootStateMachine.AddStateMachineTransition(stateMachineA, stateMachineB);