我们在Animator Controller中除了可以创建一个State外还可以创建一个Blend Tree,如下:
那么我们看下新创建的Blend Tree和State有什么区别:
唯一的区别就是Montion指向的类型变成了Blend Tree类型,那么一个Blend Tree其实也就是一个状态,和状态不同的地方就是一个状态只能设定一个动画,而一个Blend Tree则可以设定为多个动画的混合。
混合树是Mecanim动画系统中比较复杂的一个内容,且其分为多个维度,下面我们逐个的来进行学习。
一维混合树
我们以官方的例子使用一维混合树来实现下面的效果:我们人物的跑动分为3个动画,分别是向前跑、向左跑和向右跑,其中向左跑和向右跑人物都会有一定的倾斜,这样更加符合现实的情况,那么我们在状态机中跑动只有一个状态,所以我们的跑动需要设置为混合树来混合这3个动画。
首先我们需要创建一个新的场景,拖入我们的人物模型,然后创建一个Animator Controller并对其进行配置:
注意我们的Run是Blend Tree而不是State,双击Run就可以进入混合树的编辑界面。
右击我们的混合树添加3个Motion,如下:
同时我们设定好3个方向的跑动动画:
我们还需要设定一个名为Direction的Float类型的参数来控制这个混合树:
接下来我们取消Automate Thresholds的选项,并按下图进行选择,系统会为我们配置好阀值:
现在我们点击预览框查看动画播放时就可以通过拖拽小红线来看不同的变化了,我们的可使用的角度范围为-130到130之间。
到现在我们的动画控制器就配置好了。
脚本
下面我们使用脚本来控制一下人物,我们给人物添加下面的脚本即可:
1 using UnityEngine; 2 using System.Collections; 3 4 public class TestBlendTree : MonoBehaviour 5 { 6public float DirectionDampTime = 30.0f; 7 8private Animator _animator; 9 10void Start()11{12 _animator = this.GetComponent<Animator>();13}1415void Update()16{17 if(Input.GetKeyDown(KeyCode.W))18 {19 _animator.SetBool("run", true);20 }21 if(Input.GetKeyUp(KeyCode.W))22 {23 _animator.SetBool("run", false);24 }25 26 AnimatorStateInfo state = _animator.GetCurrentAnimatorStateInfo(0);27 //奔跑状态下才允许转弯28 if(state.shortNameHash == Animator.StringToHash("Run"))29 {30 //指定人物转弯通过控制混合数的参数即可31 float h = Input.GetAxis("Horizontal") * 130.0f;32 //DirectionDampTime 指示了每秒可以到达的最大值33 //deltaTime 表示当前帧的时间34 _animator.SetFloat("Direction", h, DirectionDampTime, Time.deltaTime);35 }36 else37 {38 //重置一下参数39 _animator.SetFloat("Direction", 0);40 }41}42 }
为了让摄像机跟随人物,我们直接添加官方给出的这个脚本到摄像机上即可:
1 using UnityEngine; 2 using System.Collections; 3 4 public class ThirdPersonCamera : MonoBehaviour 5 { 6public float distanceAway; // distance from the back of the craft 7public float distanceUp; // distance above the craft 8public float smooth;// how smooth the camera movement is 910private GameObject hovercraft; // to store the hovercraft11private Vector3 targetPosition; // the position the camera is trying to be in1213Transform follow;1415void Start(){16 follow = GameObject.FindWithTag ("Player").transform; 17}1819void LateUpdate ()20{21 // setting the target position to be the correct offset from the hovercraft22 targetPosition = follow.position + Vector3.up * distanceUp - follow.forward * distanceAway;23 24 // making a smooth transition between it's current position and the position it wants to be in25 transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smooth);26 27 // make sure the camera is looking the right way!28 transform.LookAt(follow);29}30 }
记得将人物的Tag设置为Player,同时脚本也要设置一下:
动画方面的一点要求
每个混合树的动画有一些要注意的地方:
动画长度需要一致;动画的起始姿势需要一致;
二维混合树
同1维混合树,不过二维混合树已经作为一个平面来处理,同时需要两个参数来进行控制。对于更复杂的动画融合可以使用该模式,这里就不深入学习了。
我们可以将两个1维混合树合并为一个2维混合树来控制。
实现的效果:人物在跑的状态下,才能进行转弯操作,和跳起动作。
1: unity中的动画混合树可以将几个动画文件很好的融合在一起其中Run是状态树:
参数Direction是浮点类型。上面概述为:动画状态可以是单个的动画文件,也可以是由动画文件融合成的状态树。勾选automate threshold可以修改thresl临界值
2:第一步已经在unity面板中把先关参数配置好了,现在就需要用脚本来设置相关参数条件的实现。
[csharp]view plain copy usingUnityEngine;usingSystem.Collections;publicclassBlendTree:MonoBehaviour{protectedAnimatoranimator;publicfloatDirectionDamoTime=0.25f;voidStart(){animator=GetComponent<Animator>();}voidUpdate(){if(animator){AnimatorStateInfostateInfo=animator.GetCurrentAnimatorStateInfo(0);if(stateInfo.IsName("BaseLayer.Run"))//注意这里必须是BaseLayer.RunBaseLayer是动画层的名称,用.的形式引出当前准备切换动画的动画状态名称{if(Input.GetKeyDown(KeyCode.Space))animator.SetBool("Jump",true);}else{animator.SetBool("Jump",false);}//在奔跑时才可以水平旋转floathorizontal=Input.GetAxis("Horizontal");animator.SetFloat("Direction",horizontal,DirectionDamoTime,Time.deltaTime);//控制idle到跑状态的切换if(Input.GetKeyDown(KeyCode.W)){animator.SetFloat("Blend",1.0f);}elseif(Input.GetKeyUp(KeyCode.W)){animator.SetFloat("Blend",-0.1f);}}}}