新mecanim动画系统_享受新的Mecanim功能

新mecanim动画系统_享受新的Mecanim功能

新mecanim动画系统

嗨! 几个月前, 我写了一篇关于 在Mecanim for Unity 5.0中添加 的新功能的文章 。 今天,我想向您展示一些使用我们的新功能可以完成的酷而简单的事情。 (Hi! A couple of months ago, I wrote a post about the new features we’ve added in Mecanim for Unity 5.0.  Today I want to show you some of the cool – and simple – stuff that you can do with our new features.)

随机节点 (Random Nodes)

Creating random “selector” nodes using StateMachineBehaviours in conjunction with the StateMachine entry node is really easy.

使用StateMachineBehaviours结合StateMachine入口节点创建随机的“选择器”节点非常容易。

The first thing you want to do is to add transitions from the Entry node to your states.

您要做的第一件事是添加从Entry节点到您的状态的过渡。

You will then need to assign each of those transitions an int condition.

然后,您需要为每个转换指定一个int条件。

Then you add a StateMachineBehaviour on your Idle StateMachine and implement OnStateMachineEnter like this:

然后,在空闲的StateMachine上添加StateMachineBehaviour并实现OnStateMachineEnter,如下所示:

1
2
3
4
5
6
override public void OnStateMachineEnter(Animator animator, int stateMachinePathHash)</pre>
{
animator.SetInt(“IdleIndex”, Random.Range(0, 4));
}
1
2
3
4
5
6
override public void OnStateMachineEnter ( Animator animator , int stateMachinePathHash ) < / pre >
{
animator . SetInt ( “ IdleIndex ” , Random . Range ( 0 , 4 ) ) ;
}

So now, every time you will enter the Idle StateMachine, a random State will be played.

因此,现在,每次您进入空闲状态机时,都会播放一个随机状态。

程序状态 (Procedural States)

In 5.0 we also did some improvements to our Humanoid IK solver and added what we call IKHints. This means that you will now have control on your IK chain roll! Using the StateMachineBehaviour’s OnStateIK callback you can have IK setups that are specific to your states. You can even go crazy and have fully procedural states. The following code will make your character dance!

在5.0中,我们还对Humanoid IK解算器进行了一些改进,并添加了所谓的IKHints。 这意味着您现在可以控制IK链条滚动了! 使用StateMachineBehaviour的OnStateIK回调,您可以具有特定于您的州的IK设置。 您甚至可以发疯并拥有完整的程序状态。 以下代码将使您的角色起舞!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{
// Do a sine based on the State normalized time
float normalizedTime = (1.0f + Mathf.Sin(Mathf.Repeat(stateInfo.normalizedTime, 1.0f) * Mathf.PI * 4)) * 0.5f;
// lower the body
animator.bodyPosition = animator.bodyPosition + new Vector3(0, -0.3f, 0);
// make hands move left and right based on sine
Vector3 leftHandPosition = animator.bodyPosition + new Vector3(-0.1f + normalizedTime * -0.2f, 0, 0.2f);
Vector3 rightHandPosition = animator.bodyPosition + new Vector3(0.1f + normalizedTime * 0.2f, 0, 0.2f);
// put elbow up
Vector3 leftElbowPosition = animator.bodyPosition + new Vector3(-5, 2, 0);
Vector3 rightElbowPosition = animator.bodyPosition + new Vector3(5, 2, 0);
animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandPosition);
animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandPosition);
// align knees to the hand
animator.SetIKHintPosition(AvatarIKHint.LeftKnee, leftHandPosition);
animator.SetIKHintPosition(AvatarIKHint.RightKnee, rightHandPosition);
animator.SetIKHintPosition(AvatarIKHint.LeftElbow, leftElbowPosition);
animator.SetIKHintPosition(AvatarIKHint.RightElbow, rightElbowPosition);
// activate everything. Could be done on start
animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1.0f);
animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1.0f);
animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1.0f);
animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1.0f);
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1.0f);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1.0f);
animator.SetIKHintPositionWeight(AvatarIKHint.LeftKnee, 1.0f);
animator.SetIKHintPositionWeight(AvatarIKHint.RightKnee, 1.0f);
animator.SetIKHintPositionWeight(AvatarIKHint.RightElbow, 1.0f);
animator.SetIKHintPositionWeight(AvatarIKHint.LeftElbow, 1.0f);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{
// Do a sine based on the State normalized time
float normalizedTime = ( 1.0f + Mathf . Sin ( Mathf . Repeat ( stateInfo . normalizedTime , 1.0f ) * Mathf . PI * 4 ) ) * 0.5f ;
// lower the body
animator . bodyPosition = animator . bodyPosition + new Vector3 ( 0 , - 0.3f , 0 ) ;
// make hands move left and right based on sine
Vector3 leftHandPosition = animator . bodyPosition + new Vector3 ( - 0.1f + normalizedTime * - 0.2f , 0 , 0.2f ) ;
Vector3 rightHandPosition = animator . bodyPosition + new Vector3 ( 0.1f + normalizedTime * 0.2f , 0 , 0.2f ) ;
// put elbow up
Vector3 leftElbowPosition = animator . bodyPosition + new Vector3 ( - 5 , 2 , 0 ) ;
Vector3 rightElbowPosition = animator . bodyPosition + new Vector3 ( 5 , 2 , 0 ) ;
animator . SetIKPosition ( AvatarIKGoal . LeftHand , leftHandPosition ) ;
animator . SetIKPosition ( AvatarIKGoal . RightHand , rightHandPosition ) ;
// align knees to the hand
animator . SetIKHintPosition ( AvatarIKHint . LeftKnee , leftHandPosition ) ;
animator . SetIKHintPosition ( AvatarIKHint . RightKnee , rightHandPosition ) ;
animator . SetIKHintPosition ( AvatarIKHint . LeftElbow , leftElbowPosition ) ;
animator . SetIKHintPosition ( AvatarIKHint . RightElbow , rightElbowPosition ) ;
// activate everything. Could be done on start
animator . SetIKPositionWeight ( AvatarIKGoal . LeftFoot , 1.0f ) ;
animator . SetIKRotationWeight ( AvatarIKGoal . LeftFoot , 1.0f ) ;
animator . SetIKPositionWeight ( AvatarIKGoal . RightFoot , 1.0f ) ;
animator . SetIKRotationWeight ( AvatarIKGoal . RightFoot , 1.0f ) ;
animator . SetIKPositionWeight ( AvatarIKGoal . LeftHand , 1.0f ) ;
animator . SetIKPositionWeight ( AvatarIKGoal . RightHand , 1.0f ) ;
animator . SetIKHintPositionWeight ( AvatarIKHint . LeftKnee , 1.0f ) ;
animator . SetIKHintPositionWeight ( AvatarIKHint . RightKnee , 1.0f ) ;
animator . SetIKHintPositionWeight ( AvatarIKHint . RightElbow , 1.0f ) ;
animator . SetIKHintPositionWeight ( AvatarIKHint . LeftElbow , 1.0f ) ;
}
新mecanim动画系统_享受新的Mecanim功能

Sweet dancing! Character by Mixamo

甜蜜的跳舞! Mixamo的角色

创建自己的工具 (Create your own tools)

Since we are exposing the API, you will be able to create all sorts of tools to create and edit Mecanim assets. When playing with 2D, I find it useful to use Blendtrees to do my navigation state. Since it uses sprite animation, I often need to redo the same steps over and over again for my different characters. Using the API, I created a simple EditorWindow: So I just need to drag in my sprite animations and the target object. Then I click create to get this: The code for the creation of the controller is as simple as it gets:

由于我们正在公开API,因此您将能够创建各种工具来创建和编辑Mecanim资产。 使用2D播放时,我发现使用Blendtrees进行导航状态很有用。 由于它使用了精灵动画,因此我经常需要为不同的角色重复执行相同的步骤。 使用API​​,我创建了一个简单的EditorWindow: 因此,我只需要拖动精灵动画和目标对象即可。 然后单击创建以获取此信息: 创建控制器的代码非常简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Creates the controller</pre>
UnityEditor.Animations.AnimatorController controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/" + target.name + ".controller");
// Adds 2 parameters
controller.AddParameter("VelX", UnityEngine.AnimatorControllerParameterType.Float);
controller.AddParameter("VelY", UnityEngine.AnimatorControllerParameterType.Float);
// Blend Tree creation
UnityEditor.Animations.BlendTree blendTree;
controller.CreateBlendTreeInController("Move", out blendTree);
// BlendTree setup
blendTree.blendType = UnityEditor.Animations.BlendTreeType.SimpleDirectional2D;
blendTree.blendParameter = "VelX";
blendTree.blendParameterY = "VelY";
for (int i = 0; i < animCount; ++i)
{
blendTree.AddChild(clips[i], DirectionToVector(directionValues[i]));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Creates the controller</pre>
UnityEditor . Animations . AnimatorController controller = UnityEditor . Animations . AnimatorController . CreateAnimatorControllerAtPath ( "Assets/" + target . name + ".controller" ) ;
// Adds 2 parameters
controller . AddParameter ( "VelX" , UnityEngine . AnimatorControllerParameterType . Float ) ;
controller . AddParameter ( "VelY" , UnityEngine . AnimatorControllerParameterType . Float ) ;
// Blend Tree creation
UnityEditor . Animations . BlendTree blendTree ;
controller . CreateBlendTreeInController ( "Move" , out blendTree ) ;
// BlendTree setup
blendTree . blendType = UnityEditor . Animations . BlendTreeType . SimpleDirectional2D ;
blendTree . blendParameter = "VelX" ;
blendTree . blendParameterY = "VelY" ;
for ( int i = 0 ; i < animCount ; ++ i )
{
blendTree . AddChild ( clips [ i ] , DirectionToVector ( directionValues [ i ] ) ) ;
}

到处都有StateMachines (StateMachines everywhere)

A nice thing with StateMachineBehaviours is that you can use StateMachines without animations. So anything in your game that requires some kind of StateMachine-esque logic can use our nice visual editor live feedback.

使用StateMachineBehaviours的好处是,您可以不使用动画而使用StateMachines。 因此,您游戏中任何需要某种类似于StateMachine逻辑的逻辑都可以使用我们出色的可视化编辑器实时反馈。

For example, a music StateMachine :

例如,音乐StateMachine:

A menu StateMachine

菜单StateMachine

很快,轮到您了! (Soon it will be your turn!)

I am hoping that these new features are getting you excited. We can’t wait to see what you guys will come up with!

我希望这些新功能使您兴奋。 我们迫不及待想看到你们会想出什么!

翻译自: https://blogs.unity3d.com/2015/02/11/having-fun-with-the-new-mecanim-features/

新mecanim动画系统