Menu
CoddyTech

Tái sử dụng con đường

Bài học 7 trên 21 trong khóa học Trò chơi Unity: đường đua trên trời của Coddy.

Bảy đoạn tạo thành 140 đơn vị đường. Với tốc độ 10 đơn vị mỗi giây, đường sẽ hết sau 14 giây. Tạo một đoạn mới mỗi khi cần rồi xóa các đoạn cũ cũng được, nhưng có cách tiết kiệm hơn: chuyển đoạn đường đã chạy qua ra phía trước để dùng lại.

Một đoạn đường nằm hoàn toàn phía sau khi điểm giữa của nó vượt qua -chunkLength. Có bảy đoạn xếp thành một hàng, vậy nên di chuyển đoạn đó về phía trước bảy lần chiều dài sẽ đưa nó đến ngay sau đoạn cuối cùng:

if (chunk.position.z < -chunkLength)
{
    chunk.position += Vector3.forward * chunkLength * chunks.Count;
}

Việc dùng lại đối tượng thay vì xóa rồi tạo đối tượng mới gọi là pooling. Bảy đoạn đường tạo thành con đường bất tận.

challenge icon

Thử thách

Dễ

Tái sử dụng mỗi đoạn đường khi nó chạy qua phía sau nhân vật chạy.

  1. Trong Road.Update, sau khi một đoạn di chuyển, hãy kiểm tra xem chunk.position.z < -chunkLength hay không.
  2. Nếu có, hãy di chuyển đoạn đó về phía trước một khoảng bằng chunkLength * chunks.Count, như trên.

Nhấn Chơi và chờ 15 giây: đường chạy không bao giờ hết. Sau đó nhấn Kiểm tra.

Tự làm thử

using UnityEngine;

public class Runner : MonoBehaviour
{
    public float laneWidth = 2.5f;
    public float laneSpeed = 16f;
    public float jumpHeight = 1.6f;
    public float gravity = -40f;
    public float slideTime = 0.7f;

    public int lane;

    private CharacterController controller;
    private float fallSpeed;
    private float slide;

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

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) lane = Mathf.Max(-1, lane - 1);
        if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) lane = Mathf.Min(1, lane + 1);
        bool jump = Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space);
        if (jump && controller.isGrounded)
        {
            fallSpeed = Mathf.Sqrt(jumpHeight * -2f * gravity);
            StopSlide();
        }
        if ((Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow)) && controller.isGrounded)
        {
            slide = slideTime;
            Resize(0.5f);
        }

        if (slide > 0f)
        {
            slide -= Time.deltaTime;
            if (slide <= 0f) StopSlide();
        }

        if (controller.isGrounded && fallSpeed < 0f) fallSpeed = -2f;
        fallSpeed += gravity * Time.deltaTime;

        float targetX = lane * laneWidth;
        float x = Mathf.MoveTowards(transform.position.x, targetX, laneSpeed * Time.deltaTime);
        Vector3 move = new Vector3(x - transform.position.x, fallSpeed * Time.deltaTime, 0f);
        controller.Move(move);
    }

    void StopSlide()
    {
        if (transform.localScale.y < 1f) Resize(1f);
        slide = 0f;
    }

    void Resize(float height)
    {
        controller.enabled = false;
        transform.position += Vector3.up * (height - transform.localScale.y);
        transform.localScale = new Vector3(1f, height, 1f);
        controller.enabled = true;
    }
}

Tất cả bài học trong Trò chơi Unity: đường đua trên trời

Tự luyện tập: Playground Unity