Menu
CoddyTech

Nhanh hơn nữa

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

Trò chơi chạy bất tận luôn hấp dẫn vì độ khó tăng dần. Hãy đếm thời gian lượt chạy, rồi tăng tốc độ theo thời gian, đến khi đạt tốc độ tối đa:

runTime += Time.deltaTime;
speed = Mathf.Min(maxSpeed, startSpeed + speedUp * runTime);

Tốc độ tăng từ 10 với mức 0.25 mỗi giây và đạt 24 sau 56 giây. Tốc độ tối đa không chỉ ảnh hưởng đến độ khó: ở tốc độ 24 đơn vị mỗi giây, con đường di chuyển 0.4 đơn vị mỗi khung hình, vẫn ít hơn chiều rộng của nhân vật chạy, nên nhân vật không thể lọt xuyên qua chướng ngại vật giữa hai khung hình.

challenge icon

Thử thách

Dễ

Khi bạn chạy càng lâu, hãy tăng tốc độ của đường.

  1. Thêm public float maxSpeed = 24f;, public float speedUp = 0.25f; và public float runTime; vào GameManager.
  2. Trong Update, hãy tăng runTime trước khi tính quãng đường và đặt tốc độ như trên.

Nhấn Chơi và tiếp tục chạy: đường sẽ nhanh hơn. 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 float magnetTime = 8f;

    public int lane;
    public float magnet;
    public bool shield;

    private CharacterController controller;
    private GameManager game;
    private Renderer body;
    private float fallSpeed;
    private float slide;
    private Color color;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        game = FindFirstObjectByType<GameManager>();
        body = GetComponent<Renderer>();
        color = body.material.color;
    }

    void Update()
    {
        if (!game.over)
        {
            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 (magnet > 0f) magnet -= Time.deltaTime;

        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);

        body.material.color = shield ? new Color(0.3f, 0.9f, 1f) : color;
        ShowPower();
    }

    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;
    }

    void ShowPower()
    {
        string text = "";
        if (magnet > 0f) text = "Magnet " + Mathf.CeilToInt(magnet);
        if (shield) text += (text == "" ? "" : "   ") + "Shield";
        game.powerText.text = text == "" ? " " : text;
    }

    void OnTriggerEnter(Collider other)
    {
        if (game.over) return;
        if (other.CompareTag("Obstacle"))
        {
            if (shield)
            {
                shield = false;
                Destroy(other.gameObject);
                return;
            }
            game.GameOver();
        }
        else if (other.CompareTag("Coin"))
        {
            game.AddCoin();
            Destroy(other.gameObject);
        }
        else if (other.CompareTag("Magnet"))
        {
            magnet = magnetTime;
            Destroy(other.gameObject);
        }
        else if (other.CompareTag("Shield"))
        {
            shield = true;
            Destroy(other.gameObject);
        }
    }
}

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