动画系统介绍
| 游戏动画
一般指模型的动作,服务视觉,实际攻击计算还靠碰撞体
暂时只尝试制作简单动画来知道动画的运行原理
如何给角色配置动作、如何切换动作、代码控制动作
| Unity动画
模型和动作
非人形角色,比如一个章鱼怪,他的动作基本上是完全为了这一个模型来设计的,无法复用到其他模型
人形角色,符合标准的都可以复用,基于Avatar
角色动作组成
游戏物体上挂载 Animator 动画组件
Animator组件上持有 Controller(动画控制器),Controller 上配置好动作以及动作切换逻辑
利用Animator组件来播放动画以及切换动画
Unity 内制作动画
选择一个具备 Animator组件的游戏物体后切换到 Animation 面板,即可进行动画的制作
Animator Controller
Animator Controller 是一个配置文件
动画片段设置
Loop Time:动画是否循环播放
Loop Pose:是否循环姿势,让头尾链接更平滑
Animator 面板
状态面板
当我们选择一个状态后,检查面板中会出现这个状态的一些参数
Motion:这个状态具体要播方收的动画文件
Speed:动画的播放速度,float类型
Mirror:镜像动画,动画左右相反
Transitions:该状态参与的状态转换
Solo:当两个状态之间有多条条件时候仅此一条生效
Mute:禁用
状态切换
参数面板
状态之间的连线,点击具体某根线后,检查面板中可以设置状态切换的具体参数
Has Exit Time:播放完毕才能切换
Conditions:条件参数,也就是这条线什么时候起效果
代码控制
游戏运行后,动画会自行从入口开始执行,但是我们可以获取 Animator 组件后修改参数,使动画切换
SetInteger("Run",1)
:修改参数的值,对应的还有SetBool、SetTrigger、SetFloatGetInteger("Run")
:获取参数的值,对应的GetBool、GetFloatspeed:整体的播放速度
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L8_3Demo : MonoBehaviour
{
public Animator animator;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("Jump");
}
}
}
模型资源与动画设置
Unity 常用模型格式:.fbx
人形动画的复用性
人性角色的骨骼结构是一致的
Avatar 映射文件:人形动作中才使用,映射人体的位置对应什么游戏物体,这样动作文件才能正确工作,基于此可以让动作复用
动画事件
自建动画:在 Animation 中添加事件
模型动画:在模型中找到动画片段,添加事件
角色控制器组件
Transform 不具备物理特性
而 Rigidbody 却不稳定,很容易被弹开、穿模
角色控制器(CharacterController):
面板:
Slope Limit:控制角色最大的爬坡斜率
Step Offset:控制角色可以迈上最大的台阶高度
Skin Width:在角色外围包裹一层 “皮肤”,这层皮肤的厚度,相当于角色身上透明的衣服,如果 Skin Width 设置为 1m,那么角色会 “浮空” 1m,一般保持默认即可
Min Move Distance:最小移动距离,默认是1毫米,如果该数值过大但代码中单位移动速度很慢,角色就不会动
Center / Radius / Height:角色控制器组件在 Scene面板 中体现为一个 “胶囊碰撞器” 的形状,这也导致其他的碰撞体我们并不需要,Center 为胶囊中心点位置,Radius 为半径,Height 为高度
角色控制器组件所在的游戏物体身上不需要碰撞体和刚体
常用属性:
- isGrounded:是否在地面上
常用方法
Move(Vector3 dir)
:和 Transform.Translate雷同,没有重力,需要传递的是一个方向,数值的大小影响移动速度,所以需要乘上Time.deltaTimeSimpleMove(Vector3 speed)
:会应用重力,需要传递的值是一个速度,并且本身就是按照时间来计算的,数值大小虽然也会影响移动速度,但是不会被帧率影响,所以不需要乘 Time.deltaTime
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L8_7Demo : MonoBehaviour
{
private CharacterController characterController;
void Start()
{
characterController = GetComponent<CharacterController>();
}
void Update()
{
Debug.Log(characterController.isGrounded);
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//Vector3 dir = new Vector3(horizontal, -9.8f, vertical);
// 1
//characterController.Move(dir * Time.deltaTime * 30);
Vector3 dir = new Vector3(horizontal, 0, vertical);
// 2
characterController.SimpleMove(dir * 30);
}
}
案例:3D 角色移动
使用角色控制器组件来控制角色位移,并且播放正确的待机或移动动画
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class L8_8Player : MonoBehaviour
{
private CharacterController characterController;
private Animator animator;
void Start()
{
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
}
void Update()
{
Demo2();
}
// 实现基于自身坐标体系的移动,不考虑旋转
private void Demo1()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (horizontal != 0 || vertical != 0)
{
animator.SetBool("Run", true);
}
else
{
animator.SetBool("Run", false);
}
Vector3 dir = new Vector3(horizontal, 0, vertical);
// 如果以 transform 为参考方向,得到我自己的前方
dir = transform.TransformDirection(dir);
characterController.SimpleMove(dir);
}
private void Demo2()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (horizontal != 0 || vertical != 0)
{
animator.SetBool("Run", true);
}
else
{
animator.SetBool("Run", false);
}
Vector3 dir = new Vector3(0, 0, vertical);
// 如果以 transform 为参考方向,得到我自己的前方
dir = transform.TransformDirection(dir);
characterController.SimpleMove(dir);
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y + horizontal * Time.deltaTime * 100, 0);
}
}