Menu
CoddyTech

CharacterController.Move

Thuộc phần Xây dựng trò chơi thực tế trong hành trình Unity của Coddy. Bài học 38 trên 60.

CharacterController là thành phần của Unity dành cho nhân vật đi bộ: một hình trụ chỉ di chuyển khi tập lệnh gọi controller.Move(motion). motion là quãng đường cần di chuyển trong khung hình này, tức là tốc độ nhân với Time.deltaTime. Move giúp hình trụ trượt dọc theo tường thay vì xuyên qua chúng, đi lên các mặt dốc có độ dốc tối đa bằng Slope Limit (45 độ) và bước lên các bậc cao tối đa bằng Step Offset (0.3 đơn vị). Đây không phải là Rigidbody: không có lực, không có trọng lực, không nảy và không có gì đẩy nó. Nó đi chính xác đến nơi Move đưa tới, phù hợp với kiểu điều khiển game cần độ chính xác cao.

Bạn cần tự thêm trọng lực và tìm mặt đất. isGrounded là true khi lần Move gần nhất chạm vào vật gì đó bên dưới, vì vậy một lần di chuyển không có thành phần hướng xuống sẽ không tìm thấy mặt đất. Lệnh Move có độ dài nhỏ hơn Min Move Distance của bộ điều khiển (0.001) sẽ không làm gì cả, nên nếu bộ điều khiển chỉ di chuyển ngang, nó sẽ báo rằng nhân vật không chạm đất ngay khi đứng yên. Nhân viên giao hàng này di chuyển bằng các phím mũi tên và luôn ấn xuống một chút trong mỗi lần di chuyển:

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;   // Luôn đẩy xuống để phát hiện mặt sàn
        controller.Move(move * Time.deltaTime);
        if (!controller.isGrounded)
        {
            Debug.Log("Off the ground");
        }
    }
}

Hình trụ luôn cách vật mà nó chạm vào một khoảng bằng Skin Width (0.08), vì vậy bộ điều khiển cao 2 đơn vị đứng trên mặt đất tại y = 0 sẽ ở y = 1.08, không phải 1. Move bắt đầu từ vị trí mà hệ thống vật lý ghi nhận bộ điều khiển lần gần nhất, nên lệnh đặt transform.position có thể bị hoàn tác trong lần Move tiếp theo: để dịch chuyển tức thời, hãy đặt controller.enabled = false, di chuyển nó rồi bật lại.

challenge icon

Thử thách

Trung bình

Di chuyển nhà thám hiểm bằng CharacterController để bức tường chặn lại.

  1. Trong Update(), tạo Vector3 move từ Input.GetAxisRaw("Horizontal") trên trục x và Input.GetAxisRaw("Vertical") trên trục z, rồi nhân với speed.
  2. Đặt move.y = -fallSpeed; và gọi controller.Move(move * Time.deltaTime);.
  3. Sau đó, đặt rend.material.color thành Color.green khi controller.isGrounded đúng, nếu không thì đặt thành Color.red.

Nhấn Chơi, đi vào tường rồi bước khỏi mép trái: nhà thám hiểm rơi xuống với màu đỏ và tiếp đất với màu xanh lá. Sau đó nhấn Kiểm tra.

Tự làm thử

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()
    {
        // Di chuyển bằng controller.Move, rồi tô màu nhân vật khám phá dựa trên isGrounded
    }
}

Tất cả bài học trong Xây dựng trò chơi thực tế

Tự luyện tập: Playground Unity