• Unity5.x 动画系统
    • ● 自定义编辑器

    Unity5.x 动画系统

     16.3 Unity5.X 动作系统  - 图1

    首先,我们发现的是3个默认的状态,这些状态是Unity自动帮我们创建的同时也无法删除:

    1. Entry:表示当进入当前状态机时的入口,该状态连接的状态会成为进入状态机后的第一个状态;
    2. Any State:表示任意的状态,其作用是其指向的状态是在任意时刻都可以切换过去的状态;
    3. Exit:表示退出当前的状态机,如果有任意状态指向该出口,表示可以从指定状态退出当前的状态机;

    ● Has Exit Time

     16.3 Unity5.X 动作系统  - 图2

    如果我们勾选了该项,在动画转换时会等待当前动画播放完毕才会转换到下一个动画,如果当前动画是循环动画会等待本次播放完毕时转换,所以对于需要立即转换动画的情况时记得要取消勾选。

    还有一种情况时,当我当前的动画播放完毕后就自动转换到箭头所指的下一个状态(没有其他跳转条件),此时必须勾选该选项,否则动画播放完毕后就会卡在最后一帧,如果是循环动画就会一直循环播放。

    1. 新的BlendTree
    2. Direct
    3. 多个动作可以同时播放
    4. 适用于做面部表情
    5. 可以通过参数控制不同动作片段的权重

    ● 常用API(需要继承StateMachineBehaviour):

     16.3 Unity5.X 动作系统  - 图3

     16.3 Unity5.X 动作系统  - 图4

    在新的动画系统中,连线变得简单明了,每增加一个动画,就像下面一样连起来就是了。至于脚本的编写,只需点击图中的任意一个动画状态,然后在Inspector面板中点击Add Behaviour,即可为该动画状态编写脚本。这里我建了一个int变量控制整个状态机的状态变换,在右边的5个退出条件中,全部取消掉Has Exit Time(退出时间改为用脚本控制)。

    需要注意的是,不要在Awake中使用Animator.GetBehaviour。

     16.3 Unity5.X 动作系统  - 图5

    1. using UnityEngine;
    2. using System.Collections;
    3. public class Idle : StateMachineBehaviour {
    4. override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    5. {
    6. if (Input.GetKeyDown(KeyCode.H))
    7. animator.SetInteger("state", (int)CharacterState.Attack1);
    8. if ((Input.GetAxisRaw("Horizontal") != 0) || (Input.GetAxisRaw("Vertical") != 0))
    9. animator.SetInteger("state", (int)CharacterState.Run);
    10. }
    11. }
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Attack1 : StateMachineBehaviour {
    4. override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    5. {
    6. if (Input.GetKeyDown(KeyCode.H) && (stateInfo.normalizedTime > 0.5f))
    7. animator.SetInteger("state", (int)CharacterState.Attack2);
    8. if(stateInfo.normalizedTime > 0.9f)
    9. animator.SetInteger("state", (int)CharacterState.Idle);
    10. }
    11. }
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Attack2 : StateMachineBehaviour {
    4. override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    5. {
    6. if (Input.GetKeyDown(KeyCode.H) && (stateInfo.normalizedTime > 0.5f))
    7. animator.SetInteger("state", (int)CharacterState.Attack3);
    8. if (stateInfo.normalizedTime > 0.9f)
    9. animator.SetInteger("state", (int)CharacterState.Idle);
    10. }
    11. }
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Attack3 : StateMachineBehaviour {
    4. override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    5. {
    6. if (stateInfo.normalizedTime > 0.7f)
    7. animator.SetInteger("state", (int)CharacterState.Idle);
    8. }
    9. }
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Run : StateMachineBehaviour {
    4. override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    5. {
    6. if ((Input.GetAxisRaw("Horizontal") == 0) && (Input.GetAxisRaw("Vertical") == 0))
    7. animator.SetInteger("state", (int)CharacterState.Idle);
    8. }
    9. }

    ● 自定义编辑器

    另外,可以用代码来创建AnimatorController。

    1. using UnityEngine;
    2. using UnityEditor;
    3. using UnityEditor.Animations;
    4. public class CreateController : EditorWindow {
    5. [MenuItem("Window/CreateController")]
    6. static void Create()
    7. {
    8. // Creates the controller
    9. var controller = AnimatorController.CreateAnimatorControllerAtPath ("Assets/StateMachineTransitions.controller");
    10. // Add parameters
    11. controller.AddParameter("TransitionNow", AnimatorControllerParameterType.Trigger);
    12. controller.AddParameter("Reset", AnimatorControllerParameterType.Trigger);
    13. controller.AddParameter("GotoB1", AnimatorControllerParameterType.Trigger);
    14. controller.AddParameter("GotoC", AnimatorControllerParameterType.Trigger);
    15. // Add StateMachines
    16. var rootStateMachine = controller.layers[0].stateMachine;
    17. var stateMachineA = rootStateMachine.AddStateMachine("smA");
    18. var stateMachineB = rootStateMachine.AddStateMachine("smB");
    19. var stateMachineC = stateMachineB.AddStateMachine("smC");
    20. // Add States
    21. var stateA1 = stateMachineA.AddState("stateA1");
    22. var stateB1 = stateMachineB.AddState("stateB1");
    23. var stateB2 = stateMachineB.AddState("stateB2");
    24. stateMachineC.AddState("stateC1");
    25. var stateC2 = stateMachineC.AddState("stateC2"); // don’t add an entry transition, should entry to state by default
    26. // Add Transitions
    27. var exitTransition = stateA1.AddExitTransition();
    28. exitTransition.AddCondition(AnimatorConditionMode.If, 0, "TransitionNow");
    29. exitTransition.duration = 0;
    30. var resetTransition = stateMachineA.AddAnyStateTransition(stateA1);
    31. resetTransition.AddCondition(AnimatorConditionMode.If, 0, "Reset");
    32. resetTransition.duration = 0;
    33. var transitionB1 = stateMachineB.AddEntryTransition(stateB1);
    34. transitionB1.AddCondition(AnimatorConditionMode.If, 0, "GotoB1");
    35. stateMachineB.AddEntryTransition(stateB2);
    36. stateMachineC.defaultState = stateC2;
    37. var exitTransitionC2 = stateC2.AddExitTransition();
    38. exitTransitionC2.AddCondition(AnimatorConditionMode.If, 0, "TransitionNow");
    39. exitTransitionC2.duration = 0;
    40. var stateMachineTransition = rootStateMachine.AddStateMachineTransition(stateMachineA, stateMachineC);
    41. stateMachineTransition.AddCondition(AnimatorConditionMode.If, 0, "GotoC");
    42. rootStateMachine.AddStateMachineTransition(stateMachineA, stateMachineB);
    43. }
    44. }

    ?