Unity: Move, Camera Tracking, Animator

Unity: Move, Camera Tracking, Animator

最近跟着网络上的课程班学习了一些Unity的使用,记录一下自己的学习心得。

移动:Move

实现角色的移动需要在Update方法里对物体的位置进行更新。

Unity支持数学公式,角色控制器以及刚体等移动方式。
而每种方式又有不同的子方法。

旋转:Rotation

我们先要根据input获取键盘上对应的操作命令。
如果水平和垂直数值均为0,则直接返回,不进行下面的更新命令。

将输入的方向新建为一个向量。
然后将其转换为一个四元数,通过rotation方法对角色进行旋转。

1
2
3
4
5
6
7
8
9
10
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
m_anim.SetBool("bMove", h != 0 || v != 0);
if (h == 0 && v == 0) return;

Vector3 dir = new Vector3(-h, 0, -v);
Quaternion targetQ = Quaternion.LookRotation(dir, Vector3.up);
//transform.rotation = targetQ;
transform.rotation = Quaternion.Lerp(transform.rotation, targetQ, Time.deltaTime * mfRoateSpeed);
//对四元数进行插值,控制旋转速度

数学公式:Math Function

我们可以直接以数学公式的方法更新当前位置,将其加入向量乘以帧时间乘以速度的方式更新当前位置:
transform.position += transform.forward * Time.deltaTime * mfMoveSpeed;

也可以使用Translate()方法,注意这里需要传入world空间模式
transform.Translate(transform.forward * Time.deltaTime * mfMoveSpeed, Space.World);

MoveTowards方法,不太常用。
transform.position = Vector3.MoveTowards(transform.position, transform.position + transform.forward * Time.deltaTime * mfMoveSpeed, Time.deltaTime * mfMoveSpeed);

角色控制器:Character Controller

这种模式需要在全局变量中创建并获取角色控制器对象。
使用角色控制器需要设定其盒子范围。

1
2
3
4
5
6
7
m_characterController = transform.gameObject.GetComponent<CharacterController>();
if(m_characterController == null)
{
m_characterController = transform.gameObject.AddComponent<CharacterController>();
}
m_characterController.center = new Vector3(0f, 0.6f, 0f);
m_characterController.height = 1.3f;

我们也可以使用角色控制器移动角色。

Simple Move模式可以直接模拟重力:
m_characterController.SimpleMove(transform.forward * mfMoveSpeed);

注意Simple Move模式下按秒进行移动,不需要乘以帧时间。

Move模式则需要手动添加向下的重力,否则物体Y轴移动后不会下降。
m_characterController.Move(-transform.up * Time.deltaTime * mfMoveSpeed);m_characterController.Move(transform.forward * Time.deltaTime * mfMoveSpeed);

刚体:Rigidbody

首先需要在全局变量中创建并获取刚体对象。

刚体模式需要创建碰撞盒,并且将Y轴freeze,否则物体会直接向下落下。

1
2
3
4
5
6
7
8
9
10
11
m_rigidbody = transform.gameObject.GetComponent<Rigidbody>();
if(m_rigidbody == null)
{
m_rigidbody = transform.gameObject.AddComponent<Rigidbody>();
}
m_rigidbody.constraints = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;

CapsuleCollider collider = transform.gameObject.AddComponent<CapsuleCollider>();
collider.center = new Vector3(0f, 0.6f, 0f);
collider.height = 1.3f;

可以采用恒速的velocity方法
m_rigidbody.velocity = transform.forward * mfMoveSpeed;

或者采用AddForce方法,这样会不断加速。
m_rigidbody.AddForce(transform.forward * mfMoveSpeed * mAddForceFactor);

MovePosition方法,同样是直接计算移动后的位置。
m_rigidbody.MovePosition(transform.position + transform.forward * Time.deltaTime * mfMoveSpeed);

镜头跟随:Camera Tracking

脚本需要挂在到相机下。

两个向量相减的几何意义是减数方向指向被减数方向

用相机位置减去玩家的位置,则可以得到玩家指向相机的向量。
然后在Update中实时更新相机的位置,就可以实现镜头跟随的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MainCamera : MonoBehaviour
{
private Transform m_player; //需要聚焦的角色的位置
private Vector3 m_v3RelativePos; //相机和角色的相对向量

// Start is called before the first frame update
void Start()
{
m_player = GameObject.FindGameObjectWithTag("Player").transform; //获取玩家角色
m_v3RelativePos = transform.position - m_player.position; //计算相对位置
}

// Update is called once per frame
void Update()
{
transform.position = m_player.position + m_v3RelativePos; //实时更新相机的位置
}
}

动画状态机:Animator

模型下需要有Anim模块才能实现动画。
原有的资源里已经制作了动画,在这里额外实现的是根据动作来切换动画。

在Start()里初始化成员变量Animator m_anim。
m_anim = transform.Find("Anim").GetComponent<Animator>();
然后在Update()里使用SetBool方法对Animator的开关真值进行更新。
m_anim.SetBool("bMove", h != 0 || v != 0);

Animator支持几种类型的trigger如Bool,Int,