In order to complete the experience of playing the game, we need to finish the background for the scene and use the Unity 5 UI system to show the players what is going on with the game, as well as allow them to restart the game when they die.
The background is going to be made up of four images: a static (nonmoving) background, clouds that will hover, and two sets of mountains that will move to make the player movement seem more real.
The Unity 5 UI system is made up of a panel object that will hold children, such as text and buttons, to display what is currently going on in the game to the user. For the game, we will display a unit number that represents how far the player has moved and keep a tally of how many coins the player has picked up. We will also display a restart button the user can tap when they die, restarting the game loop.
In this chapter, we will cover the following topics:
To start with, we will need a C# script.
Perform the following steps:
Assets/Scripts
folder and right-click on it.SceneBackground
.SceneBackground
file to open it.The SceneBackground
file will hold four sprites. Each of these sprites will have their own movement speed and movement distance (speed being how fast they move and distance is how far forward and backward they can move).
Add the following code to the SceneBackground
file before the Start
function:
// Struct to hold data for Background Element [System.Serializable] public struct BackgroundElement { public Sprite BackgroundSprite; public float MovementSpeed; public float MovementDistance; public Vector3 SpriteLocation; public Vector3 SpriteScale; [System.NonSerialized] public Vector3 ObjectStartLocation; [System.NonSerialized] public GameObject ChildObject; [System.NonSerialized] public bool bMoveBackwards; }; // Array to store backgrounds for scene public BackgroundElement[ ] SceneBackgroundElement;
The BackgroundElement
struct is a way for us to create a sprite and manage its MovementSpeed
and MovementDirection
without having to create individual variables for all of them. This way, we can compartmentalize the data into a single struct object and assign the values we need with less code clutter. Then, with the SceneBackgroundElement
array, we can create and assign the background images with unique settings to handle them correctly.
[System.Serializable]
allows you to edit these variables in the editor. Without this, the variables will not be shown in the Inspector window when you select the GameObject from the Hierarchy or Project folder(s).
Save the SceneBackground
code file and go back to Unity. Right-click on Hierarchy and then select Create Empty. Name this SceneBackground
.
In the Inspector window, with the new SceneBackground GameObject selected in Hierarchy, click on Add Component. Search for SceneBackground
and select SceneBackground.
You should see a drop-down list for Scene Background Element with zero elements. Set the number of elements to four. You should now see the empty elements for Scene Background Element:
In order to set all of these, we need to import the art for them. In the Assets
folder, right-click and select Create and then Folder. Name this Background
.
Open the Background
folder and right-click on it. Then, click on Import New Asset…. Navigate to the book art files and find the folder named ChapterFive_Background
. Import all the four images.
This includes:
Background_00
Background_01
Background_02
Background_03
Select all the four images in the Assets/Background
folder. Then, in the Inspector window, perform the following steps:
1024
.With the SceneBackground GameObject selected in Hierarchy, click on the drop-down list for the 0 element of the SceneBackground script component.
In the Sprite object slot, click on the small circle with a dot. When the window opens, select the sprite object, search for Background_00
and then select Background_00
. Change the Sprite Location to 0X
, 0Y
, and 0Z
; then, set the Sprite Scale
to 1X
, 1Y
, and 1Z
. Leave Movement Speed and Movement Distance as zero.
Next, we want to set the second element: clouds. Again, with the SceneBackground GameObject selected, take at look at the Inspector tab and click on the 1or 2 element drop-down list so that you change the settings as follows:
Background_01
.0
.0
.5.65
, Y to 1.95
, and Z to 40
.0.2
, Y to 0.2
, and Z to 0.2
.Next element is smaller mountains:
Background_02
.0
.0
.3.45
, Y to 2.25
, and Z to 30
.0.2
, Y to 0.2
, and Z to 0.2
.Finally, for the bigger mountains:
Background_03
.0
.0
.0
, Y to 3.8
, and Z to 45
.1
, Y 1
, and Z to 1
:The following is screenshot showing the settings for all the elements:
We will update the Movement Speed and Movement Distance values after we write the code that handles these values.
For now, let's write the code that will create and place the GameObjects and sprites based on the settings we just created. In the Start
function of the SceneBackground
class, write the following code:
// Use this for initialization void Start ( ) { SpriteRenderer backgroundRenderer; GameObject backgroundObj; for (int i = 0; i < SceneBackgroundElement.Length; i++) { // new GameObject backgroundObj = new GameObject( ); // Parent it, set its position, and scale backgroundObj.transform.SetParent( transform ); backgroundObj.transform.position = SceneBackgroundElement[i].SpriteLocation; backgroundObj.transform.localScale = SceneBackgroundElement[i].SpriteScale; // Keep reference of new object and its start location SceneBackgroundElement[ i ].ChildObject = backgroundObj; SceneBackgroundElement[ i ].ObjectStartLocation = backgroundObj.transform.position; // Create Renderer and set Sprite backgroundRenderer = backgroundObj.AddComponent<SpriteRenderer>(); backgroundRenderer.sprite = SceneBackgroundElement[ i ].BackgroundSprite; } }
As we only have values to use and are not using any direct reference to other GameObjects in the scene for these, we have to create them. To do this, we need a SpriteRenderer and a GameObject to hold it.
We know by the number of elements created by us (or if you were on a bigger team, the designer) in the GameObject SceneBackground
script component that we have to create a certain number of GameObjects to hold the BackgroundSprite
for each of the SceneBackgroundElement
objects. In order to create all of them efficiently, we will use a for
loop that will loop the number of created SceneBackgroundElement
objects.
In each loop, we can create a new GameObject and set its parent using the SetParent
function to transform the GameObject that holds this SceneBackground
script component. We will then set its local position and scale, relative to the parent transform location, to the settings we entered. Then, we will store the new GameObject that was created to the SceneBackgroundElement
of that loop and its location.
After this, add a
SpriteRenderer
component to the newly created GameObject and assign the sprite from the settings we entered to the sprite for SpriteRenderer
.
If you run the game now, you should see a background with some mountains. The clouds will be out of the field of view of the camera. We will fix this by having them move across the screen.
As we want some movement to SceneBackgroundObjects
, we need the code to manage it. In the SceneBackground
class file, change the Update
function, as shown in the following code:
// Update is called once per frame void Update ( ) { for (int i = 0; i < SceneBackgroundElement.Length; i++) { // Does the SceneBackgroundElement move if (SceneBackgroundElement[i].MovementSpeed > 0) { // Get current location and offset it by movement speed, based on bMoveBackwards Vector3 newSceneBackgroundLoc = SceneBackgroundElement[ i ].ChildObject.transform.position; newSceneBackgroundLoc.x += (SceneBackgroundElement[i].bMoveBackwards) ? -SceneBackgroundElement[i].MovementSpeed * Time.deltaTime : SceneBackgroundElement[i].MovementSpeed * Time.deltaTime; // Set location based on movement speed offset SceneBackgroundElement[ i ].ChildObject.transform.position = newSceneBackgroundLoc; // If ChildObject has moved farther than move distance, have it move the other way. if (Vector3.Distance(SceneBackgroundElement[i].ChildObject.transform.position, SceneBackgroundElement[i].ObjectStartLocation) >= SceneBackgroundElement[i].MovementDistance) { // Change the direction of the SceneBackgroundElement SceneBackgroundElement[ i ].bMoveBackwards = !SceneBackgroundElement[ i ].bMoveBackwards; } } } }
We begin the Update
function with a for
loop. The for
loop will loop through the SceneBackgroundElement
struct variables that we created earlier. For each one of the struct elements, we will start by checking whether the MoveSpeed
elements is greater than zero because we do not want to try to move something if it isn't set to move.
Next, we will create a new
Vector3
local variable within the scope of the Update
function named newSceneBackgroundLoc
and assign it to the ChildObject
variable of the element of SceneBackgroundElement
represented by i
. This is the value represented by the current loop.
Once we have the position value of the ChildObject
variable of the current SceneBackgroundElement
variable, we can use the ternary operator to decide which direction the ChildObject
variable needs to be moving in. In addition, it has a rule that if you add a negative value to a positive value, it is subtracted. Then, we can use the +=
operator to assign a negative value to the offset of newSceneBackgroundLoc.x
if the bMoveBackward
bool value is true
. If it is not true
, we can then assign a positive value because positive plus positive is still positive. We multiply the negative or positive MovementSpeed
value by Time.deltaTime
, making the transition between movements a bit smoother.
We can then assign the SceneBackgroundObject[ i ].ChildObject
position to the newSceneBackgroundLoc
offset position, moving the ChildObject
variable to whatever the MovementSpeed
value is set to.
Once the ChildObject
variable has been moved, we need to check whether the current distance from the start location is greater than the MovementDistance
value of the current SceneBackgroundObject
. If it is, we flip the bMoveBackwards
value, making the previous ternary operator begin calculating the newSceneBackgroundLoc
value in the opposite direction.
Let's go back to the Unity editor and change the movement values for the SceneBackgroundElements
as follows:
In Element0:
0.2
2
In Element1:
1
6
In Element2:
0.2
4
In Element3:
0.2
4
If you play the game now, you will see a lot more movement with the SceneBackgroundElements
. Feel free to adjust these values to anything you want. The values are literal, meaning the larger the number, the farther/faster the object will change.