使用Time类的属性来控制游戏角色的移动速度
在Unity中控制游戏角色移动速度的核心是 使用 Time.deltaTime 实现帧率无关移动——这是最基础也最关键的原则,确保角色在不同帧率设备(如30fps手机和60fps电脑)上移动速度一致。此外,还可通过 Time.timeScale 实现慢动作/快进移动,或用 Time.unscaledDeltaTime 实现不受暂停影响的移动(如UI角色、后台移动单位)。
以下分 核心实现(帧率无关移动)、进阶控制(慢动作/暂停兼容)、不同移动方式适配 三部分详细说明,附完整代码示例。
一、核心原则:为什么必须用 Time.deltaTime?
- 游戏的
Update()函数调用频率不固定(帧率越高,调用越频繁); Time.deltaTime表示“上一帧到当前帧的时间间隔(秒)”,乘以移动速度后,能将“每帧移动距离”转换为“每秒移动距离”,实现 帧率无关。
❌ 错误做法(帧率依赖,低帧率变慢):
// 假设60fps,每帧移动 5/60 米,但30fps时每帧仍移动同样距离,每秒仅移动 5/60 *30 = 2.5米(速度减半)
transform.Translate(Vector3.forward * 5f / 60f);
✅ 正确做法(帧率无关,每秒稳定移动5米):
// 速度(米/秒)* 帧间隔(秒)= 每帧移动距离(米),无论帧率多少,每秒总距离=速度
transform.Translate(Vector3.forward * speed * Time.deltaTime);
二、基础实现:帧率无关的角色移动(最常用)
适用于 普通角色移动(如PC端 WASD、移动端虚拟摇杆),核心是在 Update() 中用 Time.deltaTime 计算移动量。
1. 代码示例(Transform 直接移动,适合非物理角色)
适合2D/3D角色(如Top-Down视角、横版卷轴),无需物理碰撞(或用碰撞体+非刚体):
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("移动配置")]
public float moveSpeed = 5f; // 核心:移动速度(单位:米/秒,帧率无关)
public bool useWorldSpace = true; // true=世界空间移动(固定前后左右),false=本地空间(跟随角色朝向)
void Update()
{
// 1. 获取输入(PC端 WASD/方向键,可替换为移动端摇杆输入)
float horizontal = Input.GetAxis("Horizontal"); // 左右:-1(左)~1(右)
float vertical = Input.GetAxis("Vertical"); // 前后:-1(后)~1(前)
// 2. 构建移动方向(归一化避免斜向移动过快)
Vector3 moveDir = new Vector3(horizontal, 0, vertical).normalized;
// (2D游戏替换为:Vector2 moveDir = new Vector2(horizontal, vertical).normalized;)
// 3. 帧率无关移动(核心:乘以 Time.deltaTime)
if (useWorldSpace)
{
// 世界空间移动(适合固定视角,如上帝视角)
transform.Translate(moveDir * moveSpeed * Time.deltaTime);
}
else
{
// 本地空间移动(适合第三人称/第一人称,移动方向跟随角色朝向)
transform.Translate(moveDir * moveSpeed * Time.deltaTime, Space.Self);
}
}
}
2. 代码示例(Rigidbody 物理移动,适合需要碰撞/重力的角色)
如果角色有 Rigidbody(3D)或 Rigidbody2D(2D),必须在 FixedUpdate() 中使用 Time.fixedDeltaTime(物理帧固定间隔,默认0.02秒),避免物理抖动:
using UnityEngine;
public class PlayerPhysicsMovement : MonoBehaviour
{
[Header("物理移动配置")]
public float moveSpeed = 5f; // 移动速度(米/秒)
private Rigidbody rb; // 3D角色用Rigidbody,2D用Rigidbody2D
void Start()
{
// 获取组件(确保角色身上已添加Rigidbody,且勾选"Use Gravity")
rb = GetComponent<Rigidbody>();
// 优化:锁定旋转(避免移动时角色倾倒)
rb.freezeRotation = true;
}
// 物理逻辑必须用 FixedUpdate(固定时间步,不受帧率影响)
void FixedUpdate()
{
// 1. 获取输入
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 moveDir = new Vector3(horizontal, 0, vertical).normalized;
// 2. 物理移动(两种方式选一种)
// 方式1:直接设置速度(适合匀速移动,不受摩擦力影响)
rb.velocity = new Vector3(moveDir.x * moveSpeed, rb.velocity.y, moveDir.z * moveSpeed);
// 方式2:施加力(适合有加速度/摩擦力的场景,需调整ForceMode)
// rb.AddForce(moveDir * moveSpeed * Time.fixedDeltaTime, ForceMode.VelocityChange);
}
}
关键说明:
moveSpeed的单位是 米/秒(Unity默认单位),直观易调整(如想让角色1秒移动5米,就设为5);- 移动方向需
normalized:避免斜向移动时(如同时按W+D),向量长度为√2≈1.414,导致斜向速度比正向快。
三、进阶控制:用 Time.timeScale 调整移动速度(慢动作/快进)
Time.timeScale 是时间缩放因子,会影响 Time.deltaTime 和 Time.fixedDeltaTime,因此可直接控制移动速度的“时间流速”,实现慢动作、快进等效果。
1. 慢动作/快进示例
在基础移动代码上,只需修改 Time.timeScale,移动速度会自动按比例变化:
// 绑定到UI按钮的点击事件(示例:慢动作、正常、快进)
public void SetSlowMotion()
{
Time.timeScale = 0.5f; // 移动速度变为原来的50%(慢动作)
}
public void SetNormalSpeed()
{
Time.timeScale = 1f; // 正常速度
}
public void SetFastForward()
{
Time.timeScale = 2f; // 移动速度变为原来的200%(快进)
}
2. 暂停时的特殊处理
当 Time.timeScale = 0(暂停)时,Time.deltaTime 会变为0,角色会停止移动。若需要 暂停时仍能移动的角色(如UI提示角色、后台巡逻的敌人),需用 Time.unscaledDeltaTime:
// 暂停时仍能移动的角色(如UI角色)
public class UnscaledMovement : MonoBehaviour
{
public float moveSpeed = 3f;
void Update()
{
// 核心:用 Time.unscaledDeltaTime(不受 timeScale 影响)
transform.Translate(Vector3.right * moveSpeed * Time.unscaledDeltaTime);
}
}
注意事项:
- 物理移动(Rigidbody)的暂停:除了
Time.timeScale = 0,还需设置rb.isKinematic = true(暂停物理模拟),恢复时设为false; - 等待逻辑:若用
WaitForSeconds()配合慢动作,等待时间会按timeScale缩放(如timeScale=0.5时,WaitForSeconds(2)实际等4秒);若需实时等待,用WaitForSecondsRealtime()。
四、不同移动场景的适配
1. 2D角色移动(Rigidbody2D)
using UnityEngine;
public class Player2DMovement : MonoBehaviour
{
public float moveSpeed = 5f;
private Rigidbody2D rb2D;
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
rb2D.freezeRotation = true;
}
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector2 moveDir = new Vector2(horizontal, vertical).normalized;
// 2D物理移动
rb2D.velocity = moveDir * moveSpeed;
}
}
2. 第一人称/第三人称移动(跟随相机方向)
让移动方向跟随相机视角(如按下W时向相机前方移动):
using UnityEngine;
public class PlayerCameraRelativeMovement : MonoBehaviour
{
public float moveSpeed = 6f;
public Camera mainCamera; // 赋值主相机
void Update()
{
// 1. 获取输入
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 inputDir = new Vector3(horizontal, 0, vertical).normalized;
if (inputDir.magnitude < 0.1f) return; // 无输入时退出
// 2. 获取相机的水平旋转(忽略垂直旋转,避免上下看时移动方向倾斜)
Quaternion cameraRot = Quaternion.Euler(0, mainCamera.transform.eulerAngles.y, 0);
// 3. 将输入方向转换为相机空间
Vector3 moveDir = cameraRot * inputDir;
// 4. 帧率无关移动
transform.Translate(moveDir * moveSpeed * Time.deltaTime);
}
}
3. 加速/减速移动(动态调整 moveSpeed)
通过 Time.time 或计时器实现速度渐变:
public class AcceleratedMovement : MonoBehaviour
{
public float baseSpeed = 3f;
public float acceleration = 2f; // 每秒增加的速度(米/秒²)
public float maxSpeed = 8f; // 最大速度上限
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 moveDir = new Vector3(horizontal, 0, vertical).normalized;
if (moveDir.magnitude > 0.1f)
{
// 加速:速度 = 基础速度 + 加速度 * 时间(帧率无关)
moveSpeed = Mathf.MoveTowards(moveSpeed, maxSpeed, acceleration * Time.deltaTime);
}
else
{
// 无输入时减速到0
moveSpeed = Mathf.MoveTowards(moveSpeed, 0, acceleration * 2 * Time.deltaTime);
}
transform.Translate(moveDir * moveSpeed * Time.deltaTime);
}
}
五、常见问题排查
- 角色斜向移动过快:忘记对移动方向
normalized,导致斜向向量长度>1; - 物理移动抖动:在
Update()中操作Rigidbody,应改为FixedUpdate()并使用Time.fixedDeltaTime; - 暂停后角色仍移动:误用了
Time.unscaledDeltaTime,需检查是否需要受timeScale影响; - 不同设备速度不一致:未使用
deltaTime,或误将fixedDeltaTime用于Update()。
总结
控制角色移动速度的核心流程:
- 定义
moveSpeed(单位:米/秒),作为基础移动速度; - 在
Update()(Transform移动)或FixedUpdate()(物理移动)中,获取输入并构建移动方向; - 用
Time.deltaTime(受时间缩放)或Time.unscaledDeltaTime(不受时间缩放)乘以速度和方向,实现帧率无关移动; - 进阶需求:通过
Time.timeScale控制慢动作/快进,或动态调整moveSpeed实现加速/减速。
按以上方法,可确保角色在任何设备、任何帧率下都能按预期速度移动,且兼容暂停、慢动作等常见游戏机制。