animator(新动画系统):骨骼动画,骨骼驱动,格式化编辑,动画机图形化
animation(旧动画系统):物理系统,帧动画
一、如何建立动画文件 Animation Clip
手动添加动画
1、添加animation
旧动画和新动画Clips文件的区别:
旧动画,设置少
运动模式:
----Once:动画播放完毕,再次调用可以播放
----Clamp Forever:永远一次
----Loop:从新开始
----PingPong:从尾再到头
新动画,设置多
----Loop Time循环
Debug设置:
旧动画默认勾选,新动画默认不勾选,如果旧动画想在新动画系统播放,新动画系统也需要勾选
2、建立动画片段
Ctrl+6快速打开
3、添加关键帧
代表播放后的帧偏移(播放后多少帧发生什么动作),不代表游戏时间
旧动画系统:需要用代码来驱动Animation
自动添加动画,红色按钮
二、使用Animation组件来播放Clip
一个物体有多个动画状态,用代码切换动画状态,动画帧的复用
在父物体上添加Animation,在子物体上录制动画帧(子物体保留父物体的属性,记录父物体局部坐标系,不会记录世界坐标系)
把父物体生成预制体,预制体生成的新物体,动画不会受原坐标影响
动画片段的空间差异和时间差异
动画片段的播放,停止,融合
动画片段的切换:硬切和融合Crossfade
动画片段添加动画事件
能侦测同属一个物体身上的脚本方法
三、如何从模型文件提取动画文件Clip
1、如果有动画,Animation会有内容,关键帧表格,动画师会给出
2、旧动画,进入Rig,修改Legacy
3、添加片段:名字,起始帧,结束帧
选中相应的Clips可以播放片段
做好的片段的位置,在相应的模型文件目录下
不建议直接拖拽使用,建议提取出来,选中动画,按住Ctrl+D,可以独立出动画片段,仅对该类型模型有效(如果骨骼系统是同一系统,则可以复用)
用计时器控制Animation动画片段
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AnimationManager : MonoBehaviour { public GameObject prefs; private float curTime = 0; private float interval = 1.0f; void Update () { if (Time.time < 10) { curTime += Time.deltaTime; if (curTime >= interval) { Instantiate<GameObject>(prefs).transform.position = Vector3.right * Mathf.FloorToInt(Time.time); curTime = 0; } } } }
用代码控制Animation动画片段
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AnimationChange : MonoBehaviour { public Animation anim; void Update () { if (Input.GetKeyDown(KeyCode.Q)) { anim.Play("AnimationChangeMove"); } if (Input.GetKeyDown(KeyCode.E)) { anim.Play("AnimationChangeScale"); } if (Input.GetKeyDown(KeyCode.S)) { anim.Stop(); } } void SayBig() { Debug.Log("变大了"); } void SaySmall() { Debug.Log("变小了"); } }
递归树
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Tree : MonoBehaviour { public float size; public GameObject treeGo; public void CreateSelf() { if (size < 0.05f) return;//给递归添加限值 for (int i = 0; i < 6; i++) { GameObject go = Instantiate<GameObject>(treeGo); go.transform.position = transform.position + transform.up * 5 * size; go.transform.rotation = transform.rotation; go.transform.rotation *= Quaternion.AngleAxis(Random.Range(0, 360), Vector3.up) * Quaternion.AngleAxis(Random.Range(-120, 120), Vector3.right); go.GetComponent<Tree>().size = size * 0.5f; go.transform.localScale = Vector3.one * size * 0.5f; } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerAnimation : MonoBehaviour { public Animation anim; // Use this for initialization void Start () { } // Update is called once per frame void Update () { //如果每帧检测到播放的是当前动画,则不会重复播放动画第一帧,会让动画继续播下去 //anim.Play("Idle"); if (Input.GetKeyDown(KeyCode.Alpha1)) { anim.Play("Move"); } if (Input.GetKeyDown(KeyCode.Alpha2)) { anim.Play("Idle"); } if (Input.GetKeyDown(KeyCode.Alpha3)) { anim.Play("Death"); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum PlaySta { Move, Idle, Death } public class PlayerControl : MonoBehaviour { public Animation anim; public PlaySta playSta; // Use this for initialization void Start () { playSta = PlaySta.Move; } // Update is called once per frame void Update () { float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); moveDir.x = h; moveDir.z = v; cd += Time.deltaTime; Action(); } void Action() { switch (playSta) { case PlaySta.Move: Move(); break; case PlaySta.Idle: Idle(); break; case PlaySta.Death: Death(); break; } } Vector3 moveDir; Vector3 lookPoint; RaycastHit hit; public float moveSpeed = 3; void Move() { anim.Play("Move"); transform.position += moveDir * moveSpeed * Time.deltaTime; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100, 1 << 8)) { lookPoint = hit.point; lookPoint.y = transform.position.y; transform.LookAt(lookPoint); } if (moveDir.magnitude < 0.01f) { playSta = PlaySta.Idle; } } void Idle() { anim.Play("Idle"); if (moveDir.magnitude >= 0.01f) { playSta = PlaySta.Move; } } float cd; public void Damage() { cd = 0; playSta = PlaySta.Death; } void Death() { anim.Play("Death"); } public void OnTriggerEnter(Collider other) { if (other.tag == "Monster") { if (cd > 0.5f) { Damage(); } } } }
抛异常的用法: try:包含异常的语句 try不能单独使用,要搭配catch和finally使用 catch:捕获异常,可以填参数 catch(Exception e){},(Exception是所有异常的基类) finally:最后都会执行,作为替补收尾工作, 无论如何都会执行,即使前面有return 结果:输出“捕获到了异常”,而“11111”不会输出
树BlendTree
在外边不能播动画
里面两层中心点偏移
只能改中间层