Animator 動畫依腳步狀態切換

Animator 動畫依腳步狀態切換

在制作 Animator 狀態機時候, 經常需要到判斷現在人型的左右腳的位置.
為甚麼要算出當下的腿部情況?
那是因為 Animation Blending 的處理.
以下圖作示意, 左圖是正在跑的情況, 右圖是我們有的起跳動畫.
留意左右腿是剛好相反的, 那麼在 Animator 需要切換動畫 (Blending) 的時候就會有一段很快的腿腳交換的動作.
在大形遊戲製作中是屬於 glitch 的存在.

由於 Untiy3D 沒有幫忙算 foot phase 也沒有任何 AI 輔助, 所以轉時只能自己把動畫都分成 左右兩種的情況然後再接駁好
(辛苦的工作……)

以往用 Unity3D 最初寫好的 LegCycle (依影片時間估算)勉強充當一個指標, 可是經常出差錯.
所以決定自己用三維來算一個.

public class LegCycleSMB : StateMachineBehaviour
{
	[Header("Animator")]
	[SerializeField] string LegCycle = "LegCycle";
	[Tooltip("Damping time for switching leg")]
	[Range(0f, 1f)] public float m_LegCycleDampTime = .3f;

	private Transform m_LeftFoot = null;
	private Transform m_RightFoot = null;
	private Transform m_Root = null;

	public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex, AnimatorControllerPlayable controller)
	=> FetchBone(animator);
	public override void OnStateMachineEnter(Animator animator, int stateMachinePathHash, AnimatorControllerPlayable controller)
	=> FetchBone(animator);
	private void FetchBone(Animator animator)
	{
		if (ReferenceEquals(null, m_Root))
		{
			m_Root = animator.transform;
			m_LeftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
			m_RightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
		}
	}

	public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
	{
		// 以 m_Root 取得左右腳在 Local space 的三維坐標.
		Vector3 left = m_Root.InverseTransformPoint(m_LeftFoot.position);
		Vector3 right = m_Root.InverseTransformPoint(m_RightFoot.position);
		// 由左 -> 右足構成 vector
		Vector3 vector = right - left;
		vector.y = 0f;
		// 用人物的正前方及該 vector 算出 vector dot, 來判斷前後足.
		float dot = Vector3.Dot(vector.normalized, Vector3.forward);

		// Because usually within -0.7~0.7 range.
		float bias = Mathf.Clamp(dot * 2f, -1f, 1f);

		// 左足在前以 -1 表示,
		// 右足在前以 1 表示.
		animator.SetFloat(LegCycle, bias, m_LegCycleDampTime, Time.deltaTime);
	}
}

重點在於 OnStateUpdate() 裡面.
直接以 m_Root 取得左右腳在 Local space 的三維坐標. 算出向量並投影到地面 (取消 Y 軸),
並以之與正前方用 Vector dot 進行比較來取值.

參考 : https://docs.unity3d.com/2019.3/Documentation/Manual/UnderstandingVectorArithmetic.html
由此可以得知左右足, 那一只在人物身前方.

這邊我們加了一點 Bias, 因為腳在跑動時大部份時間只是在 -45~45 度的範圍活動 (對應身體中心點).
所以用一套簡單的數學加減一下取得 -1~1 的值方便運算.
之後就回到 Animator 為不同的 state 設定好左右腳的 Blending 的情況.

AnimatorBlendLR

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料