参考视频链接:【详解Unity】几种移动方式实现_哔哩哔哩_bilibili

1. Transform 类移动

a. transform.position

最基础的移动方式,每帧瞬移 speed * Time.deltaTime,注意这里是 += position 而不是 = (即这里的输入是一帧内的相对运动距离)

1
transform.position += new Vector3(0, 0, speed * Time.deltaTime);

b. transform.Translate

实现:Translate(V3向量, 坐标系)

相较于 transform.position 的优点是 translate 可使用自身坐标移动,而 position 则永远以世界坐标为参照。举个例子,当把物体绕 z 轴旋转 45 度之后,让其沿着 x 轴进行运动。此时其自身坐标系的 x 和 z 平面与世界坐标系的平面之间有了夹角,默认情况下使用 Translte 运动时便会斜着进行运动。而不是与世界坐标系的平面平行运动。若想让其仍然沿着世界坐标系的 x 轴进行运动的话,修改下 Translate 的第三个参数为 Space.World 即可,默认值是 Space.Self

坐标系参数:

  • Space.Self(默认值)(参照自身坐标移动)
  • Space.World(参照世界坐标移动)
1
transform.Translate(Vector3.forward * Time.deltaTime * speed, Space.Self);

关于世界坐标系和自身坐标系的区别,可以在 Unity 左上角进行切换查看,或者按快捷键 x 进行切换。

2. Vector3 类移动(渐变)

这类移动相关的函数与其说是移动不如说是渐变更合适些,通过插值的形式得到一组渐变的位置点,然后进行赋值。

a. Vector3.Lerp

实现:Lerp(当前位置(V3),目标位置(V3),时间(float));

这种方式实现的线性移动由时间参数控制,距离越近,运动越缓慢。主要应用在摄像机跟随上

1
2
Vector3 lerp = Vector3.Lerp(transform.position, target.position, Time.deltaTime * speed);
transform.position = lerp; // 生成的插值进行赋值

b. Vector3.Slerp

实现:Slerp(当前位置(V3),目标位置(V3),时间(float));

相比 Lerp,其移动跟随时是以一个弧形轨迹来进行的,主要应用在旋转时过渡,或者抛物线。

1
2
Vector3 slerp = Vector3.Slerp(transform.position, target.position, Time.deltaTime * speed);
transform.position = slerp;

c. Vector3.MoveTowards

实现:MoveTowards(当前位置(V3),目标位置(V3),时间(float)) ;

一个缓慢的,匀速运动的过程。速度参数:取正->靠近目标,取负->远离目标

1
2
Vector3 movetowards = Vector3.MoveTowards(transform.position, target.position, Time.deltaTime * speed);
transform.position = movetowards;

d. Vector3.SmoothDamp

实现:SmoothDamp(当前位置(V3),目标位置(V3),当前速度(ref: V3), 所需时间(float), 最大速度(float))

官方翻译为“平滑阻尼”,也就是移动过程中,逐渐变慢地抵达终点。

注意:当前速度参数应为全局变量,因为是 ref 所以每次都会修改该值。而对于所需时间参数,该值越小,越快抵达目标。

1
2
Vector3 movetowards = Vector3.SmoothDamp(transform.position, target.position, ref currentVelocity, smoothTime, maxSpeed);
transform.position = movetowards;

3. 刚体 (Rigidbody) 方式移动

a. AddForce

实现:

1
rig.AddForce(new Vector3(0, 0, 20f), ForceMode.Force); // (力的方向,力的模式)

该实现建议放置在 FixedUpdate 函数下,此时移动物体需要添加刚体,适合模拟外力作用下的刚体运动。注意此力为累加的力,不适合重复施加力来模拟物体。

力的模式(ForceMode) 有如下几种:

  • Force -> 可持续的力,受质量影响(默认)
  • Acceleration -> 可持续的加速度,不受质量影响
  • Impulse -> 一个瞬间冲击力,受质量的影响
  • VelocityChange -> 一个瞬间速度变化,不受质量影响

这里补充下刚体 Rigidbody Component 里面几个参数的含义

  • Mass -> 物体的质量
  • Drag -> 空气的阻力
  • Angular Drag -> 角阻力
  • Use Gravity -> 是否使用重力
  • Is Kinematic -> 是否使用动力学

b. MovePosition

实现:

1
rig.MovePosition(transform.position + speed * Time.deltaTime);

其适合模拟常规移动,但需要收到物理引擎影响的物体

c. Velocity

实现

1
rig.velocity += new Vector(0, 0, 10) * Time.deltaTime;

瞬间给一个物体恒定的速度,将该物体提升到这个速度并保持。主要应用在跳跃上。

4. 使用角色控制器组件移动

角色控制器(Character Controller)是一个 Compoent 需要自己手动添加,里面大致有以下几个参数:

  • Slope Limit -> 爬坡限制,高于这个就爬不上去了
  • Step Offset ->
  • Skin Width -> 外壳厚度
  • Min Move Distance -> 最小移动距离

以下两个功能使用均需要挂载角色控制器组件

a. SimpleMove

实现:SimpleMove(有方向的力(V3));

以秒为单位,无需乘以时间。无需添加刚体,自带刚体效果,具有重力。Y 轴无效,若想使用 Y 轴有效需使用 Move

应用于简单角色移动,角色控制器的物体有刚体的效果,但仅受限于碰撞体,其他物理效果对此无效。

1
cc.SimpleMove(transform.forward * speed);

b. Move

实现:Move(有方向的力(V3))

注意其不具备重力,需要自行计算下落(需要考虑加速度之类)。主要应用在角色移动(角色控制器的物体有刚体的效果,但仅限于碰撞体,其他物理效果对此无效)。

1
cc.Move(transform.forward * speed * Time.deltaTime);

5. 几种移动方式的区别和应用

  • Transform:适用于既没有物理系统,又对移动无特殊要求的物体,但过于基础,不易处理障碍物阻挡问题;
  • Vector:动作之间的渐变,不常用于移动,摄像机跟随;
  • Rigidbody:适用于关卡障碍之类;
  • CharacterController:常用于主角移动;