Menu
CoddyTech

CharacterController.Move

本课属于 Coddy Unity 学习旅程的“打造真正的游戏”单元。第 38 课,共 60 课。

CharacterController 是 Unity 中用于控制行走角色的组件:它是一个胶囊体,只有在你的脚本调用 controller.Move(motion) 时才会移动。motion 表示这一帧要移动的距离,因此它等于速度乘以 Time.deltaTime。Move 会让胶囊体沿墙壁滑动,而不是穿过墙壁;它可以爬上坡度不超过 Slope Limit(45 degrees)的斜坡,也可以踏上高度不超过 Step Offset(0.3 units)的台阶。它不是 Rigidbody:没有力、重力或反弹,也不会被任何东西推动。它会准确移动到 Move 指定的位置,这正是精确控制游戏角色所需要的。

重力需要你自行添加,寻找地面也是如此。如果上一次 Move 碰到了下方的物体,isGrounded 就为 true,因此不包含向下移动的 Move 永远找不到地面。短于控制器 Min Move Distance(0.001)的 Move 完全不会产生效果,所以,如果控制器只向侧面移动,那么它一停下来,就会报告自己没有接触地面。这个快递员用方向键行走,并在每次移动时稍微向下施压:

public class Courier : MonoBehaviour
{
    public float speed = 6f;
    CharacterController controller;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
        move.y = -2f;   // 始终向下施加一点力,以便检测到地面
        controller.Move(move * Time.deltaTime);
        if (!controller.isGrounded)
        {
            Debug.Log("Off the ground");
        }
    }
}

胶囊体与接触到的物体之间始终保持 Skin Width(0.08)的距离,因此,在 y = 0 的地面上,高度为 2 unit 的控制器会停在 y = 1.08,而不是 y = 1。Move 会从物理系统上一次检测到控制器的位置开始移动,因此,设置控制器的 transform.position 后,下一次 Move 可能会撤销这一设置。要传送控制器,先设置 controller.enabled = false,移动它,然后再启用它。

challenge icon

挑战

中等

用它的 CharacterController 控制 explorer 行走,这样墙就能挡住它。

  1. 在 Update() 中,根据 x 轴上的 Input.GetAxisRaw("Horizontal") 和 z 轴上的 Input.GetAxisRaw("Vertical") 构建 Vector3 move,再乘以 speed。
  2. 设置 move.y = -fallSpeed;,并调用 controller.Move(move * Time.deltaTime);。
  3. 然后,当 controller.isGrounded 为真时,将 rend.material.color 设置为 Color.green,否则设置为 Color.red。

按“开始”,让 explorer 撞上墙,再从左侧边缘走出去:它会变红并落下,着地后变绿。然后点击“检查”。

亲手试试

using UnityEngine;

public class Explorer : MonoBehaviour
{
    public float speed = 4f;
    public float fallSpeed = 3f;

    CharacterController controller;
    Renderer rend;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        rend = GetComponent<Renderer>();
    }

    void Update()
    {
        // 用 controller.Move 移动,然后根据 isGrounded 为探险者设置颜色
    }
}

打造真正的游戏中的所有课

自己练习: Unity 在线编辑器