Menu
CoddyTech

Crash

Lesson 11 of 20 in Coddy's Unity Game: Sky Lanes course.

The obstacles are triggers: they detect the runner without pushing it. When the runner's CharacterController and a trigger meet, Unity calls OnTriggerEnter on the runner's scripts, with the trigger's collider:

void OnTriggerEnter(Collider other)
{
    if (game.over) return;
    if (other.CompareTag("Obstacle"))
    {
        game.GameOver();
    }
}

GameOver ends the run: over becomes true, the speed goes to 0 so the road stops, and the message in the middle of the screen says so. While over is true the GameManager stops counting the distance and the Runner stops reading the keys.

challenge icon

Challenge

Medium
  1. In GameManager add public TMP_Text messageText; and public bool over;.
  2. Add public void GameOver(): if already over, return; otherwise set over = true, speed = 0f and messageText.text = "Game over".
  3. At the top of GameManager's Update, if (over) return;.
  4. In Runner, find the GameManager in Start, read the keys only while !game.over, and add OnTriggerEnter as above.

Try it yourself

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

All lessons in Unity Game: Sky Lanes

Practice on your own: Unity playground