基础知识引入
移动物体方式分2种
- 非物理移动(没有力/速度等因素),只需要改变物体的位置Position即可
- 物理运动,这个时候就需要使用Unity中的物理系统
运动方式有3种
1. 朝一个方向运动
非物理运动
在Update中对Transform.position中的 (x, y, z) 值自加,例如Transform.position.x+=0.1f,0.1f被称为步长
物理运动(Rigidbody组件中的方法)
- Rigidbody.AddForce() 方法在某一个方向上施加力的效果
- Rigidbody.velocity 给物体一个移动速度
- CharacterController 中的方法,由于 CharacterController 中继承部分的 Rigidbody 属性,也可以控制物体移动,主要用于制作第一,三人称射击运动
2. 向着目标点移动(一般是鼠标点击点)
非物理运动
- Transform.Translate:举个例子,Transform.Translate(Vector3.zero*Time.deltaTime) 以一米每秒的速度向 (0,0,0) 点运动
- Vector3.lerp:Vector.Slerp,Vector3.MoveTowards插值。Vector3.lerp(transform.position, targetposition, Time.deltaTime),Slerp主要用于角度弧度的插值运算,MoveTowards在Lerp基础上增加了限制最大速度
- Vector3.SmoothDamp:该方法是可以平滑的从A逐渐移动到B点,并且可以控制速度,最常见的用法是相机跟随目标。
物理运动
- Righdbody 中的 Rigidbody.MovePosition 方法用于实现向目标点移动
3. 由A点到B点(运动方式2的特殊化)
运用
一个物体在运动状态下,会有一个速度变量,也就是我们期望的速度。而从静止到运动状态的过程,会有一个加速度。而游戏开发中,要做到一个物体平滑的运动,也就是模拟出这个从静止,通过加速度,达到期望速度的过程。游戏是按帧运行的,在初始的时候,目标运动速度为 0,随着每一帧的流逝,目标速度会不断累加一帧中的加速度,当累加到期望速度时,则会以期望速度来运动。
Unity 中实现的代码如下(原理对于所有游戏引擎通用)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovingSphere : MonoBehaviour
{
// 用户设定最大期望速度
[SerializeField, Range(0f, 100f)] private float maxSpeed = 10f;
// 用户设定最大加速度
[SerializeField, Range(0f, 100f)] private float maxAcceleration = 10f;
// 当前的运动速度
private Vector3 velocity;
// Update is called once per frame
void Update()
{
// 通过读取用户输入,来确定期望速度向量(向量包含了大小和方向)
Vector2 playerInput;
playerInput.x = Input.GetAxis("Horizontal");
playerInput.y = Input.GetAxis("Vertical");
Vector3 desiredVelocity = new Vector3(playerInput.x, playerInput.y, 0.0f) * maxSpeed;
// 计算这一帧中的最大加速度(现实中是以秒为单位,而游戏运行是以帧为单位)
float maxSpeedChanged = maxAcceleration * Time.deltaTime;
// 下面的代码是将当前速度限制为最大期望速度
if (velocity.x < desiredVelocity.x)
{
velocity.x = Mathf.Min(velocity.x + maxSpeedChanged, desiredVelocity.x);
}
else if (velocity.x > desiredVelocity.x)
{
velocity.x = Mathf.Max(velocity.x - maxSpeedChanged, desiredVelocity.x);
}
if (velocity.y < desiredVelocity.y)
{
velocity.y = Mathf.Min(velocity.y + maxSpeedChanged, desiredVelocity.y);
}
else if (velocity.y > desiredVelocity.y)
{
velocity.y = Mathf.Max(velocity.y - maxSpeedChanged, desiredVelocity.y);
}
// 得到了当前速度,就可以计算当前这一帧的位移
Vector3 displacement = velocity * Time.deltaTime;
// 将物体的当前位置,累加上这一帧的位移,就是最终的移动
transform.localPosition += displacement;
}
}