Animator & Timeline

  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using UnityEngine.Playables;
  5    
  6 public class Player : MonoBehaviour {
  7 
  8     private Animator anim;
  9     //private int speedID = Animator.StringToHash("Speed");           // 10     //private int isSpeedUPID = Animator.StringToHash("isSpeedUP");   // 11     //private int turnAroundID = Animator.StringToHash("TurnAround");   //转向
 12 
 13     private int speedRotateID = Animator.StringToHash("SpeedRotate");
 14     private int speedZID = Animator.StringToHash("SpeedZ");
 15 
 16     private int isHoldLogID = Animator.StringToHash("isHoldLog");
 17     private int slideID = Animator.StringToHash("Slide");
 18     private int vaultID = Animator.StringToHash("Vault");
 19     private Vector3 matchTarget = Vector3.zero;
 20 
 21     private CharacterController characterController;
 22     private int colliderID = Animator.StringToHash("Collider");
 23 
 24     public GameObject unityLog = null;     //角色身上的木头
 25     public Transform rightHand;         //木头左右边的节点(空的gameobject)
 26     public Transform leftHand;
 27     public PlayableDirector playable;
 28 
 29     // Use this for initialization
 30     void Start () {
 31         anim = GetComponent<Animator>();
 32         characterController = GetComponent<CharacterController>();
 33         //unityLog = transform.Find("Reference/Hips/Unity_Log (1)").gameObject;       //找到Log
 34     }
 35     
 36     // Update is called once per frame
 37     void Update () {
 38         //2D混合树控制移动和旋转
 39         anim.SetFloat(speedZID, Input.GetAxis("Vertical") * 4.1f);
 40         anim.SetFloat(speedRotateID, Input.GetAxis("Horizontal") * 126f);
 41 
 42         ProcessVault();
 43         ProcessSlide();
 44         //if(anim.GetFloat(colliderID)>0.5f)
 45         //{
 46         //    characterController.enabled = false;
 47         //}
 48         //else
 49         //{
 50         //    characterController.enabled = true;
 51         //}
 52         //上面判断语句的简写
 53         //滑动或FQ时禁用角色控制器
 54         characterController.enabled = anim.GetFloat(colliderID) < 0.05f;
 55 
 56 
 57         // 58         //anim.SetFloat(speedID, Input.GetAxis("Vertical")*4.1f);
 59 
 60         ////转向
 61         //anim.SetFloat(turnAroundID, Input.GetAxis("Horizontal"));
 62         ////跑
 63         //if(Input.GetKeyDown(KeyCode.LeftShift))
 64         //{
 65         //    anim.SetBool(isSpeedUPID, true);
 66         //}
 67         //if (Input.GetKeyUp(KeyCode.LeftShift))
 68         //{
 69         //    anim.SetBool(isSpeedUPID, false);
 70         //}
 71 
 72 
 73     }
 74 
 75     //FQ
 76     private void ProcessVault()
 77     {
 78         //FQ
 79         bool isVault = false;
 80         //当Animator状态机在混合树“Motion”时判断,节省性能
 81         if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("Motion"))
 82         {
 83             RaycastHit hit;
 84             if (Physics.Raycast(transform.position + Vector3.up * 0.3f, transform.forward, out hit, 4f))
 85             {
 86                 if (hit.collider.tag == "Obstacle")
 87                 {
 88                     if (hit.distance > 3)
 89                     {
 90                         Vector3 point = hit.point;
 91                         //设定匹配位置
 92                         point.y = hit.collider.transform.position.y + hit.collider.bounds.size.y + 0.05f;
 93                         matchTarget = point;
 94                         isVault = true;
 95                     }
 96 
 97                 }
 98             }
 99         }
100         anim.SetBool(vaultID, isVault);
101 
102         //匹配跳跃过程中左手与墙面的位置
103         if (anim.GetCurrentAnimatorStateInfo(0).IsName("Vault"))
104         {
105             anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.LeftHand, new MatchTargetWeightMask(Vector3.one, 0), 0.32f, 0.4f);
106         }
107 
108     }
109 
110     //
111     private void ProcessSlide()
112     {
113         bool isSlide = false;
114         if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("Motion"))
115         {
116             RaycastHit hit;
117             if (Physics.Raycast(transform.position + Vector3.up * 1.5f, transform.forward, out hit, 3f))
118             {
119                 if (hit.collider.tag == "Obstacle")
120                 {
121                     if (hit.distance > 2)
122                     {
123                         Vector3 point = hit.point;
124                         point.y = 0;
125                         matchTarget = point + transform.forward * 2;
126                         isSlide = true;
127                     }
128                 }
129             }
130         }
131         anim.SetBool(slideID,isSlide);
132         if (anim.GetCurrentAnimatorStateInfo(0).IsName("Slide"))
133         {
134             anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(1,0,1), 0), 0.17f, 0.67f);
135         }
136     }
137 
138     //检测碰撞
139     private void OnTriggerEnter(Collider other)
140     {
141         //木头
142         if(other.tag=="Log")
143         {
144             Destroy(other.gameObject);
145             CarryWood();
146         }
147         //镜头
148         if(other.tag=="Playable")
149         {
150             playable.Play();
151         }
152     }
153 
154     //扛木头
155     void CarryWood()
156     {
157         unityLog.SetActive(true);
158         anim.SetBool(isHoldLogID, true);
159     }
160 
161     //设置左右手IK到相应节点
162     //每帧都调用
163     private void OnAnimatorIK(int layerIndex)
164     {
165         //当layer层级为HoldLog
166         if(layerIndex==1)
167         {
168             int weight = anim.GetBool(isHoldLogID) ? 1 : 0;
169             //左手
170             anim.SetIKPosition(AvatarIKGoal.LeftHand, leftHand.position);
171             anim.SetIKRotation(AvatarIKGoal.LeftHand, leftHand.rotation);
172             anim.SetIKPositionWeight(AvatarIKGoal.LeftHand, weight);         //IK权重
173             anim.SetIKRotationWeight(AvatarIKGoal.LeftHand, weight);
174 
175             //右手
176             anim.SetIKPosition(AvatarIKGoal.RightHand, rightHand.position);
177             anim.SetIKRotation(AvatarIKGoal.RightHand, rightHand.rotation);
178             anim.SetIKPositionWeight(AvatarIKGoal.RightHand, weight);
179             anim.SetIKRotationWeight(AvatarIKGoal.RightHand, weight);
180         }
181     }
182 }
Player

Rig:

动画类型分为三类

1.Legacy:老版本的动画系统,一般都是单独做好的

2.Generic:骨骼动画,一般用在非人型生物上

3.Humanoid:骨骼动画,一般可通用在人形模型上面,只要骨骼节点设置相同

       如果有些人物模型带有骨骼但是无法通用可选择:Create Form This Model -> Apply一下

       ->点击configure进行编辑确认后保存退出看下能不能用

 

 

Animation:

可进行动画的剪切与播放设置

1.Loop Pose让动画循环播放时衔接更顺滑(猜测是通过动画曲线开始与结束时的的陡峭程度进行插值运算)

2.Root Transform 下面的Bake into Pose勾选后动画播放后的位置就会被固定(有些动画播放时会有位移和转向)

3.Curves:设置曲线值,并且可以在Animator编辑器中添加相同名称的Parameters来控制触发条件

 

 

Animator状态机:

1.可以把动画拖进去设置然后通过相应的状态连接起来(点击连接箭头后如右边Inspector显示)

    (1)Has Exit Time是否等当前动画播放完才跳转到下一个

    (2)Conditions里可以设置Parameter里添加的各种条件参数

 

Blend Tree混合树:

在Animator里的BaseLayer层右键单击选择Creat State -> From New Blend Tree

如右边面板所示  (1)可选择1D/2D等混合树类型

          (2)可以添加各个动画然后在图中拖动摆放各个动画并观察相互间的影响范围,也可以通过Compute Positions来按照特定条件计算摆放

 

 

AvatorMask:

通过Project中的Create -> AvatorMask创建

如图可以设置各个部位与Ik的禁用

通过新建一个Layer层设置Weight权重,Mask,Blending混合类型等可以在主动画播放时控制另一个动画也播放

如图中设置就能使第一个Layers里的动画播放时,第二个Layers动画中手部的动画状态覆盖掉第一个动画

(也就是说原本第一层动画是跑动时的动作(手会摆动),而第二层动画是原地站立举手的动作,如图中设置后就变成跑动时举手的动作了)

 

 

Timeline:

功能有点类似于视频编辑软件,主要通过Playable Director组件来控制

把相应的动画,物体,声音等直接拖入会显示创建类型,或者右键单击也可以看到有哪些类型可创建

1.可通过点击红色圆点进行动画的录制(改变position与rotation等)

2.右键单击相应轨道选择Add From Animation Clip可以生成模块,然后就能随意的拖动摆放或缩放播放内容了

 

点击相应的模块后可在inspector面板进行设置

1.Pre/Post - Extrapolate可以设置动画播放前/后的状态(暂时未发现这些设置对Post有何作用,因此那个“结束后”待定)

  (1)None:在开始前/结束后,无,物体原始位置都会被设置为(0,0,0),动画开始的默认状态也不会有(以带有骨骼动画的人物为例,不会站立等,而是变成骨骼动画设置里的Muscle&Setting状态(苟起来)),直到播放动画为止

  (2)Hold:在开始前/结束后,保持动画起始时的状态,直到播放动画为止

  (3)Loop:同上,循环播放(起点 -> 终点, 起点 -> 终点。。这样一个状态),同上

  (4)PingPong:同上,和循环对比的区别就是(起点 -> 终点 ->起点这一过程,不会瞬移),同上

  (5)Continue:同上,在播放前会把动画播放一边然后一直等待到动画播放为止,如果动画前面部分被缩减掉一点,当放到此动画时依然会播放完整

 

posted @ 2018-07-01 23:41  QQW的进化之旅  阅读(544)  评论(0编辑  收藏  举报