Menu
CoddyTech

Đi trên bệ

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 51 trên 60.

CharacterController không di chuyển theo bề mặt mà nó đứng trên: khi đứng trên một bệ di động, nó vẫn đứng yên tại chỗ, còn bệ trượt đi bên dưới. Thay đổi transform.position không giúp ích, vì lần gọi Move tiếp theo bắt đầu từ vị trí mà hệ thống vật lý ghi nhận lần trước và hoàn tác thay đổi đó.

Vì vậy, nhân vật cộng chuyển động của bệ vào chuyển động của chính mình. OnControllerColliderHit(ControllerColliderHit hit) chạy cho từng collider mà Move chạm vào; một va chạm từ bên dưới có hit.normal.y gần bằng 1. Một chiếc phà chở thùng hàng theo cách tương tự:

private Ferry ferry;

void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.normal.y > 0.7f && hit.gameObject.TryGetComponent(out Ferry f))
    {
        ferry = f;
    }
}
challenge icon

Thử thách

Trung bình

Giúp nhân vật di chuyển trên bục di động.

  1. Trong Player, thêm private MovingPlatform platform; và OnControllerColliderHit: khi hit.normal.y > 0.5f và đối tượng có MovingPlatform, hãy lưu đối tượng đó vào platform.
  2. Trong Update(), đặt (move + velocity) * Time.deltaTime vào Vector3 motion. Nếu platform != null, hãy cộng platform.delta và đặt platform = null.
  3. Gọi controller.Move(motion).

Nhấn Chơi rồi nhảy lên bục di động: bục sẽ đưa bạn đi. Sau đó, nhấn Kiểm tra.

Tự làm thử

using UnityEngine;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
    [SerializeField] private float speed = 5f;
    [SerializeField] private float jumpHeight = 1.5f;
    [SerializeField] private float gravity = -9.81f;

    private CharacterController controller;
    private InputAction moveAction;
    private InputAction jumpAction;
    private Vector3 velocity;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        moveAction = InputSystem.actions.FindAction("Move");
        jumpAction = InputSystem.actions.FindAction("Jump");
    }

    void Update()
    {
        if (controller.isGrounded && velocity.y < 0f)
        {
            velocity.y = -2f;
        }

        Vector2 input = moveAction.ReadValue<Vector2>();
        Vector3 move = new Vector3(input.x, 0f, input.y) * speed;

        if (jumpAction.WasPressedThisFrame() && controller.isGrounded)
        {
            velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
        }

        velocity.y += gravity * Time.deltaTime;
        controller.Move((move + velocity) * Time.deltaTime);
    }
}

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