标签:animation unity animator mecanimcontrol
使用Mecanim动画系统有时会遇到大量转换连线导致状态图特别复杂杂乱。这时很多人希望能像旧的动画系统Animation那样用Play()函数来控制动画。Mecanim Control正式解决这问题的方案。
获取MecanimControl插件。官网购买地址https://www.assetstore.unity3d.com/en/#!/content/15156
新建Unity工程,导入MecanimControl。另下载并导入MecanimExampleScenes1.0作为动画测试资源。
任务:模拟一个人从站立待机开始->向前走动->跑->慢停->待机结束。
1、创建场景配置属性
在Raw Mocap Data资源目录下找到DefaultAvatar,拖到场景中。准备动画资源,默认的动画资源是一个完整合集,我们要挑出合适的剪辑成最终需要的。挑选Idle_Neutral_1,添加一个剪辑起始是75,结束150帧处,命名为Idle。然后按下表准备好动画剪辑。
描述 | 原始资源名 | 动画剪辑名 | 起始帧 | 结束帧 | Wrap |
待机 | Idle_Neutral_1 | Idle | 75 | 150 | Loop |
走动 | WalkFWD | Walk | 0 | 30 | Loop |
跑 | Run_Impulse | Run | 163 | 181 | Loop |
跑停 | Run_FastStop_Idle | RunStop | 83 | 161 | Once/Clamp |
走停 | WalkJump_ToLeft_R_1 | WalkStop | 440 | 474 | Once/Clamp |
添加MecanimControl脚本,配置好的动画剪辑加入Animations参数。Speed都设为1,WrapMode按表中配置。
到此基本准备好了,因动画走、跑等这些不是在原地走动,播放动画时会一直往前走。所以我们要采取措施修正走路前进动画。这里创建一个GameObject命名为Player,将DefaultAvatar拖入Player,Reset Transform的属性。给Player添加Rigidbody组件,勾掉Use Gravity。后面会用代码修正DefaultAvatar的LocalPostion的z值,这样便不会再有前进移动。
2、代码
新建cs脚本,命名为MecanimControlTest。代码思路通过W键来控制前进还是停止前进,这部分代码在FixedUpdate里。根据当前的运动状态来切换动画,这部分代码在Update里。真实开发中摆臂、跨步动作要拆分出先左还是先右才能连贯。用速度来控制动画状态的切换。
测试中发现一个问题,Walk、Run动画在连续循环后方向会发生偏移。为了方便测试在FixedUpdate中对LocaRotation做复位处理。以前在项目中也常常遇到使用Animtor时Position和Rotation一个周期后会产生偏移,重复循环后非常明显。网络上的方案是调整动画剪辑的Based Upon来解决,实际发现只有少部分能解决。哪位大大知道有效的解决方案欢迎交流。
下面附上MecanimControlTest.cs的代码。
using UnityEngine; using System.Collections; public class MecanimControlTest : MonoBehaviour { public Rigidbody body; // 赋值Player public MecanimControl mecanimControl; // 赋值 public float forwardForce = 3f; // 驱动力 public float brakeForce = 5f; // 制动力 public float runStartPoint = 3f; // 开始跑动的速度 public float maxForwardSpeed = 7f; // 最大速度 private bool mKeyDown; /// <summary> /// 行驶 /// </summary> private bool mDrive; /// <summary> /// 制动,运动行驶中松掉W键刹车。 /// </summary> private bool mBrake { get {return mDrive && !mKeyDown;} } private AnimState mCurrentAnimState = AnimState.Idle; public enum AnimState { Idle, Walk, Run, RunStop, WalkStop, } // Use this for initialization void Start() { mecanimControl.Play ("Idle"); } // Update is called once per frame void Update () { if ((mCurrentAnimState == AnimState.Idle || mCurrentAnimState == AnimState.WalkStop) && mKeyDown) { // idle/walkStop->walk mecanimControl.CrossFade("Walk", 0.2f); mCurrentAnimState = AnimState.Walk; } if ((mCurrentAnimState == AnimState.Walk || mCurrentAnimState == AnimState.RunStop) && body.velocity.magnitude >= runStartPoint && mKeyDown) { // walk/runStop->run mecanimControl.CrossFade("Run", 0.2f); mCurrentAnimState = AnimState.Run; } if (mBrake) { if (mCurrentAnimState == AnimState.Walk) { // walk->walkStop mecanimControl.CrossFade ("WalkStop", 0.2f); mCurrentAnimState = AnimState.WalkStop; } if (mCurrentAnimState == AnimState.Run) { // run->runStop mecanimControl.CrossFade ("RunStop", 0.2f); mCurrentAnimState = AnimState.RunStop; } } if (mCurrentAnimState != AnimState.Idle && !mDrive) { // walkStop/runStop->idle mecanimControl.CrossFade("Idle", 0.2f); mCurrentAnimState = AnimState.Idle; } } void FixedUpdate() { Vector3 pos = mecanimControl.transform.localPosition; pos.z = 0; mecanimControl.transform.localPosition = pos; mecanimControl.transform.localRotation = Quaternion.identity; mKeyDown = Input.GetKey (KeyCode.W); if (mKeyDown) { mDrive = true; if (body.velocity.magnitude > maxForwardSpeed) { body.velocity = Vector3.forward * maxForwardSpeed; } else { body.AddForce(Vector3.forward * forwardForce, ForceMode.Force); } } if (mBrake) { if (body.velocity.z <= 0.0001f) { body.velocity = Vector3.zero; mDrive = false; } else { body.AddForce(Vector3.back * brakeForce, ForceMode.Force); } } } }
工程超出上传限制移植资料里下载(资源上传后一直看不到下载链接,后面补上)。MecanimControl不是开源,项目中把它移除。下载工程测试前请先导入MecanimControl插件。
欢迎Unity爱好者加入QQ群255316030
本文出自 “Toto” 博客,请务必保留此出处http://visualparkzhao.blog.51cto.com/10059377/1631605
标签:animation unity animator mecanimcontrol
原文地址:http://visualparkzhao.blog.51cto.com/10059377/1631605