Menu
CoddyTech

Move the Road

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

In a runner the player stays put and the world comes at it. Moving the camera and the player forward forever would work too, but the numbers would grow without end; moving the road keeps everything near zero.

The speed belongs to the whole game, so it lives in GameManager. The Road finds it once in Start and reads its speed every frame:

float step = game.speed * Time.deltaTime;
foreach (Transform chunk in chunks)
{
    chunk.position += Vector3.back * step;
}

Vector3.back is (0, 0, -1): towards the camera. To move the pieces later the Road has to remember them, in a List<Transform>.

challenge icon

Challenge

Easy
  1. In GameManager add public float startSpeed = 10f; and public float speed;, and set speed = startSpeed in Start.
  2. In Road add private List<Transform> chunks = new List<Transform>(); (with using System.Collections.Generic;) and private GameManager game;.
  3. In Start set game = FindFirstObjectByType<GameManager>(); and add every new piece to chunks.
  4. Write Update 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