---
title: "Lesson 3.2 - Make the World Whiz By"
content_type: tutorial
url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by?language=en"
language: en
difficulty: beginner
duration_minutes: 70
unity_version:
  - "6.0"
  - "6.3"
supported_unity_versions:
  - name: "6.0"
    url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by.md?language=en&version=6.0"
  - name: "6.3"
    url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by.md?language=en&version=6.3"
  - name: "2022.3"
    url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by.md?language=en&version=2022.3"
  - name: "2021.3"
    url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by.md?language=en&version=2021.3"
available_languages:
  - name: "en"
    url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by.md?language=en"
  - name: "es"
    url: "https://learn.unity.com/tutorial/leccion-3-2-haz-que-el-mundo-pase-volando.md?language=es"
  - name: "ja"
    url: "https://learn.unity.com/tutorial/lesson-3-2-make-the-world-whiz-by-jp.md?language=ja"
  - name: "ko"
    url: "https://learn.unity.com/tutorial/3-2gang-weoldeuga-bbareuge-jinagadorog-guhyeon.md?language=ko"
last_updated: "2026-08-04T14:23:00.000Z"
---

# Lesson 3.2 - Make the World Whiz By

Implement a looping background, obstacle cleanup, and collision-based game over using script communication in your runner game.

**Overview:**

We’ve got the core mechanics of this game figured out: The player can tap the spacebar to jump over incoming obstacles. However, the player appears to be running for the first few seconds, but then the background just disappears! In order to fix this, we need to repeat the background seamlessly to make it look like the world is rushing by! We also need the game to halt when the player collides with an obstacle, stopping the background from repeating and stopping the obstacles from spawning. Lastly, we must destroy any obstacles that get past the player.

**Project Outcome:**

The background moves flawlessly at the same time as the obstacles, and the obstacles will despawn when they exit game boundaries. With the power of script communication, the background and spawn manager will halt when the player collides with an obstacle. Colliding with an obstacle will also trigger a game over message in the console log, halting the background and the spawn manager.

Overview: [Video](https://connect-mediagw.unity.com/h1/20241205/videos/89db90b3-1012-48be-9179-988b54b53d98_CWC_U3.L2.S0_Intro_U6mp4.mp4) ([Transcript (en)](https://connect-mediagw.unity.com/h1/20241205/3527319d-e8af-41db-a271-4e268304c40d_CWC_U3.L2.S0_Intro_U6mp4.mp4.vtt))

## 1. Create a script to repeat background

We need to repeat the background and move it left at the same speed as the obstacles, to make it look like the world is rushing by. Thankfully we already have a move left script, but we will need a new script to make it repeat.

[Video](https://connect-mediagw.unity.com/h1/20241205/videos/dba9f53b-2849-4d70-9b64-15674e05965a_CWC_U3.L2.S1_U6.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgQ7S%22%5D.body%5B_key==%22JpI72pm885s7ezHBZkgQ9s%22%5D.subtitles/CWC_U3.L2.S1_U6.mp4_20260505_043810.srt))

1. Create a new script called **RepeatBackground.cs** and attach it to the **Background Object**

## 2. Reset position of background

In order to repeat the background and provide the illusion of a world rushing by, we need to reset the background object’s position so it fits together perfectly.

[Video](https://connect-mediagw.unity.com/h1/20241205/videos/4475a4aa-a6b2-491d-b030-c6c880fe06e2_CWC_U3.L2.S2_U6.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgQH8%22%5D.body%5B_key==%22JpI72pm885s7ezHBZkgQJY%22%5D.subtitles/CWC_U3.L2.S2_U6.mp4_20260505_043826.srt))

1. Declare a new variable **_private Vector3 startPos;_**
2. In **_Start()_**, set the **_startPos_** variable to its actual starting position by assigning it  **_= transform.position;_**
3. In **_Update()_**, write an **if-statement** to reset position if it moves a certain distance

![](https://connect-mediagw.unity.com/h1/20190522/learn/images/15a868a0-f936-4758-a663-90a761d10ad1_3_2_2.png)

## 3. Fix background repeat with collider

We’ve got the background repeating every few seconds, but the transition looks pretty awkward. We need to make the background loop perfectly and seamlessly with some new variables.

[Video](https://connect-mediagw.unity.com/h1/20241205/videos/cae55e6c-b91f-4511-a9b7-01da25be0c6a_CWC_U3.L2.S3_U6.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgQcu%22%5D.body%5B_key==%22JpI72pm885s7ezHBZkgQfK%22%5D.subtitles/CWC_U3.L2.S3_U6.mp4_20260505_043842.srt))

1. Add a **Box Collider** component to the **Background**
2. Declare a new **_private float repeatWidth_** variable
3. In **_Start()_**, get the width of the **box collider**, divided by 2
4. Incorporate the **_repeatWidth_** variable into the **repeat function**

![](https://connect-mediagw.unity.com/h1/20190522/learn/images/21b03d3e-7de7-403f-8dbd-4dedcf0acd51_3_2_3.png)

## 4. Add a new game over trigger

When the player collides with an obstacle, we want to trigger a “Game Over” state that stops everything. In order to do so, we need a way to label and discern all game objects that the player collides with.

[Video](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgR2J%22%5D.body%5B_key==%22eaddcf6d27d4%22%5D.overviewVideo/Unit%203.2%20-%20Step%204%20-%20Add%20a%20new%20game%20over%20trigger%20%28NO%20VO%29%20-%20FINAL%20RENDER_20260622_194952.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgR2J%22%5D.body%5B_key==%22eaddcf6d27d4%22%5D.subtitles/Unit%203.2%20-%20Step%204%20-%20Add%20a%20new%20game%20over%20trigger%20%28NO%20VO%29%20-%20FINAL%20RENDER_20260622_194952_20260623_013235.vtt))

1. In the inspector, add a “Ground” tag to the **Ground** and an “Obstacle” tag to the **Obstacle prefab**
2. In PlayerController, declare a new **public bool gameOver;**
3. In **OnCollisionEnter**, add the **if-else statement** to test if player collided with the “Ground” or an “Obstacle”
4. If they collided with the “Ground”, set **isOnGround = true**, and if they collide with an “Obstacle”, set **gameOver = true**

![](https://connect-mediagw.unity.com/h1/20190523/learn/images/efbbf70f-5cc5-4d27-89e3-3c1b25f0df94_3_2_4.png)

## 5. Stop MoveLeft on gameOver

We’ve added a gameOver bool that seems to work,  but the background and the objects continue to move when they collide with an obstacle. We need the MoveLeft script to communicate with the PlayerController, and stop once the player triggers gameOver.

[Video](https://connect-mediagw.unity.com/h1/20241205/videos/0c8c68da-b424-44cb-a8d5-c12b5a90a721_CWC_U3.L2.S5_U6.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgRVL%22%5D.body%5B_key==%22JpI72pm885s7ezHBZkgRXl%22%5D.subtitles/CWC_U3.L2.S5_U6.mp4_20260505_043932.srt))

1. In **MoveLeft.cs**, declare a new **_private PlayerController playerControllerScript;_**
2. In **_Start()_**, initialize it by finding the **Player** and getting the PlayerController component
3. Wrap the **translate method** in an **if-statement** checking if game is not over

![](https://connect-mediagw.unity.com/h1/20190522/learn/images/5bb36fd0-ebad-441a-8a49-6190ffda6121_3_2_5.png)

## 6. Stop obstacle spawning on gameOver

The background and the obstacles stop moving when gameOver == true, but the Spawn Manager is still raising an army of obstacles! We need to communicate with the Spawn Manager script and tell it to stop when the game is over.

[Video](https://connect-mediagw.unity.com/h1/20241205/videos/89e0db77-e763-4eb1-b8ef-3a1a47823192_CWC_U3.L2.S6_U6.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgRsK%22%5D.body%5B_key==%22JpI72pm885s7ezHBZkgRuk%22%5D.subtitles/CWC_U3.L2.S6_U6.mp4_20260505_043947.srt))

1. In **SpawnManager.cs**, get a reference to the **playerControllerScript** using the same technique you did in MoveLeft.cs
2. Add a condition to only instantiate objects if **_gameOver_** **_== false_**

![](https://connect-mediagw.unity.com/h1/20190522/learn/images/77b2934b-d6e1-407f-8a0c-f8cfdce81115_3_2_6.png)

## 7. Destroy obstacles that exit bounds

Just like the animals in Unit 2, we need to destroy any obstacles that exit boundaries. Otherwise they will slide into the distance… forever!

[Video](https://connect-mediagw.unity.com/h1/20241205/videos/b5ff3bfe-f238-4793-be4c-bfa92712e6c1_CWC_U3.L2.S7_U6.mp4) ([Transcript (en)](https://storage.googleapis.com/learn-platform-bucket-production/tutorial/7b1d0b2a-2dd4-4250-87f3-a44abbb0196e/versions%5B_key==%22f67a09281bac%22%5D.sections%5B_key==%22JpI72pm885s7ezHBZkgS9G%22%5D.body%5B_key==%22JpI72pm885s7ezHBZkgSBg%22%5D.subtitles/CWC_U3.L2.S7_U6.mp4_20260505_044003.srt))

1. In **MoveLeft**, in **_Update()_**; write an if-statement to **Destroy** Obstacles if their position is less than a **_leftBound_** variable
2. Add any **comments** you need to make your code more **readable**

![](https://connect-mediagw.unity.com/h1/20190529/learn/images/ffad50db-b857-44cb-b972-c2d46ae9bc5e_3.2_7.PNG)

## 8. Lesson Recap

## New Functionality

- Background repeats seamlessly
- Background stops when player collides with obstacle
- Obstacle spawning stops when player collides with obstacle
- Obstacles are destroyed off-screen

## New Concepts and Skills:

- Repeat background
- Get Collider width
- Script communication
- Equal to (==) operator
- Tags
- CompareTag()

## Next Lesson:

- Our character, while happy on the inside, looks a little too rigid on the outside, so we’re going to do some work with ANIMATIONS

## Check your scripts

PlayerController.cs

```csharp
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private Rigidbody playerRb;
    public InputAction jumpAction;
    public float jumpForce = 10;
    public float gravityModifier;
    public bool isOnGround = true;
    public bool gameOver = false;


    void Start()
    {
        playerRb = GetComponent<Rigidbody>();
        jumpAction.Enable();
        Physics.gravity *= gravityModifier;
    }

    void Update()
    {
        if (jumpAction.triggered && isOnGround)
        {
            playerRb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            isOnGround = false;
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isOnGround = true;
        }
        else if (collision.gameObject.CompareTag("Obstacle"))
        {
            gameOver = true;
            Debug.Log("Game Over!");
        }
    }
}
```

RepeatBackground.cs

```csharp
using UnityEngine;

public class RepeatBackground : MonoBehaviour
{
    private Vector3 startPos;
    private float repeatWidth;

    void Start()
    {
        startPos = transform.position;
        repeatWidth = GetComponent<BoxCollider>().size.x / 2;
    }

    void Update()
    {
        if (transform.position.x < startPos.x - repeatWidth)
        {
            transform.position = startPos;
        }
    }
}
```

SpawnManager.cs

```csharp
using UnityEngine;

public class SpawnManager : MonoBehaviour
{
    public GameObject obstaclePrefab;
    private Vector3 spawnPos = new Vector3(25, 0, 0);
    private float startDelay = 2;
    private float repeatRate = 2;
    private PlayerController playerControllerScript;

    void Start()
    {
        InvokeRepeating("SpawnObstacle", startDelay, repeatRate);
        playerControllerScript = GameObject.Find("Player").GetComponent<PlayerController>();
    }

    void Update()
    {
        
    }

    void SpawnObstacle()
    {
        if (playerControllerScript.gameOver == false)
        {
            Instantiate(obstaclePrefab, spawnPos, obstaclePrefab.transform.rotation);
        }
    }
}
```

MoveLeft.cs

```
using UnityEngine;

public class MoveLeft : MonoBehaviour
{
    private float speed = 30;
    private PlayerController playerControllerScript;
    private float leftBound = -15;

    void Start()
    {
        playerControllerScript = GameObject.Find("Player").GetComponent<PlayerController>();
    }

    void Update()
    {
        if (playerControllerScript.gameOver == false)
        {
            transform.Translate(Vector3.left * Time.deltaTime * speed);
        }

        if (transform.position.x < leftBound && gameObject.CompareTag("Obstacle"))
        {
            Destroy(gameObject);
        }
    }
}
```
