Mecanim動畫系統(三)


一、初識Blend Trees(混合樹)

●  混合樹 用於兩個或多個類似動畫的融合。如從walk到run的速度的變化,或在奔跑的時候向左、向右的傾斜角度。

● 2D Simple Directional(簡單的定向): 表示在二維每個空間方向只能有一個動作
  適用於當你的動作片段代表不同方向時,如“向前行走”、“向后行走”、“向左行走”和“向右行走”或是“向上瞄准”、“向下瞄准”、“向左瞄准”和“向右瞄准”。選一個基礎動作放在位置 (0, 0) 處,如 “idle” 和“aim straight”等。在簡單方向 (Simple Directional) 類型中,相同方向上不應存在多個運動,如“向前行走”和“向前奔跑”。
● 2D Freeform Directional(自由的定向): 表示在二維每個空間方向可以有多個動作
  這種類型同樣用於當你的動作片段代表不同方向時使用,但是你可以在相同方向上具有多個動作,例如“向前行走”和“向前奔跑”。在任意方向 (Freeform Directional) 類型中,在該類型中應設置一個動作在位置 (0, 0)處,如“idle”。
● 2D Freeform Cartesian(自由的坐標):
  適用於你的動作中不需要代表不同方向時。如你要做的游戲中包括“向前行走不轉彎”、“向前奔跑不轉彎”、同時可以“向前行走並右轉”、“向前奔跑並右轉”等運動時,使用這種類型。

 Direct:能夠精准的控制每個動畫所占的權重(每個動畫占用一個不同的float值)。如下圖:

● Automate Threshold: 自動化闕值(闕值:臨界值)

1、1D 混合樹

 

● Parameter: 參數類型

● Thresholds:闕值。當“Blend Tree”的數值達到某個動畫的闕值時,則完全播放該動畫

● 在“1D 混合樹”中用代碼實現walk到run的過度

        //按下W、S鍵實現"WalkRun"參數由-1到1的動態變化
        float y = Input.GetAxis("Vertical"); _animator.SetFloat("WalkRun", y);

2、2D 混合樹

● 2D Freeform Cartesian

        //按下W、S、A、D鍵實現行走動畫的過度
        float x = Input.GetAxis("Horizontal"); float y = Input.GetAxis("Vertical"); _animator.SetFloat("h", x); _animator.SetFloat("v", y);

二、Mecanim動畫系統的簡單應用

1、遮罩(用於兩種動畫的不同部位同時播放,如邊奔跑邊射擊等)

● Weight:權重。基礎層的權重為默認

● Mask : 遮罩

● Blending:該層動畫與其他層動畫的混合方式,包括Override(復寫方式,即取不同層動畫的中間值)和additive(直接疊加)。

● Sync:同步。同步是本層動畫直接同步其他層動畫狀態之間的邏輯狀態,一般需要選取同步源。同步之后需要給本層的動畫狀態添加動畫剪輯。

● IK Pass:即本層動畫是否支持IK動畫。

1)在Layers中新建一個圖層“Layer_attack”,調整權重(Weight)、添加動畫。

2)右鍵新建一個Avatar Mask遮罩並調節Humanoid屬性,然后在Mask圖層中添加遮罩。新建Avatar Mask如下圖:

3)可以在Blending屬性中將Override改為additive(直接疊加),得到不同的效果

 2、動畫重定向

1、直接將建好的Animator Controller賦給角色模型
2、在Project視圖中右鍵新建一個Animator Override Controller然后將Animator Controller賦給他。方法二的好處是可以將“Animator Controller”重新命名便於區分。
注意:需要注意Avatar下面有沒有Configure Avatar選項,如果沒有則需要重新設置Animation Type和Avatar Definition。否則無法進行動畫重定向。如下圖

 

 3、IK

  IK(Inverse Kinematics)即反向動力學,即可以使用場景中的各種物體來控制和影響角色身體部位的運動,一般來說骨骼動畫都是傳統的從父節點到子節點的帶動方式(即正向動力學),而IK則倒過來,由骨骼子節點帶動骨骼父節點。(插件:FinalIK)

using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary>
/// 在Animator Controller添加一個idle /// 在Hierarchy窗口創建一個游戲物體給角色用 /// 開啟IK Pass,綁定腳本即可 /// </summary>
public class IKController : MonoBehaviour { //聲明
 Animator _animator; public Transform lookAtObj = null; public Transform rightHandObj = null; void Start() { _animator = GetComponent<Animator>(); } void OnAnimatorIK() { if (_animator) { if (lookAtObj != null) { _animator.SetLookAtWeight(1);//設置權重
 _animator.SetLookAtPosition(lookAtObj.position); } else _animator.SetLookAtWeight(0); if (rightHandObj != null) { //“AvatarIKGoal.RightHand”右手的權重為1
                _animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1); _animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1); //右手的位置和旋轉角度
 _animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position); _animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation); } else { _animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 0); _animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0); } } } }

4、用代碼觸發開門動畫

 1)選中門利用Unity創建一個簡單的開門動畫;

 2)在Project視圖創建一個Animation動畫(靜態的)作為默認動畫;

 3)連接如下圖:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private AudioSource _audioSource;
    private Animator _animation;
    void FixedUpdate()
    {
        Move();
    }
    void Move()
    {
        //角色移動
        //運行時需要在"Rigidbody"組件上設置constraints(軸約束),否則角色膠囊無法保持平衡
        transform.Translate(0, 0, Input.GetAxis("Vertical") * Time.deltaTime * 5);
        transform.Rotate(0, Input.GetAxis("Horizontal") * Time.deltaTime * 50, 0);
    }
    void OnTriggerEnter(Collider other)
    {
        //使用OnTrigger方法必須在游戲物體或者角色上開啟“Is Trigger”
        //如果觸發標簽為"door"的游戲對象,則播放聲音及開門動畫
        //如果獲取組件不添加“other”,則默認獲取的是當前綁定腳本的游戲對象
        if (other.tag == "door")
        {
            _audioSource = other.GetComponent<AudioSource>();
            _audioSource.Play();
            _animation = other.GetComponent<Animator>();
            _animation.SetTrigger("door1");
        }
    }
    void OnTriggerExit(Collider other)
    {
        if (other.tag == "door")
        {
            _audioSource = other.GetComponent<AudioSource>();
            _audioSource.Play();
            _animation.SetTrigger("door0");
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM