Unity3D學習筆記(十八):Animator新動畫
阿新 • • 發佈:2019-02-11
新節點 false 溝通 遍歷 模型生成 for in pan dha motion 新動畫系統:
給模型選擇動畫類型
普通動畫:Generic
人形動畫:Humanoid
建立動畫控制器 - 在Project右擊 - 選擇Create-AnimatorContorller
將對應動畫控制器拖入到Animator的Contorller
雙擊動畫控制器可以打開Animator窗口
將對應動畫片段拖入生成新節點,就可以編輯了
橙色節點:相當於舊動畫系統的默認片段
灰色節點:
Any State:代表所有動畫狀態
建立過渡條件
添加參數,有4種
通過代碼激活參數,實現動畫切換
默認過渡條件:Has Exit Time,播放完當前動畫才會進行到下一動畫的過渡
有條件,取消勾選
無條件,默認勾選,跳躍,浮空
給遊戲物體添加腳本,控制參數的激活
代碼不能越權:越過動畫狀態機設置的邏輯(動畫連線)的權限
設置默認片段
建立基礎連線
箭頭代表兩個動畫的過渡 Transition Duration:代表融合任何狀態都可以連線到death,甚至包括自己到自己
取消death過渡到自己的選擇 動畫鬼畜問題,自己過渡到自己
using System.Collections; using System.Collections.Generic; using UnityEngine; public class HellephantAnimator : MonoBehaviour { public Animator anim;用一個怪物管理器,管理兩個怪物的父類 兩種方法: 1、管理兩個怪物的父類 2、把方法寫成接口 父類:全部寫成虛函數// Use this for initialization void Start () { } // Update is called once per frame void Update () { if (Input.GetKeyDown(KeyCode.Alpha1)) { anim.SetBool("isMove", true); } if (Input.GetKeyDown(KeyCode.Alpha2)) { anim.SetBool("isMove", false); } if (Input.GetKeyDown(KeyCode.Alpha3)) { anim.SetTrigger("Death"); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public enum EnemySta { Move, Idle, Death } public class NewMonsterBase : MonoBehaviour { public PlayerControl moveTarget;//設置目標點 public MonsterManager manager;//怪物屬於那個管理器 public virtual void Action() { } public virtual void Move() { } public virtual void Idle() { } public virtual void Damage() { } public virtual void Death() { } public virtual void DeathEvent() { } }
這兩個需要初始化,要放在父類裏
public PlayerControl moveTarget;//設置目標點 public MonsterManager manager;//怪物屬於那個管理器
子類:繼承父類,並重寫父類方法
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class HellephantControl : NewMonsterBase { public Animator anim; public EnemySta enemySta; //因為我們需要經常用到目標的狀態,所以把TransForm改成了PlayerControl public NavMeshAgent navMeshAgent;//引用尋路系統 private int enemyHealth = 30;//設置怪物生命值 // Use this for initialization void Start()//子類添加新動畫系統 { enemySta = EnemySta.Move; anim.SetBool("isMove", true); } // Update is called once per frame void Update() { Action(); } public override void Action() { switch (enemySta) { case EnemySta.Move: Move(); break; case EnemySta.Idle: Idle(); break; case EnemySta.Death: Death(); break; } } public override void Move() { //anim.CrossFade("Move", 0.2f); navMeshAgent.SetDestination(moveTarget.transform.position); //如果怪物的目標死了 if (moveTarget.playSta == PlaySta.Death) { //尋路停止 navMeshAgent.isStopped = true; //狀態切換到閑置 enemySta = EnemySta.Idle; anim.SetBool("isMove", false); } } public override void Idle() { //anim.CrossFade("Idle", 0.2f); } public override void Damage() { //受傷減血 enemyHealth -= 10; //Debug.Log("怪物生命"+enemyHealth); //如果血到了0 if (enemyHealth <= 0) { //狀態變成死亡狀態 enemySta = EnemySta.Death; anim.SetTrigger("Death"); navMeshAgent.isStopped = true; gameObject.GetComponent<SphereCollider>().enabled = false; //gameObject.tag = "Untagged"; } } public override void Death()//子類關閉老動畫系統 { //anim.CrossFade("Death", 0.2f); } public override void DeathEvent() { //在管理器列表中移除自己 manager.monsterList.Remove(this); //銷毀自己 Destroy(this.gameObject); } }怪物管理器的怪物列表全部改成父類 怪物管理器的怪物生成 怪物預制體改成數組
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MounsterManager : MonoBehaviour { List<Transform> birthPoint; public GameObject[] monsterPreGo; //最大怪物數 public int MaxMonsterCount; public List<NewMonsterBase> monsterList; public NewPlayer player; // Use this for initialization void Start () { birthPoint = new List<Transform>(); monsterList = new List<NewMonsterBase>(); //遍歷所有的子物體,將其加到出生點列表中 for (int i = 0; i < transform.childCount; i++) { birthPoint.Add(transform.GetChild(i)); } } void CreateMonster() { monsterCont++; GameObject go; if (monsterCont%5==0) { go = Instantiate<GameObject>(monsterPreGo[1]); } else { //實例化一個怪物 go = Instantiate<GameObject>(monsterPreGo[0]); } //怪物的位置設置任意出生點 go.transform.position = birthPoint[Random.Range(0, birthPoint.Count)].position; //取得怪物腳本 NewMonsterBase monster = go.GetComponent<NewMonsterBase>(); //把怪物放到管理器列表裏 monsterList.Add(monster); //指定怪物的目標 monster.moveTarget = player; //指定怪物的管理者 monster.manager = this; } int monsterCont = 0; void CheckMonster() { if (monsterList.Count < MaxMonsterCount) { CreateMonster(); } } // Update is called once per frame void Update () { } private void FixedUpdate() { CheckMonster(); } }
怪物動畫添加死亡檢測事件 骨骼動畫鎖定:只允許動畫控制器修改 在動畫狀態機的設置裏,取消骨骼動畫鎖定
怪物添加碰撞體
新動畫系統的新功能 融合樹功能:一個和多個參數,來決定播放哪個動畫 更改動畫類型動畫和模型分開
拖拽模型生成預制體
添加動畫控制器
任意窗口最大化:shift+空格 中鍵拖動,滾輪縮放 動畫本身帶有位移動畫,根據實際情況決定 好處:過渡自然 壞處:代碼不可控,代碼強拉,會顯得不自然 勾選動畫自帶的位移動畫 建立三個動畫的融合樹 添加參數,保存鍵值,保證參數正確傳遞右鍵新建 融合樹
雙擊融合樹,打開融合樹窗口,右鍵可以再添加融合樹
添加motion
第一列:默認融合區間0到1 ,三個動畫過渡0,0.5,1 第二列:動畫速度 默認融合區間均等分開,取消勾選,可自行修改舊動畫系統修改動畫片段的速度
添加腳本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DefaultAvatarAnimator : MonoBehaviour { public Animator anim; public int speedHashID; public int angleHashID; public int attackHashID; private float slowSpeed;//速度修正 // Use this for initialization void Start () { speedHashID = Animator.StringToHash("Speed");//哈希Code,效能略高,不用每次調用都轉換 angleHashID = Animator.StringToHash("Angle"); attackHashID = Animator.StringToHash("Attack"); } // Update is called once per frame void Update () { if (Input.GetKey(KeyCode.LeftShift)) { slowSpeed = 0.5F; } else { slowSpeed = 1.0F; } anim.SetFloat(speedHashID, Mathf.Clamp01(Input.GetAxis("Vertical")) * slowSpeed);//Mathf.Clamp01,剔除向後走的值 anim.SetFloat(angleHashID, Input.GetAxis("Horizontal") * slowSpeed); if (Input.GetMouseButtonDown(0)) { anim.SetTrigger(attackHashID); } } }
給Walk和Run添加融合樹
層級關系 兩個動畫融合,要和動畫師溝通,融合動作容易變形,最後讓動畫師手動新建動畫 邊跑動,邊射箭 添加Attack層,添加射箭節點,添加Attack參數點擊齒輪,修改層級權重為1
Blending融合模式 Override,兩個動作折中,一般選則 Aaditive,兩個動作疊加 添加Avatar Mask,阿凡達遮罩 如果動畫類型是人形動畫:Humanoid,可選擇Humanoid的Mask 分配骨骼權重:點擊區域激活失活 動畫模型來自同一骨骼(同一Avatar)添加代碼
Unity3D學習筆記(十八):Animator新動畫