Você está na página 1de 44

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

raywenderlich.com/69675/make-game-like-jetpack-joyride-unity-2d-part-3

Kirill Muzykov

Kirill Muzykov on July 11, 2014

This is the final part of How to create a game like Jetpack Joyride in Unity 2D tutorial series. If youve missed
previous parts you better to complete them first. Here they are: Part 1 and Part 2.

As Ive mentioned at the end of the previous part this part has all the fun. This will be the reward for going this far :]

In this part you will add lasers, coins, sound effects, music and even parallax scrolling. So enough talking lets start
the fun!

Getting Started
You can continue using the project you created in the second part or alternatively you can download the starter
project for this part. They should be almost identical.

If you want to download the starter project use this link: RocketMouse_Final_Part2

When youre ready open the RocketMouse.unity scene and lets begin!

Adding Lasers
The mouse flying through the room is great, but what is the challenge of this game? It is time to add some obstacles,
and what can be cooler than lasers> ;]

Lasers will be generated randomly, in a similar manner as you generate rooms, so you need to create a Prefab. Also
you will need to create a small script controlling the laser.

Creating Laser
Here are the steps required to create a laser object:

1. In the Project view find laser_on sprite and drag it to the scene.

Note: Since laser Prefab will consist of only the laser itself you dont have to position it at the origin or
something like this.

2. Select it in the Hierarchy and rename it to laser.


3. Set its Sorting Layer to Objects.
4. Add Box Collider 2D component.

1/44
5. Enable Is Trigger property in Box Collider 2D component.

Note: When the Is Trigger property is enabled collider will trigger collision events, but will be ignored by the
physics engine. In other words if the mouse touches the laser you will get notified. However, the laser will not
block the mouse movement.

It is very convenient for many reasons. For example if the mouse dies on top of the laser it wont hang in the
air lying on the laser. Also the mouse can still move a little forward after hitting the laser due to inertia, instead
of bouncing back from the laser

Besides that, real lasers are not some hard objects, so by enabling this property youre just simulating the
real laser.

6. Set Size of collider, X to 0.18 and Y to 3.1.

Note: This creates a collider only where the laser is, leaving emitters on both ends absolutely safe.

7. Create new C# Script named LaserScript and attach it to laser.

Here is the full list of steps displayed:

Turning laser On and Off from the Script

Open LaserScript in MonoDevelop and add following instance variables:

2/44
//1
public Sprite laserOnSprite;
public Sprite laserOffSprite;

//2
public float interval = 0.5f;
public float rotationSpeed = 0.0f;

//3
private bool isLaserOn = true;
private float timeUntilNextToggle;

It might seem like a lot of variables, but in fact everything is quite trivial.

1. The Laser is going to be in two states: On and Off. There is a separate image for each state. You will specify
each state image in just a moment.
2. These properties allow you to add a bit of random fluctuation. You can set a different interval so that all
lasers on the level didnt work exactly the same. By setting a low interval you will create a laser that will
turn On and Off real quick, and by setting a high interval you will create a laser that will stay in its state for
quite long, and who knows, maybe the mouse can even fly trough the laser when it is Off.

The rotationSpeed variable serves similar purpose. It specifies the speed of the laser rotation.

3. Finally there are two private variables that are used to toggle the laser state.

Here is an example of lasers. Each has a different interval and rotationSpeed.

Add the following code in Start:

timeUntilNextToggle =
interval;

This will set the time until the laser should toggle its state
for the first time.

To toggle and rotate the laser add FixedUpdate with


following:

3/44
void FixedUpdate () {
//1
timeUntilNextToggle -= Time.fixedDeltaTime;

//2
if (timeUntilNextToggle <= 0) {

//3
isLaserOn = !isLaserOn;

//4
collider2D.enabled = isLaserOn;

//5
SpriteRenderer spriteRenderer = ((SpriteRenderer)this.renderer);
if (isLaserOn)
spriteRenderer.sprite = laserOnSprite;
else
spriteRenderer.sprite = laserOffSprite;

//6
timeUntilNextToggle = interval;
}

//7
transform.RotateAround(transform.position, Vector3.forward, rotationSpeed *
Time. fixedDeltaTime);
}

Here is what that code does:

1. Decreases the time left until next toggle.


2. If timeUntilNextToggle is zero or even less then zero, it is time to toggle the laser state.
3. Sets the correct state of the laser in the private variable.
4. The laser collider is enabled only when the laser is On. This means that mouse can fly through the laser freely
if it is Off.
5. Casts the more general Renderer class to a SpriteRenderer since you know the laser is a Sprite. It also
sets the correct laser sprite. This will display laser_on sprite when the laser is On and laser_off sprite
when the laser is Off.
6. Resets timeUntilNextToggle variable since the laser has just been toggled.
7. Rotates the laser around the z-axis using its rotationSpeed.

Note: To disable rotation you can just set rotationSpeed to zero.

Setting the Laser Script Parameters

Switch back to Unity and select laser in the Hierarchy. Make sure the Laser Script component is visible.

Drag laser_on sprite from the Project view to the Laser On Sprite property of the Laser Script component in the
Inspector.

4/44
Then drag laser_off sprite to Laser Off Sprite property.

Set Rotation Speed to 30.

Now set the laser Position at (2, 0.25, 0). This is to test that everything works correctly.

Run the scene. You should see a laser nicely rotating.

Now, turn the laser into a prefab.

Solution Inside: Need help creating a laser prefab? Show

Killing the Mouse


Right now the mouse can easily pass through the enabled laser without so much as a whisker getting bent. This is
not a good example for kids. Kids should see the consequences of playing with lasers. :]

Better get to fixing that.

Open MouseController script and add dead instance variable.


5/44
private bool dead = false;

This instance variable indicates a dead mouse. Once this variable is true, you will not be able to activate the jetpack,
move forward, and so on.

Now add the following two methods somewhere within the MouseController class:

void OnTriggerEnter2D(Collider2D
collider)
{
HitByLaser(collider);
}

void HitByLaser(Collider2D laserCollider)


{
dead = true;
}

The OnTriggerEnter2D method is called when mouse collides with any laser. Currently, it just makes marks the
mouse dead.

Note: It might seem strange why you need to create a separate method for one line of code, but you will add more
code to both OnTriggerEnter2D and HitByLaser so it is just a way to make future changes more convenient.

Now, when the mouse is dead it shouldnt move forward or fly using the jetpack. Youre not filming The Flying Dead,
arent you? :]

Make the following changes in FixedUpdate to make sure this doesnt happen:

void FixedUpdate ()
{
bool jetpackActive = Input.GetButton("Fire1");

jetpackActive = jetpackActive && !dead;

if (jetpackActive)
{
rigidbody2D.AddForce(new Vector2(0,
jetpackForce));
}

if (!dead)
{
Vector2 newVelocity = rigidbody2D.velocity;
newVelocity.x = forwardMovementSpeed;
rigidbody2D.velocity = newVelocity;
}

UpdateGroundedStatus();

AdjustJetpack(jetpackActive);
}

6/44
Note that now jetpackActive is always false when the mouse is dead. This means that no upward force will be
applied to the mouse and also, since jetpackActive is passed to AdjustJetpack, the particle system will be
disabled.

In addition to that you dont set the mouse velocity if its dead, which is pretty obvious thing to do.

Switch back to Unity and run the scene. Make the mouse fly into the laser.

Hm.., it looks like you can no longer use the jetpack and the mouse doesnt move forward, but why is the mouse
running like crazy?

Guesses? Anyone? Bueller? Bueller?

The reason for this strange behavior is that you have two states for the mouse: run and fly, and when the mouse
falls down on the floor it becomes grounded so run animation is activated.

Since the game cannot end like this, you need to add few more states to show that the mouse is dead.

Adding the Fall and Die Mouse Animations

Select mouse GameObject in the Hierarchy and open the Animation view.

Create new animation called die. Save new animation to Animations folder.

7/44
After that, follow these steps to complete the animation:

1. Open Sprites folder in the Project view.


2. Select and drag mouse_die_0 and mouse_die_1 sprites to the Animation views timeline.
3. Set Samples to 8 to make the animation slower.
4. Note that recording mode is on. The easiest way to notice this is by looking at playback buttons, which has
turned red. Click on the recording button to stop the recording. This will make the playback buttons to return to
normal color.

8/44
That was easy. In fact I think you can create fall animation yourself. This time just use the mouse_fall sprite as a
single frame. However, if you get stuck feel free to expand the section below for detailed instructions.

Solution Inside: Need help creating fall animation? Show

Transitioning to Fall and Die Animations

After creating the animations, you need to make the Animator switch to the corresponding animation at the right time.
To do this, youre going to transition from a special state called Any State, since it doesnt matter what the current
state the mouse is currently in, when it hits the laser.

Since you created two animations(fall and die), there is a difference if the mouse hits the laser in the air or while
running on the ground. In the first case, the mouse should switch to the fall animation state and only after hitting the
ground play die animation.

However, in both cases you need one new parameter. Open the Animator view and create new Bool parameter
called dead.

9/44
After this Make Transition from Any State to fall.

Select this transition and in Conditions, set dead to


true and add grounded as a second parameter by
clicking +. Set grounded to false.

Select this transition and in Conditions set both dead


and grounded parameters to true.

This way there are two possible combinations:

1. dead but not grounded


2. dead and grounded

10/44
This way, if the mouse is dead, but still in the air (not grounded) the state is switched to fall. However, if the mouse is
dead and grounded, or was dead and becomes grounded after falling to the ground, the state is switched to die.

The only thing left to do is update the dead parameter from MouseController script.

Open MouseController script and add the following line to the end of HitByLaser:

animator.SetBool("dead",
true);

This will set the dead parameter of the Animator component to true.

Run the scene and fly into the laser.

As you can see, when the mouse hits the laser, the script sets a dead parameter to true and the mouse switches to
fall state (since grounded is still false). However, when the mouse reaches the floor, the script sets grounded
parameter to true. Now, all conditions are met to switch to die state.

Using the Trigger to Make the Mouse Die Once

There is an old saying that you only can die once, however the mouse right now is dying all the time. You can check
this yourself by looking at Animator view after the mouse dies.

11/44
This happens because the transition from Any State to die happens all the time. The grounded and dead
parameters are always true, which triggers the animator to transition from Any State

To fix this, you use a special parameter type called Trigger. Trigger parameters are very similar to Bool, with the
exception that they are automatically reset after used. This is a relatively new featured added in Unity 4.3.

Open the Animator view and add a new Trigger parameter called dieOnceTrigger. Set its state to On, by checking
the checkbox next to it.

Next, select the transition from Any State to die, and add dieOnceTrigger in the Conditions section.

Run the scene and fly into the laser once again.

I wouldnt say that this makes things better, but fortunately this is very easy to fix. This
happens only because die animation is set to loop by default.

Open Animations folder in the Project view and select animation. In the Inspector uncheck
Loop Time. This disables the animation looping.

Run the scene and collide with a laser.

12/44
This time the mouse stays on the floor after dying.

Adding Coins
While death dealing lasers are fun to implement, how about adding some coins for mouse to collect.

Creating Coin Prefab

Creating a coin Prefab is so easy and similar to creating laser so you should try doing this yourself. Just use the coin
sprite and follow these tips:

Dont create any scripts for coin.


Use Circle Collider 2D instead of Box Collider 2D.
Enable Is Trigger option for the collider, since you dont want the coin to stop the mouse movement.

If you have any questions just take a look at the expandable section below.

Solution Inside: Creating coin prefab Show

After creating a coin GameObject, drag it from the Hierarchy and into the Prefabs folder in the Project view to create
a coin Prefab.

13/44
Now add several coins to the scene by dragging coin Prefabs to the Scene view. Create something like this:

Run the scene.

14/44
Wait a second the mouse died the moment it touched the coins? Are they
poisoned?

No, the coins are okay. The mouse dies because of the code in MouseController script, which handles any collision
as a collision with a laser.

Using Tags to Distinguish Coins from Lasers

To distinguish coins from lasers you will use Tags, which are made exactly for that purpose.

Select coin Prefab right in Prefabs folder in the Project view. This will open the Prefab properties in the Inspector.
Find the Tag dropdown right below the name field, open it, and chose Add Tag..

15/44
This will open the already familiar Tags & Layers editor in the Inspector. In the Tags section add a tag named Coins.

Note: It will automatically increase the Size to 2 and add Element 1, but thats ok.

Now select coin Prefab in the Project view once again and set its Tag to Coins in the Inspector.

Of course just setting the Tag property doesnt make the script to
distinguish coins from lasers, youll still need to modify some code.

Updating MouseController Script to use Tags

Open the MouseController script and add a coins counter variable:

private uint coins =


0;

This is where youll store the coin count.

Then add CollectCoin method:

void CollectCoin(Collider2D
coinCollider)
{
coins++;

Destroy(coinCollider.gameObject);
}

This method increases the coin count and removes the coin from the scene so that you dont collide with it a second
time.

Finally, make following changes in OnTriggerEnter2D:

void OnTriggerEnter2D(Collider2D collider)


{
if
(collider.gameObject.CompareTag("Coins"))
CollectCoin(collider);
else
HitByLaser(collider);
}

With this change, you call CollectCoin in case of a coin and HitByLaser in all other cases.

Note: In this game there are only two types of objects so it is okay to use else case for lasers. In a real game, you
should assign tags for all object types and check them implicitly.

Run the scene.

16/44
Now thats much better. The mouse collects coins and dies if it hits a laser. It looks like youre ready to generate
lasers and coins using a script.

Generating Coins and Lasers


Generating coins and lasers is similar to what you did when you generated rooms. The algorithm is almost identical,
but before writing the code, you need to improve the coin generation so as to make it more fun for the player.

Currently you have a Prefab that consists of only one coin, so if you write generation code you will simply generate
only one coin here and there on the level. This is not fun! How about creating different figures from coins and
generating a pack of coins at once?

Creating Pack of Coins Prefab

Open the Prefabs folder in the Project viewer and create 9 coins on the scene using the coin Prefab. It should look
something like this:

Select any coin and set its Position to (0, 0, 0). This will be
central coin. You will add all coins into Empty GameObject, so
you need to build your figure around the origin.

After placing the central coin, build a face down triangle shaped
figure around the coin. Dont forget that you can use Vertex
Snapping by holding V key.

Now create an Empty GameObject by choosing


GameObject\Create Empty. Select it in the Hierarchy and
rename it to coins_v.

Set its Position to (0, 0, 0) so that it has the same position as the central coin. After that select all coins in the
Hierarchy and add them to coins_v. You should get something like this in the Hierarchy:
17/44
Select coins_v in the Hierarchy and drag it to Prefabs folder in the
Project view to create Prefab.

Note: You can create as many different coins combinations as you want, just as with rooms, the generator script will
provide a property where you will specify all the possible objects to generate.

Youre done. Now remove all the coins and lasers from the scene since they will be generated by the script.
18/44
Adding New Parameters to GeneratorScript

Open GeneratorScript and add following instance variables:

public GameObject[] availableObjects;


public List<GameObject> objects;

public float objectsMinDistance = 5.0f;


public float objectsMaxDistance = 10.0f;

public float objectsMinY = -1.4f;


public float objectsMaxY = 1.4f;

public float objectsMinRotation = -45.0f;


public float objectsMaxRotation = 45.0f;

The availableObjects array, will hold all objects that the script can generate (i.e. different coins packs and
laser). The objects list will store the created objects, so that you could check if you need to add more ahead of the
player or remove them when they have left the screen.

Note: Just as with rooms, you can create several lasers or coins at the beginning of the level where you dont want to
rely on random generation code. Just dont forget to add them to objects list.

The variables objectsMinDistance and objectsMaxDistance are used to pick a random distance between
the last object and the currently added object, so that the objects dont appear at fixed interval.

By using objectsMinY and objectsMaxY you can configure the maximum and minimum height at which objects
are placed, and by using objectsMinRotation and objectsMaxRotation you can configure the rotation
range.

Adding The Method to Add New Object

New objects are added in AddObject in a similar way to how rooms are added.

Add the following:

19/44
void AddObject(float lastObjectX)
{
//1
int randomIndex = Random.Range(0, availableObjects.Length);

//2
GameObject obj = (GameObject)Instantiate(availableObjects[randomIndex]);

//3
float objectPositionX = lastObjectX + Random.Range(objectsMinDistance,
objectsMaxDistance);
float randomY = Random.Range(objectsMinY, objectsMaxY);
obj.transform.position = new Vector3(objectPositionX,randomY,0);

//4
float rotation = Random.Range(objectsMinRotation, objectsMaxRotation);
obj.transform.rotation = Quaternion.Euler(Vector3.forward * rotation);

//5
objects.Add(obj);
}

This method takes the position of the last (rightmost) object and creates a new object at the random position (within
given interval) after it. By calling this method, each time the last object is about to show on the screen you create a
new object off screen and keep an endless flow of new coins and lasers.

Here is the description of each code block:

1. Generates a random index for the object to generate. This can be a laser or one of the coin packs.
2. Creates an instance of the object that was just randomly selected.
3. Sets the objects position, using a random interval and a random height. This is controlled by script
parameters.
4. Adds a random rotation to the newly placed objects.
5. Adds the newly created object to the objects list for tracking and ultimately, removal (when it leaves the
screen).

With the code in place, the only thing left to do is actually use it.

Generating and Removing Objects When Required

Add the following in the GeneratorScript:

20/44
void GenerateObjectsIfRequired()
{
//1
float playerX = transform.position.x;
float removeObjectsX = playerX - screenWidthInPoints;
float addObjectX = playerX + screenWidthInPoints;
float farthestObjectX = 0;

//2
List<GameObject> objectsToRemove = new
List<GameObject>();

foreach (var obj in objects)


{
//3
float objX = obj.transform.position.x;

//4
farthestObjectX = Mathf.Max(farthestObjectX, objX);

//5
if (objX < removeObjectsX)
objectsToRemove.Add(obj);
}

//6
foreach (var obj in objectsToRemove)
{
objects.Remove(obj);
Destroy(obj);
}

//7
if (farthestObjectX < addObjectX)
AddObject(farthestObjectX);
}

This method checks if an object should be added or removed somewhere within GeneratorScript class. Heres
the breakdown:

1. Calculates key points ahead and behind the player.

If the laser or coin pack is to the left of removeObjectsX, then it has already left the screen and is far
behind. You will have to remove it.

If there is no object after addObjectX point, then you need to add more objects since the last of the
generated objects is about to enter the screen.

The farthestObjectX variable is used to find the position of the last (rightmost) object to compare it with
addObjectX.

2. Since you cannot remove objects from the currently iterating, you place objects that you need to remove in a
separate array to be removed after the loop.

21/44
3. This is the position of the object (coin pack or laser).
4. By executing this code for each objX you get a maximum objX value in farthestObjectX at the end of
the cycle (or the initial value of 0, if all objects are to the left of origin, but not in our case)
5. If current object is far behind, it is marked removal to free some resources.
6. Removes objects marked for removal.
7. If the player is about to see the last object and there are no more objects ahead, the scripts adds more.

To make this method work, add a call to GenerateObjectsIfRequired at the end of FixedUpdate:

GenerateObjectsIfRequired();

This method is called with each fixed update, insuring that there will always be objects ahead of the player.

Setting up Script Parameters

To make the GeneratorScript work, you need to set few of its parameters. Switch back to Unity and select the mouse
GameObject in the Hierarchy.

Find the Generator Script component in the Inspector and make sure that the Prefabs folder is opened in the Project
view.

Drag the coins_v Prefab from the Project view to the Available Objects list in the GeneratorScript component. After
that, drag the laser Prefab from the Project view also to the Available Objects list in the GeneratorScript.

Thats it! Run the scene.

Note: In the animated GIF, the lasers are not rotating because I set rotationSpeed parameter of LaserScript to 0.
With rotating lasers, it is quite hard to record a good gameplay video :]

22/44
Now this looks like an almost complete game!

Adding GUI Elements


Whats the point of collecting coins if you cant see how many
coins that you have collected? Also, Theres no way for the
player to restart the game once they have died. Its time to fix
these issues by adding a couple of GUI elements.

Displaying Coins Count

Open the MouseController script in MonoDevelop and add


the following instance variable:

public Texture2D coinIconTexture;

Then add DisplayCoinsCount method:

void DisplayCoinsCount()
{
Rect coinIconRect = new Rect(10, 10, 32, 32);
GUI.DrawTexture(coinIconRect, coinIconTexture);

GUIStyle style = new GUIStyle();


style.fontSize = 30;
style.fontStyle = FontStyle.Bold;
style.normal.textColor = Color.yellow;

Rect labelRect = new Rect(coinIconRect.xMax, coinIconRect.y, 60, 32);


GUI.Label(labelRect, coins.ToString(), style);
}

This method uses GUI.DrawTexture to draw a coin icon at the top left corner of the screen. Then it creates a
GUIStyle for the label to change its size, bolds the text, then changes the text color to yellow. Or should I say gold?
:]

Finally, it uses GUI.Label to display the amount of coins to the right of the coins icon.

All code to display GUI elements should be called from OnGUI method that is called by Unity. So go ahead and add
the OnGUI method that simply calls DisplayCoinsCount.

void OnGUI()
{

DisplayCoinsCount();
}

Switch back to Unity and select mouse GameObject in the Hierarchy. Open Sprites folder in the Project view and
drag coin sprite to Coin Icon Texture field of Mouse Controller component in the Inspector.

23/44
Run the scene. You should see coins count displayed in top left corner.

Raising the Dead

Open MouseController script again, but this time add


DisplayRestartButton method:

void DisplayRestartButton()
{
if (dead && grounded)
{
Rect buttonRect = new
Rect(Screen.width * 0.35f, Screen.height *
0.45f, Screen.width * 0.30f, Screen.height *
0.1f);
if (GUI.Button(buttonRect, "Tap to
restart!"))
{
Application.LoadLevel
(Application.loadedLevelName);
};
}
}

Most of this method is only executed when mouse GameObject is dead and grounded. You dont want the player
to miss the mouse dripping dead, especially after you put so much efforts creating those animations :]

When the mouse is dead and grounded, you display a button right in the center of the screen with a Tap to restart!
label on it. If the player taps this button, you simply reload the currently loaded scene.

Now add a call to DisplayRestartButton at the end of OnGUI and youre done:

DisplayRestartButton();

Switch to Unity and Run the scene. Fly into some laser to kill the mouse. When the button appears, tap it, and you
will restart the game.

24/44
Note: You can customize how button looks by creating a public instance variable like this:

public GUIStyle
restartButtonStyle;

Then you can use customize the buttons look and feel.

You can find out more information about customizing the buttons look and feel by checking out the Unity
documentation. Keep in mind that with the arrival of Unity 4.6, the New GUI will be released which provides an
entirely new way of working with Unitys GUI tools. You can find out more about it over here

Adding Sound and Music


The game is deadly quiet. You will be amazed how much better it play once add some sounds and music to it.

Hitting Laser Sound

Open Prefabs folder in the Project view and select laser Prefab.
25/44
In the Inspector, add an Audio Source component by clicking Add Component and selecting Audio\Audio Source.
Then open the Audio folder in the Project view and drag laser_zap sound to Audio Clip field.

Dont forget to uncheck Play On Awake . Otherwise the laser zap sound will be played right at the start of the game,
just as if the mouse started on the laser.

Oh, that would be a cruel game if the player character died right at the start and you couldnt do anything about it.
Maybe it will even break all the records in the AppStore since it is that much harder then Flappy Bird :]

This is what you should get:

Note: Make sure you select the laser Prefab not the laser
instance in the Hierarchy. Otherwise you will need
additionally to click Apply button to save changes made
in instance to Prefab.

Now open MouseController script in MonoDevelop and


add following code to the beginning of HitByLaser:

if (!dead)

laserCollider.gameObject.audio.Play();

Note: It is important to add it to the beginning of the method, before you set dead to true or otherwise it wont be
played even once.

When the mouse touches the laser, you get a reference to the lasers collider in OnTriggerEnter2D. By accessing
gameObject property of laserCollider you then get the laser object itself. Then, you can access the Audio
Source component, and make it play.

Run the scene. You will now hear a zap sound when the mouse hits any laser.

26/44
However, the zap sound is too quiet and if you have a stereo speakers or headphones, the sound is played a bit t to
the left. This happens because Audio Listener component is placed on Main Camera by default, and the Audio
Source component is placed on laser. Fortunately, this is an easy issue to fix.

Note: Dont forget that Unity was originally developed to create 3D games. In 3D games, you need 3D sounds (e.g.
to hear that someone shoots at you from the side or even from the back).

However, although you still might want to use 3D sound in some 2D games, most of the time you just want the sound
played at the same volume independently from where the audio source is placed.

Disabling 3D Sound Mode

Open Audio folder in the Project view and select laser_zap file. This will open the Import Settings editor in the
Inspector. Uncheck the 3D Sound option and click Apply.

Do the same for the rest audio files:

coin_collect
footsteps
jetpack_sound
music

Collecting Coin Sound

While you could apply the same approach with coins, youll be
something a little bit different.

Open the MouseController script in MonoDevelop and add following


instance variable:

public AudioClip
coinCollectSound;

Scroll down to the CollectCoin method and add following line of code at the end of the method:

27/44
AudioSource.PlayClipAtPoint(coinCollectSound, transform.position);

This way you use a static method of the AudioSource class to play the coin collect sound at the position where the
mouse is currently located.

Switch back to Unity and select the mouse GameObject in the Hierarchy. Drag the coin_collect from the Project view
to the Coin Collect Sound field in MouseController script.

Run the scene. You should hear a nice sound when collecting a coin :]

Jetpack and Footsteps Sound

Next, you need to add the sound of the jetpack and the mouses
footsteps when it is running on the floor. This will be just a little bit
different since mouse will have to have two Audio Source components
at once.

Adding Audio Sources

Select the mouse GameObject in the Hierarchy and add two Audio
Source components. Drag footsteps from the Project view to the Audio Clip of the first Audio Source component.
Then drag jetpack_sound to Audio Clip field of the second Audio Source component.

Enable Play On Awake and Loop for both Audio Sources.

28/44
If you run the scene, you will hear that both sounds are playing all the time, independently of whether the mouse is
flying or running on the floor. Youll fix this in code.

Switching Between Footsteps and Jetpack Sounds

Open MouseController script in MonoDevelop and add two following instance variables:

public AudioSource jetpackAudio;

public AudioSource
footstepsAudio;

These reference your newly created Audio Sources.

Now add AdjustFootstepsAndJetpackSound method:

void AdjustFootstepsAndJetpackSound(bool jetpackActive)


{
footstepsAudio.enabled = !dead && grounded;

jetpackAudio.enabled = !dead && !grounded;


jetpackAudio.volume = jetpackActive ? 1.0f : 0.5f;

29/44
This method enables and disables the footsteps and the jetpack Audio Source component. The footsteps sound is
enabled when the mouse is not dead and on the ground, the jetpack sound only when the mouse is not dead and not
on the ground.

In addition, this method also adjusts the jetpack volume, so that it corresponds with the particle system

Finally add a call to AdjustFootstepsAndJetpackSound at the end of FixedUpdate:

AdjustFootstepsAndJetpackSound(jetpackActive);

Now you need to assign references to Audio Source components within mouse GameObject to footstepsAudio
and jetpackAudio variables.

Setting Footstep and Jetpack Script Variables

Switch back to Unity and select mouse GameObject in the Hierachy. Youre going to work only within the Inspector
window. Collapse all components except Mouse Controller.

Now drag the top Audio Source component to Footsteps Audio in


the Mouse Controller script component.

Note: In my case I know that the first Audio Source in the Inspector
is the footsteps sound clip, but you might want temporarily expand
the Audio Source component to check this.

After that drag the second Audio Source component to the Jetpack
Audio in the Mouse Controller script component.

Run the scene. Now you should hear the footsteps when the mouse
is running on the floor and jetpack engine when its flying. Also the
jetpack sound should become stronger when you enable jetpack by
holding the left mouse button.

30/44
Adding Music

To add music just follow these simple steps:

1. Select Main Camera in the Hierarchy.


2. Add an Audio Source component in the Inspector.
3. Drag music asset from the Project browser to Audio Clip property.
4. Make sure Play On Awake and Loop are enabled.
5. Decrease the Volume to 0.3, since the music is quite loud compared to other sounds.

31/44
Thats it. Run the scene and enjoy some music!

Adding Parallax Background


Currently this room with a view is pretty boring.

However, there are two ways to solve it:

1. Create something to show behind the window.


2. Dont use windows :]

Of course youll go with the first one, but instead of adding a motionless
background image you will add a parallax background.

Note: To implement parallax scrolling for this game I used the technique
described in one of the Mike Geigs videos that you can watch over here.
The link is provided in the end of this part.

Here is how things will work. You will add two Quads, one for background
and one for foreground parallax layer.

Note: You can read more about Quads in Unity documentation. To simplify things a little, you can think of them as
just a rectangles with a texture stretched on it. Well, at least in this case.

32/44
You might wonder why do you need to use Quad instead of a typical Sprite? The reason for this is that you cant
change the Sprites image wrapping mode. Well, at least at the moment of writing this tutorial. And we need to
change the wrapping mode to make sure the texture is endlessly repeated while we moving it to the left. It will get
clearer in a moment.

You will set a texture for each quad, and instead of moving quads to simulate movement you will simply move the
textures within the quad at a different speed for the background and the foreground layer.

Preparing Background Images

To use background images with quads you need to adjust how they are imported to Unity.

Open Sprites folder in the Project view and select window_background. In the Inspector change its Texture Type to
Texture instead of Sprite. This will change how the look of the Inspector.

After that change Wrap Mode that just appeared to Repeat. Click Apply.

Do the same for window_foreground image.

Creating Another Camera

Wait, what, another camera? The Main Camera is reserved for


following the mouse through the level. This new camera will render
the parallax background and wont move.

Create new camera by selecting GameObject\Create Other\Camera.


Select it in the Hierarchy and make following changes in the
Inspector:

1. Rename to ParallaxCamera.
2. Set Position to (0, 10, 0)
3. Set Projection to Orthographic
4. Set Size to 3.2, the same size as Main Camera has.

Since you have two cameras you also have 2 audio listeners in the
scene. Disable Audio Listener in ParallaxCamera or you will get
following warning.

There are 2 audio listeners in the scene.


Please ensure there is always exactly one audio
listener in the scene.

Creating Quads

Create two Quad objects by choosing GameObject\Create Other\Quad. Name the first quad parallaxBackground
and the second name parallaxForeground. Drag both quads to ParallaxCamera to add them as children.

Select parallaxBackground and change its Position to (0, 0, 10) and Scale to (11.36, 4.92, 0).

Note: You get this scale because background images have size of 1136492 px.

Select parallaxForeground and set its Position to (0, 0, 9) and Scale to (11.36, 4.92, 0).
33/44
Note: This time you set the z-coordinate position. Since you cannot
use Sorting Layers for quads you need to set the background quad
behind the foreground quad.

Setting Quad Textures

Open Sprites folder in the Project view. Drag the


window_background over to the parallaxBackground and
window_foreground over parallaxForeground in the Hierarchy.

Then select parallaxForeground in the Hierarchy. You will see that a


Mesh Renderer component was added. Click on the Shader drop
down and select Unlit\Transparent.

Do the same for parallaxBackground.

This is what you should see in the Scene view right now.

If you disable 2D mode and rotate a scene a little, this is how things
are in the scene right now.

34/44
35/44
36/44
Run the scene. You will see that the background is in front of the main level. This is useful so you can see how the
textures move with ParallaxScrolling. Once you have the textures moving, you will move it back to the background.

37/44
Making Textures Move

You will not move the Quads. Instead, youre going to move the textures of the quads by changing the texture offset.
Since you set the Wrap Mode to Repeat the texture will repeat itself.

Note: This doesnt wont work with any image. They background images designed to be repeated. In other words if
you repeat the background horizontally many times and each left side of the picture will perfectly fit the ride side.

Create a new C# Script called ParallaxScroll and attach it to ParallaxCamera.

38/44
Open ParallaxScript in MonoDevelop and add the following
instance variables:

public Renderer background;


public Renderer foreground;

public float backgroundSpeed =


0.02f;
public float foregroundSpeed =
0.06f;

The Renderer variables will hold a reference to the Mesh


Renderer component of each of the quads so that you could adjust
their texture properties. The backgroundSpeed and
foregroundSpeed just define speed for each background.

Add following code to Update:

float backgroundOffset =
Time.timeSinceLevelLoad * backgroundSpeed;
float foregroundOffset =
Time.timeSinceLevelLoad * foregroundSpeed;

background.material.mainTextureOffset = new
Vector2(backgroundOffset, 0);
foreground.material.mainTextureOffset = new
Vector2(foregroundOffset, 0);

This code increases the texture offset of each the quads texture with time, thus moving it. The speed is different
since the script uses backgroundSpeed and foregroundSpeed coefficients.

Switch back to Unity and select ParallaxCamera in the Hierarchy. Drag the parallaxBackground quad to Background
field of the ParallaxScroll script and parallaxForeground to Foreground.

39/44
Run the scene. You will now see some nice parallax scrolling.

But what about the level itself? You cant see it!

Fixing the Order of Cameras

Select ParallaxCamera in the Hierarchy. In the Inspector, find Camera component and look for a Depth field, set it to
-2.

Note: The Depth of the ParallaxCamera should be lower then Depth of Main Camera, so check your Main Camera
Depth if required and adjust Depth of ParallaxCamera to be lower.

However, if you run the game right now you wont see parallax
background through the window.

To fix this, select Main Camera in the Hierarchy and set its Clear
Flags to Depth Only. This way it wont clear out the picture drawn
by parallax camera.

40/44
Run the scene. Now you will see parallax background through the window.

Few Improvements

Although you can see the treetops and clouds throughout the window, it is better to move background quads a bit
higher, so that you can see the hills.

Another thing to improve is that the background keeps moving even after the mouse dies.

Stoping Parallax Scrolling After the Mouse Dies

Open ParallaxScroll script in MonoDevelop and add public offset variable.


41/44
public float offset =
0;

You will use it instead of Time.timeSinceLevelLoad, so in Update replace the code where you calculate offsets
with this:

float backgroundOffset = offset *


backgroundSpeed;
float foregroundOffset = offset *
foregroundSpeed;

Now open MouseController script and add following public variable:

public ParallaxScroll
parallax;

Then add following code to the end of FixedUpdate:

parallax.offset = transform.position.x;

This way you will use the mouse position as offset instead of time.

Switch back to Unity and select mouse GameObject in the Hierarchy. Make sure MouseController script is visible in
the Inspector.

Drag ParallaxCamera from the Hierarchy to Parallax field in the Inspector.

This will allow MouseController script to change the offset variable of ParallaxScroll script.

Moving Background a bit higher

Set Y component of Position of both parallaxBackground and parallaxForeground quads to 0.7. This will make them
a little higher so that you can see the hills.

42/44
Run the scene. Now the background stops moving as soon as the mouse dies, and you can see more background
through the window.

Note: In fact, the mouse doesnt have to die in order to stop the background. As soon as the mouse stops, the
background will also stop. If for some reason the mouse flies backward, the background will also move in the
opposite direction.

However, this is too sad an image to end this tutorial, so I decided to add a kitty :]

43/44
Where To Go from Here?
I hope you liked this tutorial as much as I liked creating it.

You can download the final project here: Download Final Project

If you want to know more about the making of the actual Jetpack Joyride game check out this video.

Creating a parallax background is heavily inspired by this video by Mike Geig (he has a lot of really cool videos on
Unity).

The cat image is made by Nicolas Suzor and you can find it on Flickr.

Please post your questions and comments below. Thank you for completing this tutorial :]

44/44

Você também pode gostar