Reader small image

You're reading from  Unity 2022 Mobile Game Development - Third Edition

Product typeBook
Published inJun 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781804613726
Edition3rd Edition
Languages
Tools
Right arrow
Author (1)
John P. Doran
John P. Doran
author image
John P. Doran

John P. Doran is a passionate and seasoned Technical Game Designer, Software Engineer, and Author who is based in Incheon, South Korea. His passion for game development began at an early age. He later graduated from DigiPen Institute of Technology with a Bachelor of Science in Game Design. For over a decade, John has gained extensive hands-on expertise in game development working in various roles ranging from game designer to lead UI programmer working in teams consisting of just himself to over 70 people in student, mod, and professional game projects including working at LucasArts on Star Wars: 1313. Additionally, John has worked in game development education teaching in Singapore, South Korea, and the United States. To date, he has authored over 10 books pertaining to game development. John is currently a Technical Game Design Instructor at George Mason University Korea. Prior to his present ventures, he was an award-winning videographer.
Read more about John P. Doran

Right arrow

Creating obstacles

It’s great that we have some basic tiles, but it’s a good idea to give the player something to do, or in our case, something to avoid. This will provide the player with some kind of challenge and a basic gameplay goal, which is avoiding obstacles here. In this section, you’ll learn how to customize your tiles to add obstacles for your player to avoid. So, let’s look at the steps:

  1. Just like we created a prefab for our basic tile, we will create a single obstacle through code. I want to make it easy to see what the obstacle will look like in the world and make sure that it’s not too large, so I’ll drag and drop a Basic Tile prefab back into the world.
  2. Next, we will create a cube by going to GameObject | 3D Object | Cube. We will name this object Obstacle. Change the Scale value of Y to 2 and position it above the platform at (0, 1, 0.25):
Figure 1.27 – Adding obstacles

Figure 1.27 – Adding obstacles

  1. We can then play the game to see how that’ll work:

Figure 1.28 – Obstacles stop the player

Figure 1.28 – Obstacles stop the player

  1. As you can see in the preceding screenshot, the player gets stopped, but nothing really happens. In this instance, we want the player to lose when they hit this obstacle and then restart the game; to do that, we’ll need to write a script. From the Project window, go to the Scripts folder and create a new script called ObstacleBehaviour. We’ll use the following code:
    using UnityEngine;
    using UnityEngine.SceneManagement; // LoadScene
    public class ObstacleBehaviour : MonoBehaviour
    {
        [Tooltip("How long to wait before restarting the
            game")]
        public float waitTime = 2.0f;
        private void OnCollisionEnter(Collision collision)
        {
            // First check if we collided with the player
            if (collision.gameObject.GetComponent
            <PlayerBehaviour>())
            {
                // Destroy the player
                Destroy(collision.gameObject);
                // Call the function ResetGame after
                // waitTime has passed
                Invoke("ResetGame", waitTime);
            }
        }
        /// <summary>
        /// Will restart the currently loaded level
        /// </summary>
        private void ResetGame()
        {
            // Get the current level's name
            string sceneName =
                SceneManager.GetActiveScene().name;
            // Restarts the current level
            SceneManager.LoadScene(sceneName);
        }
    }
  2. Save the script and return to the editor, attaching the script to the Obstacle GameObject we just created.
  3. Save your scene and try the game:
Figure 1.29 – Obstacles destroy the player

Figure 1.29 – Obstacles destroy the player

As you can see in the preceding screenshot, once we hit the obstacle, the player gets destroyed, and then after a few seconds, the game starts up again. You’ll learn how to use particle systems and other things to polish this up, but at this point, it’s functional, which is what we want.

  1. Now that we know it works correctly, we can make it a prefab. Just as we did with the original tile, go ahead and drag and drop the Obstacle object from Hierarchy into the Project tab and into the Prefabs folder:
Figure 1.30 – Creating the Obstacle prefab

Figure 1.30 – Creating the Obstacle prefab

  1. Next, we will remove the Obstacle object, as we’ll spawn it upon creating the tile. To do so, select the Obstacle object in the Hierarchy window and then press the Delete key.
  2. We will make markers to indicate where we would possibly like to spawn our obstacles. Expand the Basic Tile object to show its children and then duplicate the Next Spawn Point object and move the new one’s Position to (0, 1, 4). We will then rename the object Center.
  3. Afterward, to help see the objects within the Scene window, go to the Inspector window and click on the gray cube icon, and then on the Select Icon menu, select whichever of the color options you’d like (I went with blue). Upon doing this, you’ll see that we can see the text inside the editor if we are close to the object (but it won’t show up in the Game tab by default):
Figure 1.31 – Creating a Center marker

Figure 1.31 – Creating a Center marker

  1. We want a way to get all of the potential spawn points we will want in case we decide to extend the project in the future, so we will assign a tag as a reference to make those objects easier to find. To do that, at the top of the Inspector window, click on the Tags dropdown and select Add Tag.... From the menu that pops up, press the + button and then name it ObstacleSpawn:
Figure 1.32 – Creating the ObstacleSpawn tag

Figure 1.32 – Creating the ObstacleSpawn tag

  1. Go back and select the Center object and assign the Tag property to ObstacleSpawn:
Figure 1.33 – Assigning the tag to the Center object

Figure 1.33 – Assigning the tag to the Center object

Note

For more information on tags and why we’d want to use them, check out https://docs.unity3d.com/Manual/Tags.html.

  1. Go ahead and duplicate this twice and name the others Left and Right, moving them two units to the left and right of the center to become other possible obstacle points:
Figure 1.34 – Creating the Left and Right markers

Figure 1.34 – Creating the Left and Right markers

  1. Note that these changes don’t affect the original prefab, by default; that’s why the objects are currently black text. To make this happen, select Basic Tile, and then in the Inspector window under the Prefab section, click on Overrides and select Apply All:
Figure 1.35 – Applying changes to the prefab

Figure 1.35 – Applying changes to the prefab

  1. Now that the prefab is set up correctly, we can go ahead and remove it by selecting it in the Hierarchy window and pressing Delete.
  2. We then need to go into the GameManager script and make some modifications. To start with, we will need to introduce some new variables:
    /// <summary>
    /// Manages the main gameplay of the game
    /// </summary>
    public class GameManager : MonoBehaviour
    {
        [Tooltip("A reference to the tile we want to
            spawn")]
        public Transform tile;
        [Tooltip("A reference to the obstacle we want to
            spawn")]
        public Transform obstacle;
        [Tooltip("Where the first tile should be placed
            at")]
        public Vector3 startPoint = new Vector3(0, 0, -5);
        [Tooltip("How many tiles should we create in
            advance")]
        [Range(1, 15)]
        public int initSpawnNum = 10;
        [Tooltip("How many tiles to spawn with no
            obstacles")]
        public int initNoObstacles = 4;

The first of these variables is a reference to the obstacle that we will be creating copies of. The second is a parameter of how many tiles should be spawned before spawning obstacles. This is to ensure that the player can see the obstacles before they need to avoid them.

  1. Then, we need to modify the SpawnNextTile function in order to spawn obstacles as well:
    /// <summary>
    /// Will spawn a tile at a certain location and setup
    /// the next position
    /// </summary>
    /// <param name="spawnObstacles">If we should spawn an
    /// obstacle</param>
    public void SpawnNextTile(bool spawnObstacles = true)
    {
        var newTile = Instantiate(tile, nextTileLocation,
                                  nextTileRotation);
        // Figure out where and at what rotation we should
        // spawn the next item
        var nextTile = newTile.Find("Next Spawn Point");
        nextTileLocation = nextTile.position;
        nextTileRotation = nextTile.rotation;
        if (spawnObstacles)
        {
            SpawnObstacle(newTile);
        }
    }

Note that we modified the SpawnNextTile function to now have a default parameter set to true, which will tell us whether we want to spawn obstacles or not. At the beginning of the game, we may not want the player to have to start dodging immediately, but we can tweak the value to increase or decrease the number we are using. Because it has a default value of true, the original version of calling this in the Start function will still work without an error, but we will be modifying it later on.

  1. Here, we ask whether the value is true to call a function called SpawnObstacle, but that isn’t written yet. We will add that next, but first, we will be making use of the List class and we want to make sure that the compiler knows which List class we are referring to, so we need to add a using statement at the top of the file:
    using UnityEngine;
    using System.Collections.Generic; // List
  2. Now we can write the SpawnObstacle function. Add the following function to the script:
    private void SpawnObstacle(Transform newTile)
    {
        // Now we need to get all of the possible places
        // to spawn the obstacle
        var obstacleSpawnPoints = new List<GameObject>();
        // Go through each of the child game objects in
        // our tile
        foreach (Transform child in newTile)
        {
            // If it has the ObstacleSpawn tag
            if (child.CompareTag("ObstacleSpawn"))
            {
                // We add it as a possibility
                obstacleSpawnPoints.Add(child.gameObject);
            }
        }
        // Make sure there is at least one
        if (obstacleSpawnPoints.Count > 0)
        {
            // Get a random spawn point from the ones we
            // have
            int index = Random.Range(0,
                obstacleSpawnPoints.Count);
            var spawnPoint = obstacleSpawnPoints[index];
            // Store its position for us to use
            var spawnPos = spawnPoint.transform.position;
            // Create our obstacle
            var newObstacle = Instantiate(obstacle,
                spawnPos, Quaternion.identity);
            // Have it parented to the tile
            newObstacle.SetParent(spawnPoint.transform);
        }
    }
  3. Lastly, let’s update the Start function:
    /// <summary>
    /// Start is called before the first frame update
    /// </summary>
    private void Start()
    {
        // Set our starting point
        nextTileLocation = startPoint;
        nextTileRotation = Quaternion.identity;
        for (int i = 0; i < initSpawnNum; ++i)
        {
            SpawnNextTile(i >= initNoObstacles);
        }
    }

Now, as long as i is less than the value of initNoObstacles, it will not spawn a variable, effectively giving us a buffer of four tiles that can be adjusted by changing the initNoObstacles variable.

  1. Save the script and go back to the Unity Editor. Then, assign the Obstacle variable of the Game Manager (Script) component in the Inspector window with the Obstacle prefab we created previously:
Figure 1.36 – Assigning the Obstacle property

Figure 1.36 – Assigning the Obstacle property

  1. It’s a bit hard to see things currently due to the default light settings, so let’s go to the Hierarchy window and select the Directional Light object. A directional light acts similar to how the Sun works on Earth, shining everywhere from a certain position.
  2. With the default settings, the light is a bit too bright and the shadows are too dark by default, so in the Inspector window, I changed Intensity to 0.5 and then the Realtime Shadows | Strength property to 0.5:
Figure 1.37 – Adjusting the Directional Light

Figure 1.37 – Adjusting the Directional Light

  1. Save your scene and play the game:
Figure 1.38 – The current state of the game

Figure 1.38 – The current state of the game

As you can see in the preceding screenshot, we now have a number of obstacles for our player to avoid!

Note

For more information on directional lights and the other lighting types that Unity has, check out https://unity3d.com/learn/tutorials/topics/graphics/light-types?playlist=17102.

Previous PageNext Page
You have been reading a chapter from
Unity 2022 Mobile Game Development - Third Edition
Published in: Jun 2023Publisher: PacktISBN-13: 9781804613726
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
John P. Doran

John P. Doran is a passionate and seasoned Technical Game Designer, Software Engineer, and Author who is based in Incheon, South Korea. His passion for game development began at an early age. He later graduated from DigiPen Institute of Technology with a Bachelor of Science in Game Design. For over a decade, John has gained extensive hands-on expertise in game development working in various roles ranging from game designer to lead UI programmer working in teams consisting of just himself to over 70 people in student, mod, and professional game projects including working at LucasArts on Star Wars: 1313. Additionally, John has worked in game development education teaching in Singapore, South Korea, and the United States. To date, he has authored over 10 books pertaining to game development. John is currently a Technical Game Design Instructor at George Mason University Korea. Prior to his present ventures, he was an award-winning videographer.
Read more about John P. Doran