How to Make a Game Like Jetpack Joyride in Unity 2D – Part 2

Kirill Muzykov

This is the second part of tutorial about How to create a game like Jetpack Joyride in Unity 2D. If you’ve missed the first part, you can find it here.

In the first part of this tutorial series you created a game with a mouse flying up and down in a room. Oh, and don’t forget the flames, they look nice ;] Although the fire is fun to look at, simply adding jetpack flames doesn’t make a good game.

In this part of the tutorial series you’re going to move the mouse forward through randomly generated rooms simulating an endless level. In addition, you’ll add a fun animation to make the mouse run when it is grounded.

Getting started

If you completed the first part of this tutorial series you can continue working with your own project. Alternatively you can download the starter project for this part of tutorial here: RocketMouse_Final_Part1

Find your project or download and unpack the final project for the first part. Then find and open the RocketMouse.unity scene.

rocket_mouse_unity_p2_0

Making the Mouse Fly Forward

It is time to move forward, literally. To make the mouse fly forward you will need to do two things.

  • Make the mouse actually move.
  • Make the camera follow the mouse.

Adding a bit of code solves both tasks.

Setting the Mouse Velocity

That’s easy. Open the MouseController script and add following public variable:

public float forwardMovementSpeed = 3.0f;

It will define how fast the mouse moves forward.

Note: Once again, by making it a public variable you’re giving yourself an opportunity to adjust the speed from Unity without opening the script in MonoDevelop.

rocket_mouse_unity_p2_26

After that add the following code at the end of FixedUpdate:

Vector2 newVelocity = rigidbody2D.velocity;
newVelocity.x = forwardMovementSpeed;
rigidbody2D.velocity = newVelocity;

This code simply sets the velocity x-component without making any changes to y-component. It is important to update only the x-component, since the y-component is controlled by the jetpack force.

Run the scene. The mouse moves forward, but there is a problem. At some point the mouse just leaves the screen.

rocket_mouse_unity_p2_23

To fix this you need to make the camera follow the mouse.

Making the Camera Follow the Player

Create a new C# Script named CameraFollow. Drag it over the Main Camera in the Hierarchy to add it as a component.

Open CameraFollow script in MonoDevelop and add the following public variable:

public GameObject targetObject;

You will assign it to the mouse GameObject in a moment, so that the camera knows which object to follow.

Add the following code to Update:

float targetObjectX = targetObject.transform.position.x;
    
Vector3 newCameraPosition = transform.position;
newCameraPosition.x = targetObjectX;
transform.position = newCameraPosition;

This code simply takes the x-coordinate of the target object and moves the camera to that position.

Note: You only change the x-coordinate of the camera, since you don’t want it to move up or down following the mouse.

Switch back from MonoDevelop to Unity and select Main Camera in the Hierarchy. There is a new property in the CameraFollow script component called Target Object. You will noticed that it is not set to anything.

rocket_mouse_unity_p2_24

To set the Target Object, click on mouse in the Hierarchy and without releasing drag mouse to the Target Object field in the Inspector as shown below:

Note: It is important not to release the mouse button, since if you click on mouse and release the mouse button you will select it and the Inspector will show the mouse properties instead of Main Camera.

Alternatively you can lock the Inspector to the Main Camera by clicking the lock button in the Inspector.

rocket_mouse_unity_p2_25

rocket_mouse_unity_p2_27

Run the scene. This time the camera follows the mouse.

rocket_mouse_unity_p2_28

This is a good news / bad news kinda thing – the good news is the camera follows the mouse! The bad news is that, well, nothing else does! You’ll address this in a moment, but first, you need to give the mouse a little space. He’s a shy sort of fella. :]

Keeping the Camera at the Distance

In most endless run games the player character is not placed at the center of the screen. Instead it is placed somewhere in the middle of the left side of the screen. This is to give the player more time to react and avoid obstacles, collect coins, etc.

To do this, select the mouse in the Hierarchy and set its Position to (-3.5, 0, 0) and run the scene.

rocket_mouse_unity_p2_29

Wait, the mouse is still centered on the screen, but this has nothing to do with the mouse position. This happens because the camera script centers the camera at the target object. This is also why you see the blue background on the left, which you didn’t see before.

To fix this, open the CameraFollow script and add distanceToTarget private variable:

private float distanceToTarget;

Then add the following code to Start:

distanceToTarget = transform.position.x - targetObject.transform.position.x;

This will calculate the initial distance between the camera and the target.

Finally, modify the code in Update to take this distance into account:

void Update () {
	float targetObjectX = targetObject.transform.position.x;
		
	Vector3 newCameraPosition = transform.position;
	newCameraPosition.x = targetObjectX + distanceToTarget;
	transform.position = newCameraPosition;
}

The camera script will now keep the initial distance between the target object and the actual camera. It will also maintain this gap throughout the entire game.

Run the scene. The mouse now remains offset to the left.

rocket_mouse_unity_p2_30

Generating Endless Level

Right now playing the game more then a few seconds doesn’t make much sense. The mouse simply flies out of the room into a blue space.

You could write a script that adds backgrounds, places the floor and the ceiling and finally adds some decorations. However, it is much easier to save the complete room as a Prefab and then instantce the whole room at once.

Note: In a game like Jetpack Joyride, you’ll often see different areas (aquarium, caves, etc.) that are each their own different Prefab. For the purposes of this game, you’ll stick with one.

rocket_mouse_unity_p2_31

Here is an excerpt from Unity documentation regarding Prefabs.

A Prefab is a type of asset — a reusable GameObject stored in Project View. Prefabs can be inserted into any number of scenes, multiple times per scene. When you add a Prefab to a scene, you create an instance of it. All Prefab instances are linked to the original Prefab and are essentially clones of it. No matter how many instances exist in your project, when you make any changes to the Prefab you will see the change applied to all instances.

In other words you add objects to your scene, set their properties, add components like scripts, colliders, rigidbodies and so on. Then you save your object as a Prefab and you can instantiate it as many times as you like with all the properties and components in place.

Creating Room Prefab

You’re going to want your Prefab to contain all the different room elements: the book case, the window, the ceiling, etc. To include all these elements as part of the same Prefab, you’ll first need to add them to a parent object.

To do this, create empty GameObject by choosing GameObject\Create Empty. Then select GameObject in the Hierarchy, and make following changes in the Inspector:

  • Rename it to room1
  • Set its Position to (0, 0, 0)

This is what you should see in the Inspector:
rocket_mouse_unity_p2_32

Note: At this moment it is important to understand that Empty is placed right in the center of the room and at the (0,0,0) point. This is not a coincidence and is done intentionally.

When you add all the room parts into Empty to group them, their positions will become relative to that Empty. Later when you will want to move the whole room by moving Empty it will be much easier to position it knowing that setting the position of the Empty will move the room center at this point.

In other words when you add objects to Empty its current position becomes the pivot point. So it is much easier if the pivot point is at the center of the group rather then somewhere else.

Move all the room parts (bg, bg, bg_window, ceiling, floor, object_bookcase_short1, object_mousehole) into room1, just as you did when added the jetpack flames particle system to the mouse object.

rocket_mouse_unity_p2_33

Note: If you decorated your room with more bookcases or mouse holes you should also add them to room1.

Create a new folder named Prefabs in the Project browser. Open it and drag room1 from the Hierarchy directly into Prefabs folder.

rocket_mouse_unity_p2_34

That’s it. Now you can see a Prefab named room1 containing all the room parts. To test it try and drag room1 Prefab to the scene. You will see how easy it is to create room duplicates using a Prefab.

Note: You can reuse this Prefab not only in this scene but in other scenes too.

rocket_mouse_unity_p2_35

The Idea Behind the Room Generation

The idea behind the generator script is quite simple. The script that has an array of rooms it can generate, a list of rooms currently generated, and two additional methods. One method checks to see if another room needs to be added and the other method actually adds room.

To check if a room needs to be added, the script will enumerate all existing rooms and see if there is a room ahead, farther then the screen width, to guarantee that the player never sees the end of the level.

rocket_mouse_unity_p2_37

As you can see in case #1 you don’t need to add a room yet, since the end of the last room is still far enough from the player. And in case #2 you should already add a room.

Note: The center of the mouse object doesn’t lie on the left edge of the screen. So although the distance to the end of the level is less then screen width, the player still won’t see the level end in case #2, but he will soon, so it is better to add a room.

Of course the image above is only a rough example, the real script will detect that it needs to generate new room much earlier, right after the end of the room passes the point at which it is closer to mouse then the screen width.

Now when the idea is clear it is time to add the script.

Adding Script to Generate Rooms

Create new C# Script and name it GeneratorScript. Add this script to the mouse GameObject. Now mouse should have two script components:

rocket_mouse_unity_p2_36

Open GeneratorScript in MonoDevelop by double clicking it in the Project view or in the Inspector.

First, add System.Collections.Generic namespace, since you’re going to use List<T> class:

using System.Collections.Generic;

Then add following instance variables:

public GameObject[] availableRooms;
    
public List<GameObject> currentRooms;
        
private float screenWidthInPoints;

The availableRooms will contain an array of Prefabs, which the script can generate. Currently you have only one Prefab (room1). But you can create many different room types and add them all to this array, so that the script could randomly choose which room type to generate.

Note: The final project that you can download at the end of Part 3 contains multiple room types as well as other improvements, but right now it is easer to work with only one room Prefab.

The currentRooms list will store instanced rooms, so that it can check where the last room ends and if it needs to add more rooms. Once the room is behind the player character, it will remove it as well.

The screenWidthInPoints variable is just required to cache screen size in points.

Now, add the following code in Start:

float height = 2.0f * Camera.main.orthographicSize;
screenWidthInPoints = height * Camera.main.aspect;

Here you calculate the size of the screen in points. The screen size will be used to determine if you need to generate new room, as it is described above.

The Method to Add New Room

Add the following AddRoom method to GeneratorScript:

void AddRoom(float farhtestRoomEndX)
{
    //1
    int randomRoomIndex = Random.Range(0, availableRooms.Length);

    //2
    GameObject room = (GameObject)Instantiate(availableRooms[randomRoomIndex]);
    
    //3
    float roomWidth = room.transform.FindChild("floor").localScale.x;

    //4
    float roomCenter = farhtestRoomEndX + roomWidth * 0.5f;

    //5
    room.transform.position = new Vector3(roomCenter, 0, 0);

    //6
    currentRooms.Add(room);         
} 

This method adds new room using the farhtestRoomEndX point, which is rightmost point of the level so far. Here is description of every line of this method:

  1. Picks a random index of the room type (Prefab) to generate.
  2. Creates a room object from the array of available rooms using the random index above.
  3. Since the room is just an Empty containing all the room parts, you cannot simply take its size. Instead you get the size of the floor inside the room, which is equal to the room’s width.
  4. When you set the room position, you set the position of its center so you add the half room width to the position where the level ends. This way gets the point at which you should add the room, so that it started straight after the last room.
  5. This sets the position of the room. You need to change only the x-coordinate since all rooms have the same y and z coordinates equal to zero.
  6. Finally you add the room to the list of current rooms. It will be cleared in the next method which is why you need to maintain this list.
  7. Now take a short break, the next method is going to be a bit bigger.

rocket_mouse_unity_p2_38

The Method to Check If New Room Is Required

Ready? Add the GenerateRoomIfRequired method:

void GenerateRoomIfRequired()
{
    //1
    List<GameObject> roomsToRemove = new List<GameObject>();

    //2
    bool addRooms = true;        

    //3
    float playerX = transform.position.x;

    //4
    float removeRoomX = playerX - screenWidthInPoints;        

    //5
    float addRoomX = playerX + screenWidthInPoints;

    //6
    float farthestRoomEndX = 0;
    
    foreach(var room in currentRooms)
    {
        //7
        float roomWidth = room.transform.FindChild("floor").localScale.x;
        float roomStartX = room.transform.position.x - (roomWidth * 0.5f);    
        float roomEndX = roomStartX + roomWidth;                            
        
        //8
        if (roomStartX > addRoomX)
            addRooms = false;
        
        //9
        if (roomEndX < removeRoomX)
            roomsToRemove.Add(room);
        
        //10
        farthestRoomEndX = Mathf.Max(farthestRoomEndX, roomEndX);
    }
    
    //11
    foreach(var room in roomsToRemove)
    {
        currentRooms.Remove(room);
        Destroy(room);            
    }
    
    //12
    if (addRooms)
        AddRoom(farthestRoomEndX);
}

It only might looks scary, but in fact it is quite simple. Especially if you keep in mind the idea previously described.

  1. Creates a new list to store rooms that needs to be removed. Separate lists are required since you cannot remove items from the list while you iterating through it.
  2. This is a flag that shows if you need to add more rooms. By default it is set to true, but most of the time it will be set to false inside the foreach.
  3. Saves player position.

    Note: I always say position, but most of the time you only work with x coordinate.

  4. This is the point after which the room should be removed. If room position is behind this point (to the left), it needs to be removed.

    Note: You need to remove rooms, since you cannot endlessly generate rooms without removing them after they are already not needed. Otherwise you will simply run out of memory.

  5. If there is no room after addRoomX point you need to add a room, since the end of the level is closer then the screen width.
  6. In farthestRoomEndX you store the point where the level currently ends. You will use this variable to add new room if required, since new room should start at that point to make the level seamless.
  7. In foreach you simply enumerate current rooms. You use the floor to get the room width and calculate the roomStartX (a point where room starts, leftmost point of the room) and roomEndX (a point where the room ends, rightmost point of the room).
  8. If there is a room that starts after addRoomX then you don’t need to add rooms right now. However there is no break instruction here, since you still need to check if this room needs to be removed.
  9. If room ends to the left of removeRoomX point, then it is already off the screen and needs to be removed.
  10. Here you simply find the rightmost point of the level. This will be a point where the level currently ends. It is used only if you need to add a room.
  11. This removes rooms that are marked for removal. The mouse GameObject already flew through them and thus, they are far behind, so you need to remove them.
  12. If at this point addRooms is still true then the level end is near. addRooms will be true if it didn’t find a room starting farther then screen width. This indicate that a new room needs to be added.

Phew, that was hard but you’ve maid it!

rocket_mouse_unity_p2_39

Add FixedUpdate to GeneratorScript containing the call to GenerateRoomIfRequred:

void FixedUpdate () 
{    
        GenerateRoomIfRequired();
}

This insures that GenerateRoomIfRequred is periodically executed.

Note: You don’t have to call this method each time, and the method itself can be optimized, but for simplicity sake you’ll leave it like this.

Setting the Script Options and Enjoying

Now, return to Unity and select the mouse GameObject in the Hierarchy. In the Inspector, find the GeneratorScript component.

rocket_mouse_unity_p2_40

Drag the room1 from the Hierarchy to Current Rooms list. Then open Prefabs folder in Project browser and drag room1 from it to Available Rooms.

As a reminder, the Available Rooms property in the GeneratorScript is used as an array of room types that the script can generate. The Current Rooms property is room instances that are currently added to the scene.

This means that Available Rooms or Current Rooms can contain unique room types, that are not present in the other list.

Here is an animated GIF demonstrating the process. Note that I’ve created one more room type called room2, just to demonstrate what would you do in case you had many room Prefabs.

rocket_mouse_unity_p2_41

Run the scene. Now the mouse can endlessly fly through the level.

rocket_mouse_unity_p2_42

Note that rooms are appearing and disappearing in the Hierarchy while you fly. And for even more fun, run the scene and switch to the Scene view without stopping the game. This way you will see how rooms are added and removed in real time.

Note: If you run the scene and switch to the Scene view after some time you will only find empty Scene. This is because the mouse already flew far to the right and all the rooms behind, including the first room were removed. You can try to find the mouse or just restart the scene and switch to the Scene view straight away.

rocket_mouse_unity_p2_43

Animating the Mouse

Right now the mouse is very lazy. It doesn’t want to move a muscle and simply let the jetpack drag it on the floor. However, the price for the jetpack fuel is quite expensive, so it is better for the mouse to run while on the ground :]

To make the mouse run, you’re going to create an animation and modify the MouseController script to switch between animations while on the ground or in the air.

Slicing mouse_run Animation Spritesheet

Frames of running animation are contained within the mouse_run spritesheet, so first of all you need to slice it correctly.

Open Sprites folder in the Project browser and find mouse_run. Select it and set its Sprite Mode to Multiple in the Inspector.

Then click the Sprite Editor button to open the Sprite Editor.

rocket_mouse_unity_p3_1

In the Sprite Editor click Slice button in the left top corner, to open slicing options. Set the Type field to Grid. Set the grid size to 162 x 156 and click Slice button. You will see the grid immediately appear.

Don’t forget to click Apply button to save changes.

rocket_mouse_unity_p3_2

Close the Sprite Editor. Now if you expand mouse_run in the Project browser you will see that it was sliced on four different sprites.

rocket_mouse_unity_p3_3

Creating Animations

Now that you have all frames, you can create the running and flying mouse animation.

Note: Flying animation consists of one sprite. The sprite that you used to create the mouse, so you already had all the frames for this animation.

To work with animations you will need to open Animation window, if you don’t have it already opened. Choose Window\Animation and open the Animation view.

Place it somewhere so that the Project browser so that you can see both the Animation view and the Project view. I prefer placing it on top, next to the Scene and the Game< views, but you can place it anywhere you like. rocket_mouse_unity_p3_4

Before you create your first animation, create a Animations folder in the Project view and select that new folder. Don't forget that most of new files in Unity are created in the folder that is currently selected in the Project browser.

rocket_mouse_unity_p3_5

Next, select the mouse GameObject in the Hierarchy, since new animations will be added to most recently selected object in the Hierarchy.

rocket_mouse_unity_p3_7

In the Animation window create two new clips: run and fly, by selecting [Create New Clip] in the dropdown menu at the top left corner, to the left of Samples property.

rocket_mouse_unity_p3_6

Note the 3 new files created in the Project view: fly and run animations. You will also notice a mouse animator file. Select the mouse in the Hierarchy. In the inspector, you will see that that an Animator component was automatically added to it.

rocket_mouse_unity_p3_12

Adding Run Animation Frames

First, you’re going to add frames to the run animation. Make sure both the Animation view and the Project view are visible.

In the Animation view select run animation.

rocket_mouse_unity_p3_11

In the Project view, open the Sprites folder and expand mouse_run spritesheet.

rocket_mouse_unity_p3_8

Select all animation frames: mouse_run_0, mouse_run_1, mouse_run_2, mouse_run_3. Drag the frames to the Animation view's timeline as shown below:

rocket_mouse_unity_p3_10

Here is how the timeline should look like after you have added the frames.

rocket_mouse_unity_p3_13

Adding Fly Animation Frame

Believe it or not, the Fly animation will consist of only one frame.

Select fly animation in the Animation view.

rocket_mouse_unity_p3_9

In the Project view find mouse_fly sprite and drag it to the timeline, just as you did with run animation. But this time you only need to add one sprite.

rocket_mouse_unity_p3_14

Make sure you stop the recoding mode in the Animation view after you add animation frames, or you might accidentally animate mouse position or other properties. Click the red dot in the Animation view's control bar to stop the recording.

rocket_mouse_unity_p2_rec

Why would someone want to create an animation with only one frame? Well, you will see in a moment that it will be much easier to switch between the running and flying mouse states using the Animator transitions.

Adjusting the Animator and Run Animation Settings

Run the scene. You will notice two strange things.

  1. The mouse is running like crazy.
  2. The mouse is not falling down even when you don’t touch the screen.

rocket_mouse_unity_p3_15

Fortunately both issues are quite easy to fix. The first one occurs because the animation is played too fast. The second one is due to the Animator settings.

Note: Did you notice that the mouse is now running by default, although earlier it was just single flying mouse sprite?

This happens because you added run animation first and Animator component set is as the default animation. This way it starts playing as soon as you run the scene.

To fix the animation speed select run animation in the Animation view and set Samples property to 8 instead of 60.

rocket_mouse_unity_p3_16

To fix the second issue, select mouse GameObject in the Hierarchy and search for Animator component in the Inspector.

Disable Apply Root Motion and enable Animate Physics.

rocket_mouse_unity_p3_17

Here is an excerpt from Unity documentation about the Apply Root Motion property:

Root motion is the effect where an object's entire mesh moves away from its starting point but that motion is created by the animation itself rather than by changing the Transform position.

In other words, you need to enable it if your animation changes the object Transform. This is not the case right now, which is why you turned it off.

Also since the game is using physics, it is a good idea to keep animations in sync with physics. This is why you check the Animate Physics checkbox.

Run the scene. Now the mouse walks on the floor.

rocket_mouse_unity_p3_18

However, the mouse continues to walk even while it is in the air.

rocket_mouse_unity_p3_19

To fix this, you need to create some animation transitions.

Switching Between Animations

Since there are two animations, you should make the mouse GameObject switch between them. To do this you’re going to use the Animator Transitions mechanism.

Creating Animation Transitions

At this point you’re going to need one more Unity window. In top menu choose Window\Animator to add the Animator view.

Currently you have two animations there: run and fly. The run animation is orange, which means that it is the default animation.

rocket_mouse_unity_p3_20

However, now there is no transition between run and fly animations. This means that the mouse is stuck forever in the run animation state. To fix this you need to add two transitions: from run to fly and back from fly to run.

To add a transition from run to fly, right-click the run animation and select Make Transition, then hover over fly animation and left-click on it.

To add a transition from fly to run, right-click the fly animation, select Make Transition and this time hover over run animation and left-click.

Here is the process of creating both transitions:

rocket_mouse_unity_p3_21

This has created two unconditional transitions which means that when you run the scene, the mouse will first play its run state, but after playing run animation one time, the mouse will switch to fly state. Once the fly state is completed, it will transition back to the run state and continue ad infinitum.

It is hard to notice, because the fly animation takes only a fraction of a second to play, since there is only one frame. However, if you switch to the Animator while the scene is running you will see that there is a constant process of transitioning between the animations as follows:

rocket_mouse_unity_p3_22

Adding Transition Parameter

To break the vicious circle, you need to add a condition that controls when the fly animation should transition to the run animation and vice versa.
Open the Animator view and find the Parameters panel in the left bottom corner. Currently it is empty. Click a + button to add a parameter, in the dropdown select Bool.

rocket_mouse_unity_p3_23

Name the new parameter grounded.

rocket_mouse_unity_p3_24

Select the transition from run to fly to open transition properties in the Inspector. In Conditions section change the only condition from Exit Time to grounded and set its value to false.

rocket_mouse_unity_p3_25

Do the same with the transition from fly to run, but this time set the grounded value to true. This way the mouse state will be changed to fly when grounded is false, and to run when grounded is true.

While you still have to pass in the parameters, you can test the transitions right now. To do this, run the scene, then make sure the Animator view is visible and check or uncheck grounded parameter while the game is running.

rocket_mouse_unity_p3_26

Adding Object to Check if Mouse Grounded

There are many ways to check if the game object is grounded. I like following method because it provides visual representation of the point where the ground is checked, and this is quite useful when you have many different checks (e.g. ground check, ceiling check, and so on).

What makes this method visual is an Empty GameObject added as a child of the player character, like it is shown below.

rocket_mouse_unity_p3_27

Go ahead and create an Empty GameObject, then drag it over mouse GameObject in the Hierarchy, to add it as a child object. Select this GameObject in the Hierarchy and rename it to groundCheck. Set its Position to (0, -0.7, 0).

To make it more visual, click on the icon selection button in the Inspector and set its icon to the green oval. You can really choose any color, but green is truly the best. :]

rocket_mouse_unity_p3_28

Here is what you should get in the end:

rocket_mouse_unity_p3_29

The script will use the position of this Empty to check if it is on the ground.

Using Layers to Define What is Ground

Before you can check that the mouse is on the ground you need to define what is ground. If you don’t do this, the mouse will walk on top of lasers, coins and other game objects with colliders.

You’re going to use the LayerMask class in the script, but to use it, you first must set correct Layer to the floor object.

Open Prefabs folder in the Project view and expand room1 Prefab. Select floor that is inside the Prefab.

rocket_mouse_unity_p3_extra_floor_prefab

In the Inspector click on Layer dropdown and choose Add Layer... option.

rocket_mouse_unity_p3_30

This will open the Tags & Layers editor in the Inspector. Find first editable element, which is User Layer 8 and enter Ground in it. All previous layers are reserved by Unity.

rocket_mouse_unity_p3_31

Next, select the floor within Prefab folder and once again and set its Layer to Ground.

rocket_mouse_unity_p3_34

Checking if Mouse is Grounded

To make the mouse automatically switch states, you will have to the update MouseController script to check if the mouse is currently grounded, then let the Animator know about it.

Open MouseController script in MonoDevelop and add following instance variables:

public Transform groundCheckTransform;
    
private bool grounded;
    
public LayerMask groundCheckLayerMask;
    
Animator animator;

The groundCheckTransform variable will store a reference to that groundCheck Empty that you created earlier.

The grounded variable denotes if the mouse is grounded.

The groundCheckLayerMask stores a LayerMask that defines what is the ground.

Finally the animator variables contains a reference to the Animator component.

Note: It is better to cache components you get by GetComponent in some instance variable, since GetComponent is slow.

To cache Animator component open following line of code to Start:

animator = GetComponent<Animator>();

Now add UpdateGroundedStatus method:

void UpdateGroundedStatus()
{
    //1
    grounded = Physics2D.OverlapCircle(groundCheckTransform.position, 0.1f, groundCheckLayerMask);

    //2
    animator.SetBool("grounded", grounded);
}

This methods checks if the mouse is grounded and sets the animator parameter:

  1. To Check if the mouse GameObject is grounded, you create a circle of 0.1 radius at position of the groundCheck object that you added to the scene.

    If this circle overlaps any object that has a Layer specified in groundCheckLayerMask then the mouse is grounded.

  2. This code actually sets grounded parameter of Animator which then triggers the animation.

Finally, add a call to UpdateGroundedStatus at the end of FixedUpdate:

UpdateGroundedStatus();

This calls the method with each fixed update, insuring that the ground status is consistently checked.

Setting MouseController Script Parameters for Ground Check

There is only one small step left to make the mouse automatically switch between flying and running. Open Unity and select mouse GameObject in the Hierarchy.

Search for the Mouse Controller script component. You will see two new parameters of the script:

rocket_mouse_unity_p3_35

Click the Ground Check Layer Mask dropdown and select Ground layer. Drag the groundCheck from the Hierarchy to the Ground Check Transform property.

rocket_mouse_unity_p3_36

Run the scene.

rocket_mouse_unity_p3_37

Enabling and Disabling Jetpack Flames

Although you cured the mouse from laziness you haven’t cured its wastefulness :] The jetpack is still On even when the mouse is on the ground. You don’t want the mouse to go bankrupt do you? Especially when only few tweaks in the code are needed to fix this.

Open MouseController script and add jetpack public variable to store a reference to the particle system.

public ParticleSystem jetpack;

Then add the following AdjustJetpack method:

void AdjustJetpack (bool jetpackActive)
{
    jetpack.enableEmission = !grounded;
    jetpack.emissionRate = jetpackActive ? 300.0f : 75.0f; 
}

This method disables the particle system when grounded and in addition to that, it also decreases the emission rate when the mouse is falling down, since jetpack might be still be active, but not at full strength.

Add a call to this method to the end of FixedUpdate:

AdjustJetpack(jetpackActive);

Just a reminder: jetpackActive variable is true when you hold the left mouse button and false when you don't.

Now switch back to Unity and drag jetpackFlames from the Hierarchy to jetpack property of the MouseController script.

rocket_mouse_unity_p3_38

Run the scene.

rocket_mouse_unity_p3_39

Now the jetpack has three different states. It is disabled when the mouse is grounded, full strength when going up, and a small emission rate when the mouse is going down. I find it pretty realistic since it is unlikely that you just turn Off the jetpack at the highest point and fall down.

Where to Go From Here

I hope you are enjoying the tutorial so far. You can download the final project for this part using this link: RocketMouse_Final_Part2

The next part will be the final part and has all the fun. You will add lasers, coins, sound effects, and many more.

If you want to know more about Prefabs Unity documentation is a good place to start.

If you have any comments, questions or issues (I hope you don't have them:]) please post them below.

Kirill is a founder of PixelOxygen, an independent development company creating games and applications for iOS. Also, Kirill is the author of Cocos2D iPhone 3.0 Beginner’s Guide book. You can read his Blog or check his latest Games and Apps at the Apple AppStore.

Other Items of Interest

Save time.
Learn more with our video courses.

raywenderlich.com Weekly

Sign up to receive the latest tutorials from raywenderlich.com each week, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

PragmaConf 2016 Come check out Alt U

Our Books

Our Team

Video Team

... 20 total!

Swift Team

... 15 total!

iOS Team

... 44 total!

Android Team

... 15 total!

macOS Team

... 11 total!

Unity Team

... 11 total!

Articles Team

... 15 total!

Resident Authors Team

... 17 total!

Podcast Team

... 8 total!

Recruitment Team

... 9 total!