【原文參考】http://blog.csdn.net/neil3d/article/details/41724705
動畫將控制RootBone對象的座標、旋轉、比例等,不合適的稱爲根運動吧
此腳本,就是將RootBone對象的座標、旋轉、比例等映射到父對象上,產生根運動的效果,不會出現感覺滑幀的情況出現
legacy參考腳本:
using UnityEngine;
using System.Collections;
public class ApplyRootMotion : MonoBehaviour
{
//-- Root Motion 控制變量
public Transform m_rootBone;
Vector3 m_lastRootPos;
Vector3 m_rootMotion;
int m_lastAnimTime;
Vector3 m_lastRootRot;
Vector3 m_rootRot;
void Start ()
{
//-- 從SkinnedMeshRenderer中讀取Root Bone
SkinnedMeshRenderer skinMesh = this.gameObject.GetComponentInChildren<SkinnedMeshRenderer>();
m_rootBone = skinMesh.rootBone;
//-- 變量初始化
m_rootMotion = Vector3.zero;
m_lastRootPos = m_rootBone.localPosition;
m_rootRot = Vector3.zero;
m_lastRootRot = m_rootBone.localRotation.eulerAngles;
m_lastAnimTime = 0;
}
void Update ()
{
//-- Apply Root Motion
Vector3 nextPos = this.transform.position + m_rootMotion;
this.transform.position = nextPos;
this.transform.rotation = Quaternion.Euler(this.transform.rotation.eulerAngles + m_rootRot);
//-- 測試代碼:更新攝像機
Camera.main.transform.LookAt(this.transform);
}
void LateUpdate()
{
AnimationState animState = this.animation["walking"];
print((int)animState.normalizedTime +" : "+m_lastAnimTime);
if ((int)animState.normalizedTime > m_lastAnimTime)
{
//-- 動畫循環處理
m_lastRootPos = m_rootBone.localPosition;
print(m_lastRootPos);
m_lastRootRot = m_rootBone.localRotation.eulerAngles;
}
else
{
//-- 計算當前幀的Root Motion
Vector3 rootPos = m_rootBone.localPosition;
m_rootMotion = rootPos - m_lastRootPos;
m_lastRootPos = rootPos;
Vector3 rootRot = m_rootBone.localRotation.eulerAngles;
m_rootRot = rootRot - m_lastRootRot;
m_lastRootRot = rootRot;
}
m_rootBone.localPosition = Vector3.zero;
m_rootBone.localRotation = Quaternion.Euler(Vector3.zero);
m_lastAnimTime = (int)animState.normalizedTime;
}
}
mecanim參考程序:
using UnityEngine;
using System.Collections;
public class AnimatorTest_2 : MonoBehaviour
{
public Transform _rortBone;
private Vector3 _startRootRot,_startRootRot2;
private Vector3 _motionRootRot;
private Animator _animator;
private AnimatorStateInfo _animStateInfo;
void Start()
{
_animator = GetComponent<Animator>();
_startRootRot2 = _startRootRot = _rortBone.rotation.eulerAngles;
_motionRootRot = Vector3.zero;
}
void Update()
{
_animStateInfo = _animator.GetCurrentAnimatorStateInfo(0);
AnimatorRecover();
if(_animStateInfo.IsName("Base Layer.Idle"))
{
if(Input.GetKeyDown(KeyCode.A))
{
_animator.SetBool("IdleToLeft",true);
}
else if(Input.GetKeyDown(KeyCode.D))
{
_animator.SetBool("IdleToRight",true);
}
}
if(_animStateInfo.IsName("Base Layer.TurnLeft") || _animStateInfo.IsName("Base Layer.TurnRight"))
{
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + _motionRootRot) ;
}
}
void LateUpdate()
{
if(_animStateInfo.IsName("Base Layer.TurnLeft") || _animStateInfo.IsName("Base Layer.TurnRight"))
{
print(_animStateInfo.normalizedTime);
if(_animStateInfo.normalizedTime < 0.98f)
{
Vector3 _rootPos = _rortBone.localRotation.eulerAngles;
_motionRootRot = _rootPos - _startRootRot;
_startRootRot = _rootPos;
}
else
{
_motionRootRot = Vector3.zero;
_startRootRot = _startRootRot2;
}
_rortBone.localRotation = Quaternion.Euler(Vector3.zero);
}
}
void AnimatorRecover()
{
if(!_animStateInfo.IsName("Base Layer.Idle"))
{
_animator.SetBool("IdleToRight",false);
_animator.SetBool("IdleToLeft",false);
}
}
}