Project Creation: RPG Game Development With Unity

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 126

RPG Game Development With Unity

Project setup

Since the release of this course, Tiled2Unity was updated to Super Tiled2Unity. As
consequence, following this lesson we added a text lesson explaining how to use Super
Tiled2Unity to import Tiled maps.

In this lesson, you will setup the Unity Project for this game and learn about what external programs
you will be using for this course.

Project Creation

First, you will need to create a new Unity Project. Open up the Unity program, and click on the New
button in the upper right hand corner.

The name and location of the project can be anything you like, but it will be easier if you make a
dedicated folder for your Unity Projects. Make sure that you have selected the 2D option and click
Create Project.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

In the Unity Editor, there will be an Assets section under the Project tab. When you right click on it,
you can open the Assets in whatever your OS’s file explorer is. For newer versions of Unity, there
will be a Scenes folder in this folder.

You will make a new folder and name it Project. Now you can download the Artwork files from the
course home. This will be a file called Art.zip, and will have 3 folders inside of it, Fonts, Maps, and
Sprites. Put these three folders into the Assets/Project folder. If you already have a Scenes folder,
put that there as well. It should end up looking like this once Unity loads in the new files:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

The reason to include a Project folder for this game is that the external packages you will be using
will have files under Assets as well. This additional folder will allow you to keep track of what
belongs to your game, and what has been added.

Sprite Editing

Now, opening the Sprites folder and then the World folder, you will see a number of different
images. If you select the player sprite, you will see that it is a sprite sheet, as shown below.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

This sprite sheet is a collection of different sprites and will be the basis for the player animations.
Each different character is a different movement. Whenever you are using sprite animations like this,
you will slice the image into smaller sections.

To do this, go to the Inspector and change the Sprite Mode from Single to Multiple.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

Now, you will click on the Sprite Editor, and then choose the Slice tool in the upper left section.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

When you click on Type, you will see multiple options in the dropdown menu. Grid by Cell Count is
what you will want to use.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

You will want to set the Column & Row line to 4 and 7 respectively, and then click Apply, which is
in the upper right section. Now, when you select the arrow next to the player sprite, each of the
individual sprites will show up. These can now be put into the game separately.

Now you will need to splice some more sprites. Go to the Battle folder under Sprites, and select the
icons sprite. Following the same sequence as before, you will slice this sprite using Grid By Cell
Count with 10 for the column and 4 for the row. Make sure to click Apply before you close. To
make this process a little faster, you can select multiple under Sprite Mode and then choose
Sprite Editor directly, and apply the change with the popup window. The rest of the sprites you
need to slice are as follows:

mage, 5 for column and 4 for row


snake, 5 for column and 4 for row
warrior, 5 for column and 4 for row

The other sprite sheets included in the battle folder will not be used in this tutorial, they are for you
to use later on for your own game creation. You can find the creator of the assets used in this tutorial
here: https://github.com/sparklinlabs/superpowers-asset-packs. These assets have all been released
under the Creative Common Zero (CC0) license, which means you can use these assets freely. There
are many different assets offered by this creator, so please check them out if you like the art.

Tile Maps

Now, you can start working on creating the tile maps for this game. Under the Sprites folder, you
will see something called tileset. When you open this with the inspector, you should see the
following:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

This file will allow you to use the various images to create different maps in your game. As there is
already a created map, you will not need to do this for the tutorial.

If you go to the maps folder, you will see two files, cave and map. To allow these to be used in
Unity, you will need to download a tool. Go here: https://www.mapeditor.org/ and click on Download
at itch.io. If you are able to support this creator, that would be great, but it is not necessary to pay
for this tool.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

Choose the proper version for your computer, and install it. Once it is installed, you can go to the
maps folder, and open the town map. You should see the following:

When opening the maps, it is possible that Tiled can not find the tileset.png file. If that’s
the cause, you only need to point to its location, which is the Sprites folder.

This is the map pre-built for this tutorial, using the provided tileset.

Tiled2Unity is no longer a supported program, you will be using SuperTiled2Unity


instead. Please check the following lesson for more information about the differences.

SuperTiled2Unity can be found here: https://seanba.com/supertiled2unity.html. It is an updated


version of the Tiled2Unity program that is shown in this video. This can be downloaded for free, and
all you have to do is open the file while you have your Unity Project open. A similar package import
window will open, and you just need to click import. All of the files will be extracted, and added to

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

your Assets folder. This is the reasoning behind creating a Projects folder, as otherwise your
Assets folder would be hard to navigate.

To add tile maps to the Scene with SuperTiled2Unity, you can drag directly into the scene. The next
lesson will cover the methods for making sure that everything is compatible.

To edit your tile map collision detection, click on the town file, which will open up Tiled. Click on the
Edit tileset button, shown below:

This will open up a tool to edit the tiles. Make sure that the Tile Collision Editor is selected under the
Tileset tab.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Project setup

This will allow you to draw the collision area on any of the tiles that you select. This will allow you to
customize the various objects that you can build future games with, but will not be used in this
tutorial.

Now you can drag the town tilemap into the editor, and then follow the steps in the next lesson if
you run into any issues with SuperTiled2Unity.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Importing Tilemaps with Super Tiled2Unity

Current Unity versions natively support Tilemaps, so Tiled2Unity is currently outdated and
unsupported. However, its developers created a new project called Super Tiled2Unity that you can
use instead of Tiled2Unity. You can find it at this URL: https://seanba.com/supertiled2unity.html

The good news is that using Super Tiled2Unity is even easier than Tiled2Unity. After installing the
package, the only thing you need to do is drag and drop your Tiled maps to Unity and it will
automatically import the maps to your game.

The only thing you need to be careful is setting an appropriate value of Pixels per Unit, so that the
map fits in your game screen. You do this by selecting the imported map asset in the Unity editor.

If Unity shows an error that the file format is too old, you need to open the map in a more
recent version of Tiled and save it again.

This way, you can simply drag and drop the map asset to your game.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Title scene

In this lesson, you will learn how to create the title scene, which will be a basic menu to allow players
to press the play button.

You will need to add a canvas to your scene. To do this, right click under the Hierarchy menu, then
select UI and then canvas.

The canvas object is what is used to create an interface with the player. You can add images,
panels, buttons, and other kinds of things. Typically, a canvas will always be drawn over other
things in your game, like a HUD for example. Rename the newly created canvas to
BackgroundCanvas in the Inspector. You will also need to change the Render Mode to Screen
Space – Camera.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

Now you need to drag the Main Camera from the Hierarchy tab into the Render Camera field of
the Render Mode. This will make the BackgroundCanvas adjust with your camera as it moves.

You will also need to adjust some aspects of the Canvas Scaler (Script) component. Change the UI
Scale Mode to Scale With Screen Size, and change the Reference Resolution so that X is 1280
and Y is 960.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

Now you need to add an image object as a child of the BackgroundCanvas. You do this by right
clicking on BackgroundCanvas and then adding either an image object directly from the UI object
list or an empty GameObject, which you can then add an image component to in the Inspector.
Rename the image object BackgroundImage. Your Hierarchy tab should look like this:

Next, go to the Sprites folder, and then the battle folder. There will be a sprite called background.
Add this to the Source Image field of the BackgroundImage in the Inspector, and click on the
Set Native Size button.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

Now you will need to add another canvas in the Hierarchy tab, and name it HUDCanvas. This will
be the canvas where you have the title and play button. You will want to change the Render Mode
and Canvas Scaler (Script) for HUDCanvas the same way that you did for the
BackgroundCanvas.

You can now add the title text to this canvas. Right click on HUDCanvas, go to UI, and then select
Text. You can enlarge the size of the text box using the Rect Tool, which will put 4 small circles you
can drag to change the sizing. This will be a useful tool for editing the size of 2D objects.

Your text may not show up. This is due to the Order in Layer field of your canvas objects. To fix
this, you can either change the Order in Layer field of either canvas so that they are different, or
you can add a Sorting Layer. To add a Sorting Layer, click on the field, and then the Add Sorting
Layer option in the dropdown menu.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

Then, on the next screen, press the plus button, and write HUD in the new Layer field.

You can now go back to the HUDCanvas object, and change the Sorting Layer to this new layer.
As the HUD layer is below the Default layer, it has priority and will render on top. This is how the
layers are sorted, and you can arrange different layers to ensure they render correctly.

To increase the size of the text box equally horizontally and vertically, press the alt key while clicking
on one of the circles. This will allow you to enlarge it easily. Now, you can go into the Inspector, and
change the Text field to say Unity RPG. This will change the text shown in the editor. You will also
want to change the font to kells_unical, which you can do by pressing the small circle next to the
font field and choosing the font in the window that pops up. Change the alignment to center for both
options and increase the font size to 130. Your Text (Script) component should look like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

If your textbox isn’t large enough to fit the text, increase its size, and place it near the top of the
background image. It should look similar to this:

Now, you can add a Button object. Following the same steps as adding the image, make the Button
object a child of the HUDCanvas, and then increase its size to whatever you think looks good. The
Button object will have a Text object child, which you will want to adjust to have the same font

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

style and alignment as the other Text object. Increase the font size to whatever you think looks
appropriate. You should end up with something that looks similar to this:

You can test the scene to interact with the button, you can click on the play button above the editor,
and click on the button once the game is running.

If you want to change the color of the button, you can click on the Button, go to the Inspector, and
choose the Color field. You can then adjust this to be whatever color you want.

Now you can save this scene, which you can do under the File tab. If you are using a newer version
of Unity, your scene will already have a name, as well as a Scenes folder, which you should have put
under the Projects folder. Either save your scene as Title, or rename the scene that is in your
Scenes folder.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

The next step is to add this scene to the Build List. Go to the File tab, and then Build Settings.

On the window that opens, there will be a button that says Add Open Scenes. Press this. It will add
the Title scene to the list.

Now you will want to make a new scene. This is done either by going to the File tab and selecting
New Scene, or by pressing Ctrl+N. Save this new scene, and name it Town. Then, go to the Build
Settings again, and add this new scene to the list. To quickly get to the Build Settings, you can
press Ctrl+Shift+B.

Go back to the Title scene. Create a new folder, and name it Scripts. In this folder, you will add a

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

new C# script, which is the next option under folder. Name this new script ChangeScene, and open
it. This will open in the editor for your version of Unity, which will be Visual Studio if you are using a
newer version of Unity.

You will need to delete the Start and Update functions, add a new function for loading in a scene.
See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class ChangeScene : MonoBehaviour


{
public void LoadScene (string name) {
SceneManager.LoadScene(name);
}
}

Your function will take in a string which will be the name of the new scene. Note that you need to
add using UnityEngine.SceneManagement; at the top, which will allow you to access various
methods for managing scenes.

Now you can go back to Unity and drag the ChangeScene script into the Inspector panel of the
button. This will attach the script to the button. Under the Button (Script) component, there is a
field called On Click (). Press the plus button there, which will open up a new field.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

Drag your Button object into this new field, and then click on the dropdown menu. Choose
ChangeScene, and then LoadScene (string). You will need to write Town in the new text field. It
should look like this when you are done:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Title scene

Now, whenever the Button is clicked, it will call this function with Town as the parameter. Since
Town is a string, it should properly load the Town scene.

Make a new folder in your Scripts folder and name it Title. Put the ChangeScene script into this
folder. This will help keep things organized when you have more scenes, as each scene will have its
own dedicated folder.

You can now test the Button, and it should take you to your blank Town scene when you press it.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Player party

In this lesson, you will learn how to create and manage the player party, which will include their
statistics and when they show up in the game.

In the Title scene, create an empty GameObject, and name it PlayerParty. This should not be a
child of anything else. Remember, you just need to right click in the Hierarchy menu and choose
the object you want to add. Make sure this object is located at the Position X:0, Y:0, Z:0. You can
verify this in the Transform component of the PlayerParty in the Inspector.

Next, go into your Scripts folder, and create a new C# Script. Name this StartBattle. Add this
script to the PlayerParty object. You may need to wait a short period of time before adding while
the script compiles.

Add the following code to your StartBattle script in the Start function:

public class StartBattle : MonoBehaviour


{
// Start is called before the first frame update
void Start()
{
DontDestroyOnLoad(gameObject);
}
}

This code tells Unity to not destroy the gameObject that has this method when the scene changes.
In this context, it means that when the user clicks the Button, the PlayerParty object will be
preserved.

Now you need to add code to enable you to check what scene this object is located in. See the code
below:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; # Make sure to add this

public class StartBattle : MonoBehaviour


{
// Start is called before the first frame update
void Start()
{
DontDestroyOnLoad(gameObject);

SceneManager.sceneLoaded += OnSceneLoaded; # New code


}
}

You can delete the void Update function, as you will not be using it for this script. What this code
does is trigger the event sceneLoaded whenever the scene changes. It means that the new
function OnSceneLoaded will happen every time this object changes scenes. OnSceneLoaded is a
method you will be writing. See the code below:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player party

public class StartBattle : MonoBehaviour


{
// Start is called before the first frame update
void Start()
{
DontDestroyOnLoad(gameObject);

SceneManager.sceneLoaded += OnSceneLoaded;

gameObject.SetActive(false); # New code


}

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)


{
if (scene.name == "Title") {
SceneManager.sceneLoaded -= OnSceneLoaded;
Destroy(gameObject);
}
else
{
gameObject.SetActive(scene.name == "Battle");
}
}
}

This code will allow OnSceneLoaded to deactivate the PlayerParty object for any scene that is not
the Battle scene, which you will be making later. By including gameObject.SetActive(false); in
the Start function, PlayerParty will always start not being active.

You can test this by clicking the play button. You will see that the PlayerParty object is now
below DontDestroyOnLoad, and is grayed out. This because it is not active.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player party

You can now add different player characters to the PlayerParty object. Start by creating an
empty gameObject as a child of the PlayerParty and labeling it PlayerUnit. You will want to add
an Image component to PlayerUnit.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player party

In the Image component, click on the Source Image field and select one of the mage sprites that
you sliced in the earlier lesson.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player party

You will not be able to see your mage sprite yet, as PlayerObject is not part of a canvas. Image
components will only work for as part of a canvas, so you will need to instead use a Sprite
Renderer. Add this the same way you did the Image component, and put one of the mage sprites
in the Sprite field.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player party

Position your mage sprite onto your BackgroundCanvas on the right-hand side.

The next step is to make a C# Script to handle the unit stats. Go into your Scripts folder, create a
new script, and name it UnitStats. Open it in the editor, and remove
the Start and Update functions, then add the following code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UnitStats : MonoBehaviour


{
public float health;
public float mana;
public float attack;
public float magic;
public float defense;
public float speed;
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player party

These are all public float variables, meaning they can have decimal values, and you will be able to
give them values in the Inspector when you attach this script to a gameObject. Save the script,
and add it to your PlayerUnit. Right now, all of these values are zero. You can set the following
values, or any that you’d like to play around with:

Health: 100
Mana: 100
Attack: 100
Magic: 10
Defense: 0
Speed: 10

You can now rename PlayerUnit to be MageUnit. This will be the first character, you will be making
more later.

Now you can test your game. The mage sprite should not show up, and when you hit the
play button, you should go to the Town scene and see that the PlayerParty is still there, but is
grayed out. If you want to test your StartBattle script, you can change the name in the else
statement of OnSceneLoaded to be Town, and your mage sprite will show up. Make sure to
change the name back to Battle if you do this.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Town graphics

In this lesson, you will learn how to add the map and player to your Town scene.

Adding the Town Map

As you will be using SuperTiled2Unity, to add your Town map to your scene, you need to go to
your Maps folder, and then drag the Town into the main window. You will want to move and resize
the town map using the Transform component until it fits your Main Camera. As the Main
Camera size changes based off your Unity layout, there will not be any default values you can use.
Play around with the Position and Scale until you like how it looks and remember that adjusting
your layout will change the size of your Main Camera viewing region.

Make sure to test it out by pressing the play button to verify everything fits nicely.

Adding the player character

Create an empty gameObject, making sure that it is not a child of anything, and rename it Player.
Add a Sprite Renderer to the Player, and then add the player_0 sprite to the Sprite field.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Town graphics

You will notice that the Player sprite does not show up. This is once again due to Unity’s layer
sorting system. Add a new layer, name it Game, and move it between Default and HUD by clicking
on the 3 horizontal lines and dragging. Set the Sorting Layer field to this new layer. Now you can
see your Player sprite. It will be quite small, so use the Scale field and make the X:2 and the Y:2.

Now you want to add a Rigidbody 2D component to your Player. Make sure that you do not use
the Rigidbody component that is not 2D. When making 2D games, you should always check if there

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Town graphics

is a 2D version and use that one. You will want to change the Collision Detection field to be
Continuous, the Interpolate field to be Interpolate, and the Gravity Scale to 0. As this is a top
down 2D game, there is no need for gravity. Now, go under the Constraints tab, and select the Z
checkbox for Freeze Rotation. Your Rigidbody 2D component should look like this.

The next step is to add a BoxCollider 2D to your Player. You will see a little square on the Player
sprite. This is showing the boundaries of the collider.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Town graphics

In the next lesson, you will be learning how to handle the player movements and animations.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Player animations

In this lesson you will learn how to create the animations for your player character.

Make a new folder in your Project folder, and name it Animations. Inside this folder, make another
folder and label it Player. To make animations, you will need two things, an Animator, and the
animations. Go to your Town scene, select the Player object, and add an Animator component to
it.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

An Animator is like a state machine which contains the logic of when to use different animations.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

You could do this with code but using the Animator tool will allow you to do this a little easier.

Now, go to the Player folder in your Animations folder, and add an Animator Controller.

Name this PlayerAnimator and drag it to the Controller field of the Animator component you just
added to the Player object.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

The Player object will have eight animations, 2 for each direction as there will be an idle animation
and a movement animation for each. Create an empty Animation in the Player folder by right
clicking and going under Create , and name it IdleLeft. To speed up the process of making the
other animations, use the keyboard shortcuts Ctrl+D for Windows or Cmd+D for Mac to duplicate
the animation, and then either F2 for Window or Enter for Mac to rename it. You will need all of the
following animations: IdleLeft, IdleRight, IdleUp, IdleDown, WalkingLeft, WalkingRight,
WalkingUp, and WalkingDown.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

You will now want to add two Windows to your editor, Animation and Animator. To do this, go to
the Window tab, select Animations, and then add both of them.

This may look a little different depending on which version of Unity you are using, and which OS you
are on.

Now, click on your Player object, and then go to the Animator window. You should see two icons,
one that says Any State and one that says Entry. Drag all of the animations you just made into the
window, either one by one or all together using the Ctrl/Cmd key to select multiple, and you should
something similar to the following. If you need to move around the Animator window, press the Alt
key and click and hold your mouse to move.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

Go to the Animation window. There will now be a timeline in the main window, and if you click on
the dropdown field, you will see each of the animations you added.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

Now open up the Sprite folder, and then go to the world folder. Locate the player sprite that you
sliced in an earlier lesson, and expand it. You should see the different sprites of the player, all facing
different directions. What you will want to do now is drag the sprite that matches the animation into
the Animation window. So for IdleDown, you should drag the player_0 sprite, and your
Animation window will look like this:

Do this for each of the idle animations, matching the sprite to the appropriate animation.

IdleDown: player_0 (should be already done)


IdleLeft: player_2
IdleRight: player_3
IdleUp: player_1

Now, for the walking animations, you will need to use 5 sprites, as this is a more complex
animations. For WalkingDown, you will use player_4, player_8, and player_12. Starting with
player_4, drag these sprites into the Animation window, spaced every 0:10. The order will be 4, 8,
12, 8, 8. When you are finished, the Animation window should look like this.

You can fine tune the frame time by selecting the diamond over the sprite. Now, do the rest of the
animations, using the following sequences:

WalkingDown: 4, 8, 12, 8, 8 (should be already done)

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

WalkingLeft: 6, 10, 14, 10, 10


WalkingRight: 7, 11, 15, 11, 11
WalkingUp: 5, 9, 13, 9, 9

Each of these animations should have the sprites at 0:00, 0:10, 0:20, 0:30, 0:40. The repetition of
the sprite at the end is to ensure that the animation has a transition between each of the arm
movements.

If you want to check this animation, you can drag your Scene window somewhere else in the editor,
making sure you can see the Player sprite, and press the play button in your Animation window.
Your Player should appear to be moving the direction of the animation.

Now you need to go to the Animations folder, then to the Player folder, and then select one of your
walking animations. You will see in the Inspector that there is a checkbox that says Loop Time.
You will want to check this box for each of your walking animations, to make sure that the
animations will not only play once.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animations

In the next lesson, you will learn about how to use the Animator state machine to control these
animations you just created.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Player animator controller

In this lesson, you will learn how to setup the animator.

First, go to the Animator window, and change to the Parameter tab. You will then need to press
the plus button, and add two int variables, naming them DirectionX and DirectionY. These will be
used later on to control the state machine you will create. Your Parameter tab should look like this:

Arranging the States

Now, take the four Idle state boxes, and arrange them in the Animator window so that they match
their directions, IdleUp on top, IdleRight on the right, IdleLeft on the left, and IdleDown on
bottom. You will want to make sure that Entry is attached to IdleDown. If it is not, right click on
the Entry box, select Set StateMachine Default State, and drag the new arrow to IdleDown. It
should then turn orange. Your Animator window should end up looking like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

Now, place the Walking animations near their corresponding Idle animations, leaving a bit of room
in between the state boxes. The order doesn’t matter here, so arrange them however makes the
most sense to you. Your Animator window should look similar to this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

Setting up the Transitions

To make sure that animations are played properly, you will need to setup transitions between the
various states. As the Idle animations need to be able to transition to any of
the Walking animations, you will need to add a transition from each Idle state to
every Walking state. To do this, you will need to right click on one of the Idle states, select Make
Transition from the pop up window, and then select one of the Walking states.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

This will make a white arrow that connects the two states.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

Now you can do the same thing, connecting each Idle state to all of the Walking states. In
the Inspector, you should see each new transition being added in the Transitions field.

When you are finished adding adding all the transitions, your Animator window should look like the
following image. Make sure to verify in the Inspector that each Idle state is matched to all
4 Walking states.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

The Walking animations will be slightly more complex. As you want your character to be able to
transition to the corresponding Idle animation when you are done walking, you will need to make a
transition from each Walking state to the corresponding Idle state. You will also need to make a
transition from each Walking state to every other Walking state, to allow for seamless switching
from one direction to another.

There should now be numerous white arrows in your Animator screen. This is where
the Inspector window will be very useful to verify that you have properly connected the transition.
Each Idle state should have 4 transitions, to all of the Walking states. Each Walking state should
also have 4 transition, one to the corresponding Idle state, and one to each of the
other Walking states.

Adding Transition Conditions

Now that you have all of the transitions in place, you will need to add conditions to each one, to
determine when they will trigger. This is when the Parameters will come into play. Click on
the IdleDown state, and then on the IdleDown->WalkingDown transition in the Inspector. In
the Inspector, you should see a field that says Conditions. Click on the plus. This should open a
new field.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

In the Conditions field, you will want to select the DirectionX, and change it to DirectionY. Then
click on the dropdown field and change it to Less.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player animator controller

What this means is that when the change in the Y direction of the Player is negative, this transition
will trigger. Now, you will need to add a condition for each of the transitions from the Idle states to
your Walking states. Each of them will match the following pattern:

For WalkingDown, choose DirectionY, Less, and 0.


For WalkingUp, choose DirectionY, Greater, and 0.
For WalkingLeft, choose DirectionX, Less, and 0.
For WalkingRight, choose DirectionX, Greater, and 0.

When you finish all of the Idle transitions, make sure to verify them before moving on to
the Walking state transitions. For the Walking state to Walking state transitions, follow the same
pattern as for the Idle state to Walking state transitions shown above. However, for
the Walking state to Idle state transitions, you will want to set the conditions to be
both DirectionX and DirectionY equal to 0. This will indicate that the Player is no longer moving
and should start the Idle animation.

Add all of the conditions to the Walking state transitions. Unfortunately, there are no easy shortcuts
for this, you’ll have to manually go through and enter all of the transitions. Make sure to verify when
you are done, as you don’t want to miss any.

You can test this by hitting the play button, and then clicking on the Animator window to see that
the IdleDown state is active. As you have not yet implemented movement control, there is no way
to exit from this state. You will be doing that in the next lesson.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Player movement

In this lesson, you will be writing the script that will enable the Player to move.

Open the Scripts folder, create a new C# script, and name it PlayerMovement. Attach this new
script to your Player object, and then open it.

Add the following code to your script to generate two new variables.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour


{
public float speed; # New code

public Animator animator; # New code

// Start is called before the first frame update


void Start()
{

// Update is called once per frame


void Update()
{

}
}

This will create two variables that you can edit directly in the Unity editor.

However, to protect these variables from somehow being edited during gameplay by another script,
you can use a different method. See the code below:

[SerializeField]
private float speed;

[SerializeField]
private Animator animator;

What this does is ensure that the script can only be edited in the Unity editor, and cannot be altered

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player movement

by other scripts.

Change the Speed field of the PlayerMovement (Script) to be 3, and drag the Player object into
the Animator field. This will attach the correct Animator for you.

Now you can go back to the script, and delete the Start method. You will not be using it for this.
Change the Update method to FixedUpdate, as this version works with the physics system and is
more suited to what you will be doing. It will use the same amount of time to calculate updates,
ensuring that there will be no issues due to a computer’s frame rates.

First, you will need to add in some logic for handling horizontal movement. See the code below:

public class PlayerMovement : MonoBehaviour


{
[SerializeField]
private float speed;

[SerializeField]
private Animator animator;

void FixedUpdate() # New code


{
// Horizontal Movement
float newVelocityX = 0f;
if (Input.GetKey (KeyCode.LeftArrow))
{
newVelocityX = -speed;
animator.SetInteger("DirectionX", -1);
}
}
}

This will check if the left arrow is being pressed, and if it is, will set the newVelocityX to be the
negative value of your speed variable. It will also set the DirectionX parameter of
your Animator to be -1, which will allow the state machine you set up in the previous lesson to
operate properly.

To add the logic for the right arrow, see the code below:

else if (Input.GetKey(KeyCode.RightArrow))
{
newVelocityX = speed;
animator.SetInteger("DirectionX", 1);
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player movement

This is basically the same as the left arrow block, with the values being opposite and
the KeyCode checking for the right arrow.

The final block for the horizontal movement will be if no key is pressed. See the code below:

else
{
newVelocityX = 0f;
animator.SetInteger("DirectionX", 0);
}

The vertical movement will be very similar, just using DirectionY and the down and up arrow
instead. See the code below:

// Vertical Movement
float newVelocityY = 0f;
if (Input.GetKey(KeyCode.DownArrow))
{
newVelocityY = -speed;
animator.SetInteger("DirectionY", -1);
}
else if (Input.GetKey(KeyCode.UpArrow))
{
newVelocityY = speed;
animator.SetInteger("DirectionY", 1);
}
else
{
newVelocityY = 0f;
animator.SetInteger("DirectionY", 0);
}

You have now created the logic that will handle the Player movement, but you still need to move
the Player. To do this, you will be accessing the RigidBody2D of the Player, and using that to
update the velocity. See the code below:

gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(newVelocityX, newVeloc


ityY);

You can now test out your game, and move your character around. It should move properly, with the
corresponding animations going at the right times. If this is not the case, double check all of your
transitions to ensure that they are set up correctly.

Your Player should successfully run into objects in the game. This is the benefit of using
the Tiled tool, it allows you to easily create new maps for new levels.

Make a new folder in your Scripts folder, name it Town, and put the PlayerMovement script there.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player movement

Don’t worry about the other scripts for now, those will be handled in later lessons.

Full code for this lesson:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour


{
[SerializeField]
private float speed;

[SerializeField]
private Animator animator;

void FixedUpdate()
{
// Horizontal Movement
float newVelocityX = 0f;
if (Input.GetKey (KeyCode.LeftArrow))
{
newVelocityX = -speed;
animator.SetInteger("DirectionX", -1);
}
else if (Input.GetKey(KeyCode.RightArrow))
{
newVelocityX = speed;
animator.SetInteger("DirectionX", 1);
}
else
{
newVelocityX = 0f;
animator.SetInteger("DirectionX", 0);
}

// Vertical Movement
float newVelocityY = 0f;
if (Input.GetKey(KeyCode.DownArrow))
{
newVelocityY = -speed;
animator.SetInteger("DirectionY", -1);
}
else if (Input.GetKey(KeyCode.UpArrow))
{
newVelocityY = speed;
animator.SetInteger("DirectionY", 1);
}
else
{
newVelocityY = 0f;
animator.SetInteger("DirectionY", 0);
}

gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(newVelocityX, n

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Player movement

ewVelocityY);
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Trigger a battle

In this lesson, you will learn how set up battle scenes and trigger battles.

Setting up the Enemy Units

You will want to go to your Title scene. In the Hierarchy, create an empty gameObject and name
it SnakeUnit. Make sure that it is not a child of any other objects. Add a Sprite Renderer to the
SnakeUnit and choose snake_0 for the Sprite field.

Add the UnitStats script to the SnakeUnit, either using the Add Component button or by
dragging it from your Scripts folder. Set the values to the fields in the UnitStats. Feel free to make
these whatever you want, they can be adjusted later on.

Now, you are going to make this SnakeUnit a prefab. Go to your Project folder, create a new
folder, and name it to Prefabs. In this folder, drag the SnakeUnit, from the Hierarchy and put it in
this folder. You can now delete the SnakeUnit, as you won’t be using it right away.

Setting up the Enemy Encounter

Make an empty gameObject, and name it EnemyEncounter. Drag your prefab SnakeUnit and
make it a child of EnemyEncounter. Then duplicate your instance, using Ctrl/Cmd+D. You should
now have two snake sprites on the screen, arrange them however looks best to you. It should look
like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

Now, drag the EnemyEncounter object to your Prefabs folder and make it a prefab. Rename the
EnemyEncounter prefab to be SnakeEncounter. Remember that with prefabs, if you change
things in one instance, it won’t automatically sync to all of the rest. There are ways to get around
this, but they are beyond the scope of this lesson.

In your Prefabs folder, make two new folders, EnemyUnits and EnemyEncounters. Put the two
prefabs in their appropriate folder.

Creating the Enemy Spawner

Go to your Town scene, making sure to save the Title scene prior to switching. Make a new empty
gameObject, and name it EnemySpawner. Add a Sprite Renderer, change the Sorting Layer to
be Game, and select the snake sprite in the Sprite field. This is a different snake sprite from the
enemy unit, but that’s ok because this is just an icon. If you would prefer to use something different,
feel free to do so.

Increase the Scale of the EnemySpawner to be 2 for each value. Now add a BoxCollider2d
component and choose the Is Trigger checkbox.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

It is important to make sure that Is Trigger is selected, because you will be doing a collision check
between this and the Player.

In your Scripts folder, create a new C# script and name it SpawnEnemy. Attach it to your
EnemySpawner object and open it in the editor.

You will need to add in the scene management namespace, and two variables. Feel free to delete
the Update method, as you will not be needing it. See the code below:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SpawnEnemy : MonoBehaviour


{
[SerializeField]
private GameObject enemyEncounterPrefab;

private bool spawning = false;

// Start is called before the first frame update


void Start()
{

}
}

Each enemy spawner that you collide with will need to have a prefab assigned to it. For this case, it
will be the SnakeEncounter that you made earlier.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

Now you will need to add some code for scene management. See the code below:

// Start is called before the first frame update


void Start()
{
DontDestroyOnLoad(gameObject);

SceneManager.sceneLoaded += OnSceneLoaded;
}

This will ensure that this object won’t be destroyed, and as with the play button script you wrote
earlier, this will need a function created for OnSceneLoaded. See the code below:

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)


{
if(scene.name == "Battle")
{
if(spawning)
{
Instantiate(enemyEncounterPrefab);
}
SceneManager.sceneLoaded -= OnSceneLoaded;
Destroy(gameObject);
}
}

What this nested if does is check if the scene is Battle, and if spawning is true. If both of these are
true, then the SnakeEncounter prefab will be instantiated. Then the EnemySpawner will be
destroyed.

Now you can add code to check if the Player has collided with the EnemySpawner. See the code
below:

void OnTriggerEnter2D(Collider2D other)


{
if (other.gameObject.tag == "Player")
{
spawning = true;
SceneManager.LoadScene("Battle");
}
}

This code will make it so that when the Player collides with the EnemySpawner, the Battle scene
will be loaded, spawning will be true, and the SnakeEncounter prefab will be loaded.

Make sure you save this, and then go back to the Town scene and select your Player object. In the
Inspector, select the Tag dropdown field, and select Player.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

Make sure you save the Town scene, and them make a new scene. You can do this either by going
to File, or by hitting Ctrl/Cmd + N. Save the new scene as Battle, and make sure that it is in your
Scenes folder. Go to File, Build Settings, and then choose Add Open Scenes to add this new
scene to your build. You can also use the keyboard shortcut Ctrl/Cmd + Shift + B to get to this menu.

You can now test your game out. Go back to the Title scene and play the game. After selecting the
play button and walking your Player into the EnemySpawner, you should get to a scene with the
mage character and the snake sprite, like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

The EnemySpawner wasn’t destroyed, because you have not yet assigned the SnakeEncounter
prefab, so the code is disrupted prior to the Destroy(gameObject) line. To fix this, go back to your
Town scene, select the EnemySpawner, and drag the SnakeEncounter prefab to the Enemy
Encounter Prefab field of your Spawn Enemy (Sript). Save the Town scene again, then go back
to the Title scene and test out the game.

You should now have the two snake units on the screen with your mage.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

This is just the setup for the battle system. The logic behind battling will require a number of
different scripts. That will be covered in the next few lessons.

Full code for lesson:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SpawnEnemy : MonoBehaviour


{
[SerializeField]
private GameObject enemyEncounterPrefab;

private bool spawning = false;

// Start is called before the first frame update


void Start()
{
DontDestroyOnLoad(gameObject);

SceneManager.sceneLoaded += OnSceneLoaded;
}

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)


{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Trigger a battle

if(scene.name == "Battle")
{
if(spawning)
{
Instantiate(enemyEncounterPrefab);
}
SceneManager.sceneLoaded -= OnSceneLoaded;
Destroy(gameObject);
}
}

void OnTriggerEnter2D(Collider2D other)


{
if (other.gameObject.tag == "Player")
{
spawning = true;
SceneManager.LoadScene("Battle");
}
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Battle scene setup 1

In this lesson, you will learn how to setup your battle scene to allow you to fight the enemy units.

Setup for the HUD Overlay

Go to your Battle scene, and add a Canvas object. This should not be a child of anything you have
in the Hierarchy. Name this BackgroundCanvas, and change the Render Mode to Screen Space
– Camera. Drag the Main Camera object to the Render Camera field. Under the Canvas Scaler
(Script), change the UI Scale Mode to be Scale With Screen Size, and change the Reference
Resolution to 1280 for X and 960 for Y.

Now you can add an Image object as a child of the BackgroundCanvas. Under the Image
(Script) in the Inspector, select the circle by Source Image, and add the background image. You
should then press the Set Native Size button.

Add another Canvas, and name it HUDCanvas. Apply the same settings to this canvas that you did
to the BackgroundCanvas, but change the Sorting Layer to HUD. You will then need to add
a Raw Image to the HUDCanvas. This is under the UI option, as shown below.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

What this will allow you to do is create a simple overlay, as you will be able to make
this RawImage a particular color. Rename this Overlay. In the upper left corner of
the Inspector panel, you will see a little box. This is for Anchor Presets, which will allow you to
change the positions of interface elements based on certain anchors. You will want to press the Alt
key, and then select the Stretch option for the Bottom.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

This will move the Overlay to the bottom. You will want to increase the size now, which you can do
with the Rect Tool, which you can access by pressing T. Drag the small blue circle until you like how
large the Overlay is. Change the Color under the Raw Image (Script) to be a gray color, or any
color you would like for you HUD.

Implement the Action Menu

You can now implement the controls for the various actions the player of your game can do, attack,
magic, run away, etc.

Go to the HUDCanvas, and make a new empty GameObject, and name it ActionsMenu. Make
sure that this is a child of the HUDCanvas. You will be making three buttons: a physical attack
action, a magical attack action, and a run away action.

Under the ActionsMenu, create another empty GameObject, and name it PhysicalAttackAction.
Add an Image to this and select the Source Image field. If you remember from the earlier lesson,
you sliced an icon sprite sheet. Now you can use one of them for this. You will want to add icons_13,
the sword.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

Press the Set Native Size button to ensure it is the correct size, and the add a Button component
to the PhysicalAttackButton. Also, you will want to move the PhysicalAttackButton away from
the center, to -90 on the X coordinate.

Now to quickly make the other actions, duplicate the PhysicalAttackButton twice. Rename one of
the new objects to MagicAttackButton. You can choose whichever icon you think works best for
this, the lesson uses icons_10. Move the MagicAttackButton to 0 for the X coordinate. For the
third one, rename it to be RunAction, move it to positive 90 for the X coordinate and give it a
suitable icon, such as icons_11.

A convenient aspect of how you have set up the hierarchy for this is you can set all three buttons to
be at a Y value of 0, and then move the ActionsMenu object to be at the desired vertical level.

When you have finished making these three buttons, it should look like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

Each of these buttons will later on have a function to do something in the game, but for right now
you don’t need to worry about that, as there is more to the interface you need to setup first.

Implement the Enemy Units Menu

To implement the enemy targeting system, you will need to make another menu. You could set this
up so that the enemy icons are clickable, but this isn’t recommended as there could be problems
with clicking on the wrong unit.

Under the HUDCanvas, add an empty GameObject, and name it EnemyUnitsMenu. Under this,
add another empty GameObject, and name it TargetEnemy. Add an Image component to this and
choose snake_face as the Source Image. Make sure to select the Set Native Size to ensure it is
the right size. Add a Button to TargetEnemy as well. Change the Scale to 0.7 on both X and Y, to
make the icon a little smaller. This isn’t necessary, simply a cosmetic choice. Move
the TargetEnemy to the bottom left corner. Your Scene window should look something like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

You will now need to make TargetEnemy a prefab. Drag it into your Prefabs folder, and then
delete it from your Battle scene.

Adding the Enemy Unit Items to your HUD

To enable you to add the TargetEnemy prefabs when you go into the Battle scene, you will need to
add some C# scripts to the enemy unit prefab. Go to your EnemyUnits folder in
your Prefabs folder and drag an instance of the SnakeUnit into your Scene window.

Add two C# scripts to your Scripts folder. Name one of them KillEnemy, and the
other CreateEnemyMenuItems. Open both of these scripts up.

What the KillEnemy script does is remove the menu item for the enemy once it is dead. You can
remove the Start and Update method, as you won’t be using them. You will add
a GameObject variable, and a function, OnDestroy. See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KillEnemy : MonoBehaviour


{
public GameObject menuItem;

void OnDestroy()

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

{
Destroy(menuItem);
}
}

Now save this script, wait for it to compile, and attach it to your SnakeUnit prefab. There will be a
field to attach a GameObject, but don’t put anything there. That will be handled by another script.

Go to the CreateEnemyMenuItems script. Go ahead and delete the Start and Update method,
and then add the variables in the following code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CreateEnemyMenuItems : MonoBehaviour


{
[SerializeField]
private GameObject targetEnemyUnitPrefab;

[SerializeField]
private Sprite menuItemSprite;

[SerializeField]
private Vector2 initialPosition, itemDimensions;

[SerializeField]
private KillEnemy killEnemyScript;
}

You will need to add a new namespace using UnityEngine.UI to make sure everything works for
this. The first variable, targetEnemyUnitPrefab, is for the TargetEnemy prefab that you created
earlier. The next, menuItemSprite, will be for the sprite of the enemy. This will allow you to just use
the one TargetEnemy prefab, and edit the values for different enemies. The 2 Vector2 variables
will be used to change the position and scale of the menu items that this script will generate. The
final variable, killEnemyScript, is what you will use to assign the menuItem in
the KillEnemy script that you just wrote.

Now you can add code to handle the creation of the enemy menu items. See the code below:

void Awake()
{
// Find the units menu.
GameObject enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");

// Calculate the item position.


GameObject[] existingItems = GameObject.FindGameObjectsWithTag("TargetEnemyUnit")
;
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

This code will run before the Start method, as that is what Awake is for, and will search in your
scene for an instance of EnemyUnitsMenu, and assign it to the enemyUnitsMenu variable in your
script. It will also search for any objects with the tag TargetEnemyUnits, and assign them to
the GameObject array existingItems. This will enable you to offset the enemy unit menu items
when you have multiple enemies, so that they are not stacked on top of each other.

In order to make this operate properly, you need to add the tag TargetEnemyUnit. You will want to
go to the TargetEnemy prefab, select Tag in the Inspector, and add the new tag. If you are using
a newer version of Unity, there will be a dedicated prefab menu, just click on the Open
Prefab button and do the same thing.

Click on the plus, and type in TargetEnemyUnit. It is crucial that you put the same tag here that
you used in your script, so double check for any errors before moving on. Make sure to apply this
newly created tag to your prefab. Save the scene and the project now. This is a good habit to get
into, to make sure that you don’t lose any progress in case something happens

Now you can add the code to handle changing the position of the enemy menu items based on how
many there are. See the code below:

void Awake()
{
// Find the units menu.
GameObject enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");

// Calculate the item position.


GameObject[] existingItems = GameObject.FindGameObjectsWithTag("TargetEnemyUnit")
;
Vector2 nextPosition = new Vector2(
initialPosition.x + (existingItems.Length * itemDimensions.x),
initialPosition.y
); # New code
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

This code will calculate the amount that the new menu item needs to move by, if there are multiple
items. Note that the Y value will stay the same. This could possibly change if you wanted to make
multiple rows of enemies, but that is not coverd in this lesson.

You can now instantiate the item. See the code below:

// Instantiate the item.


GameObject targetEnemyUnit = Instantiate(targetEnemyUnitPrefab, enemyUnitsMenu.transf
orm);
targetEnemyUnit.name = "Target" + gameObject.name;
targetEnemyUnit.transform.localPosition = nextPosition;
targetEnemyUnit.transform.localScale = new Vector2(0.7f, 0.7f);

This code will create a new GameObject that is an instance of the prefab you will assign to
targetEnemyUnitPrefab, and make it a child of the enemyUnitsMenu. If you don’t do this, it will
be outside of the menu, and that would be problematic. The next operation will simply change the
name of this new item to be Target and the name of the enemy unit. For the SnakeUnit, this
means that the new objects will be called TargetSnakeUnit. To change the position of this item,
you will use the nextPosition Vector2 that you made with the earlier code. You need to make sure
to use the localPosition so that it will be relative to the EnemyUnitsMenu that it is a child of. You
also need to change the scale, so that the item will not be too large.

You can now add the code to generate the callback for the button. See the code below:

void Awake()
{
// Find the units menu.
GameObject enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");

// Calculate the item position.


GameObject[] existingItems = GameObject.FindGameObjectsWithTag("TargetEnemyUnit")
;
Vector2 nextPosition = new Vector2(
initialPosition.x + (existingItems.Length * itemDimensions.x),
initialPosition.y
);

// Instantiate the item.


GameObject targetEnemyUnit = Instantiate(targetEnemyUnitPrefab, enemyUnitsMenu.tr
ansform);
targetEnemyUnit.name = "Target" + gameObject.name;
targetEnemyUnit.transform.localPosition = nextPosition;
targetEnemyUnit.transform.localScale = new Vector2(0.7f, 0.7f);

# New code
targetEnemyUnit.GetComponent<Button>().onClick.AddListener(() => SelectEnemyTarge
t());
targetEnemyUnit.GetComponent<Image>().sprite = menuItemSprite;

// Set the menu item in the KillEnemy script.


killEnemyScript.menuItem = targetEnemyUnit;
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

public void SelectEnemyTarget()


{

This new code addition will eventually be what you use to enable you to click on the button to select
an enemy target, and will set the new menu item in the KillEnemy script.

Now go back to the Unity editor, and select the SnakeUnit prefab. Add
the CreateEnemyMenuItems script to the object. There will be multiple fields to add objects to. For
the Target Enemy Unit Prefab, you will want to drag you TargetEnemy prefab to this and drop it
in. For the Menu Item Sprite, you will need to select the snake_face sprite again by clicking on the
little circle and choosing it. For the Initial Position, either write in -550 for X and -360 for Y, or add
an instance of your enemy unit icon, and move it to where you want and copy those numbers. For
the Item Dimensions, put in 160 for both X and Y. For the KillEnemy script field, simply drag the
instance of your SnakeUnit to this. Your Create Enemy Menu Items (Script) should look like this
in the Inspector.

Now you need to make sure to update your SnakeEncounter prefab. If you are using a new version
of Unity, you will need to double click the SnakeEncounter prefab to open the Prefab menu, delete
the two older instances of the SnakeUnit that are there, and drag an instance of your
updated SnakeUnit prefab into the Hierarchy as a child. Duplicate it, and make sure to move of
the copies so that both are showing. Unity will no longer allow you to break prefabs in the main
editor, but you can still move items as shown in the video. To update the SnakeEncounter prefab
from the main editor, choose the Overrides button, and then choose Apply All for any changes that
you want to make.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

You can now delete the SnakeEncounter from your Hierarchy.

Feel free to now test your game. Go through the Title and walk your Player into
the EnemySpawner. You should end up with something like this:

You may need to spend some time tweaking the positioning of your enemy units and icons to get a
good layout. To do this, you will have to edit the SnakeEncounter prefab for the SnakeUnit’s, the
values in the Initial Position field of the Create Enemy Menu Items (Script) component of

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

the SnakeUnit prefab to change the menu item position, and the Transform of
the ActionsMenu to adjust the action icons.

Full code for the CreateEnemyMenuItems script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CreateEnemyMenuItems : MonoBehaviour


{
[SerializeField]
private GameObject targetEnemyUnitPrefab;

[SerializeField]
private Sprite menuItemSprite;

[SerializeField]
private Vector2 initialPosition, itemDimensions;

[SerializeField]
private KillEnemy killEnemyScript;

void Awake()
{
// Find the units menu.
GameObject enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");

// Calculate the item position.


GameObject[] existingItems = GameObject.FindGameObjectsWithTag("TargetEnemyUn
it");
Vector2 nextPosition = new Vector2(
initialPosition.x + (existingItems.Length * itemDimensions.x),
initialPosition.y
);

// Instantiate the item.


GameObject targetEnemyUnit = Instantiate(targetEnemyUnitPrefab, enemyUnitsMen
u.transform);
targetEnemyUnit.name = "Target" + gameObject.name;
targetEnemyUnit.transform.localPosition = nextPosition;
targetEnemyUnit.transform.localScale = new Vector2(0.7f, 0.7f);
targetEnemyUnit.GetComponent<Button>().onClick.AddListener(() => SelectEnemyT
arget());
targetEnemyUnit.GetComponent<Image>().sprite = menuItemSprite;

// Set the menu item in the KillEnemy script.


killEnemyScript.menuItem = targetEnemyUnit;
}

public void SelectEnemyTarget()


{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 1

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Battle scene setup 2

In this lesson, you will learn how to show player unit information in your HUD.

Creating the Unit Icon

Open up your Battle scene and add a new empty GameObject under the HUDCanvas. Name
it PlayerUnitInformation. This object will have 3 elements, an icon for the unit, the unit’s health,
and the unit’s mana.

Add an Image under the PlayerUnitInformation and name it PlayerUnitFace. Make the Source
Image the mage_face image and hit the Set Native Size button. Now move this image to the
bottom right of your Overlay.

Creating the Health Bar

For the health bar, you will need to have both an image and text. Under
the PlayerUnitInformation add an Image, and name it PlayerUnitHealthBar. Make the Source
Image the healthbar and choose the Set Native Size. Manually position it to be near
your PlayerUnitFace icon, wherever you think is a good position.

Now add a Text UI element under the PlayerUnitInformation, name it PlayerUnitHealthText,


and move it above the PlayerUnitHealthBar. Resize it so that it is approximately the same size as
the PlayerUnitHealthBar using the Rect Tool (Ctrl/Cmd +T), and then change the Font Style to
be Bold, the Font Size to be 36, and the Alignment to be the center option for both. Change the
text to say “HP”. Feel free to change the color to whatever you think looks best.

You should end up having something that looks like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 2

To get the PlayerUnitHealthBar to scale down like a healthbar should, you need to change
the Anchors in the Rect Transform component in the Inspector. Set all the X values to be 0. Now,
you can change the X scale value and the health bar should shrink with the left side staying
stationary.

Creating the Mana Bar

To create the mana bar, select both the PlayerUnitHealthBar and PlayerUnitHealthText by
holding Ctrl/Cmd and clicking, and duplicate them. Rename both so that they say mana instead of
health and move them below the health bar. Change the Text field of PlayerUnitManaText to say
“MP.” Change the PlayerManaHealthBar Source Image to be manabar instead of
the healthbar image. When you are done, it should look like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Battle scene setup 2

You can now test your game, and should enter the battle scene with the two snake units and all of
the icons. It should look like this:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Animations

In this lesson you will learn how to animate the units in the battle scene.

Animating the Mage Unit

Go to your Title scene. Create a new folder in your Animations folder, and name it Mage. In this
new folder, create an Animator Controller and name it MageAnimator. Drag this
new MageAnimator to your MageUnit.

For every different kind of unit, you will need to make 4 different animations. In your Mage folder,
create a new Animation and name it Idle. Duplicate this three times. You will need a Hit animation,
a PhysicalAttack animation, and a MagicalAttack animation. Your folder should look like this
when you are done:

Select the MageUnit and open your Animator window. Drag all four of the animations you just
created into the window, and make sure that Idle is first so it will be the default state. Make
transitions from Hit, PhysicalAttack, and MagicalAttack to Idle. This is because
the Idle animation is the default and will be played in between the other actions. Select
the Idle animation and check the Loop Time checkbox. This is necessary because this animation
will need to play repeatedly.

Now open the Animation window. Select Idle in the drop down menu. Open your Sprites folder,
and then the battle folder. Select the mage sprite sheet, and then click the arrow to see all the
sliced sprites you made earlier. If you use the arrow key to navigate between mage_0 and mage_4,
you can watch in the preview window that there is a little animation. These four sprites will make up
the Idle animation.

Drag mage_0 into your Animation window, at frame 0. mage_1 should be at frame 10, mage_2 at
frame 20, mage_3 at 30, and mage_4 at 40. You can test this by moving your Scene window
somewhere else in the Unity editor, and then hitting the play button in the Animation window. You
should see your MageUnit going through the animation you just created.

Now select the MagicalAttack animation. You will be using the mage sprites 7, 8, 9, and 10. Add
them at 0, 10, 20, and 30, in numerical order. For the PhysicalAttack animation, you will use 11,
12, and 13 at 0, 10, and 20. For the Hit animation, you will use 14, 15, and 15 again at 0, 10, and
20. Test out each of your animations now, if you want to change which sprites are used, feel free to
do so.

Animating the Snake Unit

Now you will be doing a similar process for the SnakeUnit. Create a new folder in
your Animations folder, and name it Snake. In this folder, add a new Animator Controller, and

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Animations

name it SnakeAnimator. Add an instance of the SnakeUnit prefab to your scene and drag
the SnakeAnimator to it. Now make the same 4 animations that you made for the
mage: Idle, Hit, PhysicalAttack, and MagicalAttack. The SnakeUnit will not have
a MagicalAttack, but it is important to follow the same structure. Make sure to remember to set
the Idle animation to Loop Time.

Open the Animator window, making sure that the SnakeUnit is selected, and add the 4 animations
to the window, starting with Idle so that it will be the default state. Add the transitions from the
other three animations to Idle.

Change to the Animation window and select the Idle animation in the drop down menu. Navigate
back to your Sprites/battle folder and open up the snake sprite sheet. You will get a pop up menu
when you add a sprite to the animation, with Sprite Renderer and Create Enemy Menu Items
(Script) as options. This is because you could change either of these images with the animations.
Select Sprite Renderer. Setup the animations using the following guidelines.

Idle: 0, 1, 2, 3, 4, and 5 at 0, 10, 20, 30, 40, and 50.


PhysicalAttack: 6, 7, 8, 9, and 10 at 0, 10, 20, 30, and 40.
Hit: 17, 18, and 18 again at 0, 10, and 20.

You will not be creating a MagicalAttack animation for the SnakeUnit right now, but if you want
the practice you can. If you find it hard to put the sprites at the correct times, you can select the
small diamonds to fine tune the placement. Make sure to check all the animations when you are
finished setting them up.

Now you will want to apply the changes you have made to the SnakeUnit prefab. For newer
versions of Unity, there is not an Apply button. There is an Overrides drop down menu. Select this
and choose apply.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Animations

If you are using a newer version of Unity, this is all you need to do. The SnakeEncounter prefab will
automatically update with the changes to the SnakeUnit prefab.

You can now delete the SnakeUnit from your scene. Test out your game. You should now see the
three units animated in your Battle scene, doing their Idle animation on a loop.

Making the Warrior Unit

To add some diversity to the game, you can now add another player unit. Duplicate
your MageUnit and rename it WarriorUnit. Move it to somewhere else on your scene. Go to
the Sprite Renderer in the Inspecter and change the Sprite field to warrior_0.

Go to your Animations folder and follow the same sequence as for the other two units. Make a new
folder in your Animations folder and name it warrior, make an Animator Controller in the folder
and name it WarriorAnimator, drag it to your WarriorUnit, and make the same 4
animations: Idle, Hit, PhysicalAttack, and MagicalAttack. As with the others, make sure that
the Loop Time checkbox is selected for Idle. Select the WarriorUnit, open the Animator window,
and drag all 4 animations into the window. Add the transitions from the other 3 animations to Idle,
and then open the Animation window. Create the animations according to the following guidelines:

Idle: 0, 1, 2, 3, 4, and 4 at 0, 10, 20, 30, 40, and 50.


PhysicalAttack: 6, 7, 8, 9, and 10 at 0, 10, 20, 30, and 40.
MagicalAttack: 12, 13, 14, 15, and 15 at 0, 10, 20, 30, and 40.
Hit: 16, 17, and 17 again at 0, 10, and 20.

Now test each of these different animations. Feel free to tweak these as desired.

You can now test out your game all the way through. When you get to your Battle scene, you should
see your new WarriorUnit playing the animation. If they are in the wrong positions, you can adjust
them while the game is running, and figure out what values will be good. Then, stop the game, and
move the MageUnit and WarriorUnit to these values. This kind of tweaking is necessary to make
sure everything is positioned nicely, so just keep testing and adjusting things until you like how
everything looks.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Turn system

In this lesson, you will learn how to create the turn based battle system.

For this game, you will be using a turn based system that places all in the units in the battle in a list,
ordered by their speed.

Go to your Battle scene, and create an empty GameObject. Name it TurnSystem. A keyboard
shortcut to rename objects is to use F2 for Windows and Enter for Mac. Create a new C# script, and
name it TurnSystem as well. Wait for it to finish compiling, and then drop this new script into
the TurnSystem object. Open this script up. You will be adding a number of variables first. See the
code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurnSystem : MonoBehaviour


{
[SerializeField]
private GameObject actionsMenu, enemyUnitsMenu;

private List<UnitStats> unitStats;


.
.
.

The two GameObject are the menus that this TurnSystem script will be responsible for activating
and deactivating. The List object is a type of array that will store the stats of the units in the battle,
to determine their order in the turn sequence.

Now you can add code to the Start method. See the code below:

void Start()
{
unitStats = new List<UnitStats>();

// Add player units to the list.


GameObject[] playerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
}

You need to go back to the Unity editor, go to your Title scene. As you have done in previous
lessons, create a new tag, name it PlayerUnit, and apply it to both the WarriorUnit and
the MageUnit. Also create an EnemyUnit tag. You will need to apply this EnemyUnit tag to an
instance of your SnakeUnit and then update the prefab. If you are using a newer version of
Unity, SnakeEncounter will update automatically. If not, you will need to update the tags of the 2
instances of the SnakeUnit.

Make sure to save the changes to your Title scene, and then go back to your Battle scene. Now you
will be adding some more code to the TurnSystem script. See the code below:

void Start()
{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Turn system

unitStats = new List<UnitStats>();

// Add player units to the list.


GameObject[] playerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
foreach(GameObject playerUnit in playerUnits) # New code
{
UnitStats currentUnitStats = playerUnit.GetComponent<UnitStats>();
currentUnitStats.CalculateNextActTurn(0);
unitStats.Add(currentUnitStats);
}
}

This code will iterate over each GameObject that was found with the PlayerUnit tag, and put their
stats into the currentUnitStats variable. The CalculateNextActTurn is a function that you will be
writing later, but needs to be included here so that this will work later on when you implement it. The
final part of this loop is to add the currentUnitStats to the unitStats list, so that it will be saved.

Now you can do the same thing for the enemy units. See the code below:

// Add enemy units to the list.


GameObject[] enemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit");
foreach (GameObject enemyUnit in enemyUnits)
{
UnitStats currentUnitStats = enemyUnit.GetComponent<UnitStats>();
currentUnitStats.CalculateNextActTurn(0);
unitStats.Add(currentUnitStats);
}

This is essentially the same code, just for the enemy units instead of the player ones. Now you can
add the last part of the code to the Start method. See the code below:

// Sort the list based on speeds.


unitStats.Sort();

actionsMenu.SetActive(false);
enemyUnitsMenu.SetActive(false);

NextTurn();

This will sort the unitStats list based on the speeds of the units that are stored in it, set both of the
game menus to be inactive, and will call the NextTurn function, which you will be implementing
later. NextTurn will be called whenever a new unit will attack. It will be what drives the turn
mechanics.

Delete the Update method, and then you can add the NextTurn method. See the code below:

public void NextTurn()


{
UnitStats currentUnitStats = unitStats[0];

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Turn system

unitStats.Remove(currentUnitStats);

if (!currentUnitStats.IsDead())
{
GameObject currentUnit = currentUnitStats.gameObject;

currentUnitStats.CalculateNextActTurn(currentUnitStats.nextActTurn);
unitStats.Add(currentUnitStats);
unitStats.Sort();

if(currentUnit.tag == "PlayerUnit")
{
Debug.Log("Player unit should act!");
}
else
{
Debug.Log("Enemy should act");
}
}
else
{
NextTurn();
}

This code will get the current unit from the unitStats list, check if it is dead, and then determine
which unit should act next based on this. It will also allow the unit to act, but the code to do that will
be added later. If the unit is dead, this code will call NextTurn again, as a dead unit won’t have any
actions. Many of the functions in this have not been written yet, but you will be doing that soon.

Now open up your UnitStats script. You will be adding the functions and variables necessary to
allow the TurnSystem script to work. Add these below the other variables you have in this script.
See the code below:

public int nextActTurn;

private bool dead = false;

public void CalculateNextActTurn (int currentTurn)


{
nextActTurn = currentTurn + Mathf.CeilToInt(100f / speed);
}

public bool IsDead()


{
return dead;
}

The nextActTurn variable will be what is used to determine which unit will be acting next.
The dead boolean is what will enable the game to recognize that a unit is
dead. CalculateNextActTurn will be taking in a value, and then adjusting it based on the unit’s
speed. The Mathf.CeilToInt will round up the results of the division as an int value. This division

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Turn system

operation will mean that units with higher speeds will have a smaller nextActTurn value, and will
therefore act sooner in battle. The IsDead function simply returns the value of the dead variable,
which will always be false for now.

To enable the unitStats list to sort items based on speed, it needs to be comparable. See the code
below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using System; # New code

public class UnitStats : MonoBehaviour, IComparable # New code


{
. # The rest of the code in the script
.
.
public int CompareTo(object otherStats)
{
return nextActTurn.CompareTo(((UnitStats)otherStats).nextActTurn);
}
}

This code will enable you to compare this object to another objects. It will convert the otherStats to
be a UnitStats object so that it can pull the nextActTurn variable from the otherStats object. This
allows the Sort function of the list to work properly.

Now save this script, and open this up in Unity to check for any compiler errors. If there are any, try
to figure out what went wrong and continue checking the console until there are no errors.

Go to your Battle scene and add the ActionMenu and EnemyUnitsMenu to


the TurnSystem script component of the TurnSystem object.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Turn system

Make sure to save the Battle scene, and then test your game out. You should get to
the Battle scene, and there should be no menus. In the Console, there should be a log that says
either “Player should act” or “Enemy should act” depending on the speed values you have given
your units.

Full code for the TurnSystem script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurnSystem : MonoBehaviour


{
[SerializeField]
private GameObject actionsMenu, enemyUnitsMenu;

private List<UnitStats> unitStats;

// Start is called before the first frame update


void Start()
{
unitStats = new List<UnitStats>();

// Add player units to the list.


GameObject[] playerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
foreach(GameObject playerUnit in playerUnits)
{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Turn system

UnitStats currentUnitStats = playerUnit.GetComponent<UnitStats>();


currentUnitStats.CalculateNextActTurn(0);
unitStats.Add(currentUnitStats);
}

// Add enemy units to the list.


GameObject[] enemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit");
foreach (GameObject enemyUnit in enemyUnits)
{
UnitStats currentUnitStats = enemyUnit.GetComponent<UnitStats>();
currentUnitStats.CalculateNextActTurn(0);
unitStats.Add(currentUnitStats);
}

// Sort the list based on speeds.


unitStats.Sort();

actionsMenu.SetActive(false);
enemyUnitsMenu.SetActive(false);

NextTurn();
}

public void NextTurn()


{
UnitStats currentUnitStats = unitStats[0];
unitStats.Remove(currentUnitStats);

if (!currentUnitStats.IsDead())
{
GameObject currentUnit = currentUnitStats.gameObject;

currentUnitStats.CalculateNextActTurn(currentUnitStats.nextActTurn);
unitStats.Add(currentUnitStats);
unitStats.Sort();

if(currentUnit.tag == "PlayerUnit")
{
Debug.Log("Player unit should act!");
}
else
{
Debug.Log("Enemy should act");
}
}
else
{
NextTurn();
}
}
}

Full code for the updated UnitStats script:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Turn system

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using System;

public class UnitStats : MonoBehaviour, IComparable


{
public float health;
public float mana;
public float attack;
public float magic;
public float defense;
public float speed;

public int nextActTurn;

private bool dead = false;

public void CalculateNextActTurn (int currentTurn)


{
nextActTurn = currentTurn + Mathf.CeilToInt(100f / speed);
}

public bool IsDead()


{
return dead;
}

public int CompareTo(object otherStats)


{
return nextActTurn.CompareTo(((UnitStats)otherStats).nextActTurn);
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Attack system

In this lesson you will learn how to implement the attack system.

Writing the AttackTarget Script

For this game, you will be making the attacks prefabs. This is so that it will be easier to adjust
attacks for different units.

Create a new C# script in your Scripts folder and call it AttackTarget. First you will need to add
some variables. See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AttackTarget : MonoBehaviour


{
public GameObject owner;

[SerializeField]
private string attackAnimation;

[SerializeField]
private bool magicAttack;

[SerializeField]
private float manaCost;

[SerializeField]
private float minAttackMultiplier;

[SerializeField]
private float maxAttackMultiplier;

[SerializeField]
private float minDefenseMultiplier;

[SerializeField]
private float maxDefenseMultiplier;
}

The owner variable will be used to determine which unit is doing the attack.
The attackAnimation string will be the name of the animation that will be triggered.
The magicAttack boolean will be used to determine whether or not this will be a magic attack.
The manacost float is used to determine how much mana an attack will drain from the mana bar
you made earlier. The Multiplier floats will be used for calculating combat outcomes.

You can delete the Start and Update methods and add a new method public method called Hit.
See the code below:

public void Hit(GameObject target)


{
UnitStats ownerStats = owner.GetComponent<UnitStats>();
UnitStats targetStats = target.GetComponent<UnitStats>();

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

if (ownerStats.mana >= manaCost)


{
float attackMultiplier = Random.Range(minAttackMultiplier, maxAttackMultiplie
r);
float damage = (magicAttack) ? (attackMultiplier * ownerStats.magic) : ( atta
ckMultiplier * ownerStats.attack);

float defenseMultiplier = Random.Range(minDefenseMultiplier, maxDefenseMultip


lier);
damage = Mathf.Max(0, damage - (defenseMultiplier * targetStats.defense));

owner.GetComponent<Animator>().Play(attackAnimation);

targetStats.ReceiveDamage(damage);

ownerStats.mana -= manaCost;
}
}

This code will get the UnitStats components of both the owner object and the target object. It will
also check the if the owner object has the required mana to do the attack, and if so, it will calculate
the attack value. This is done by getting a random value in between the min and max attack
multipler, using the Random.Range code.

To determine the attack’s possible damage, the script will use a ternary operator and
the magicAttack boolean. The ternary operator acts like an if/else statement, with the first
operation after the question mark being returned if the boolean is true, and the operation after the
colon being returned if the boolean is false.

Determining the damage done to the target is done next, with another Random.Range using the
min and max defense multipliers this time. What the Mathf.Max function does is return either 0 or
the value of the damage minus the target’s defense multiplied by the damage multiplier that was
just calculated, and then overwriting the damage value that had been calculated in the previous
step.

The script will then play the animation that the owner object has with the name attackAnimation.

The targetStats.ReceiveDamage will be a function that will inflict the calculated damage to the
target object, but you have not yet created this function.

Updating the UnitStats script

To code this new function, open the UnitStats script and follow the code below:

public void ReceiveDamage(float damage)


{
health -= damage;
animator.Play("Hit");

if(health <= 0)
{
dead = true;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

gameObject.tag = "DeadUnit";
Destroy(gameObject);
}
}

You will need to add a variable for the Animator of the unit this is attached to, so that
the ReceiveDamage function can play the Hit animation that you made. The function will also
reduce the health of the unit, and if the health is below 0, it will mean that the unit has died and
the dead boolean needs to be made true. The function will also add a tag to this object, DeadUnit,
and then destroy it.

Now go back to the Unity editor, select any element in your scene, and add the new tag DeadUnit.
You don’t need to add this to any elements, this is just for the script.

To add a text indicator for the damage, you need to add some new variables. See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; # New code

using System;

public class UnitStats : MonoBehaviour, IComparable


{
[SerializeField]
private Animator animator;

[SerializeField]
private GameObject damageTextPrefab; # New code

[SerializeField]
private Vector2 damageTextPosition; # New code
.
.
.
.
}

These variables and the new namespace will allow you to add text objects to the game to indicate
damage. This will be done in the ReceiveDamage function. See the code below:

public void ReceiveDamage(float damage)


{
health -= damage;
animator.Play("Hit");

GameObject HUDCanvas = GameObject.Find("HUDCanvas");


GameObject damageText = Instantiate(damageTextPrefab, HUDCanvas.transform);
damageText.GetComponent<Text>().text = "" + Mathf.FloorToInt(damage);
damageText.transform.localPosition = damageTextPosition;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

damageText.transform.localScale = Vector2.one;

if(health <= 0)
{
dead = true;
gameObject.tag = "DeadUnit";
Destroy(gameObject);
}
}

You will need a reference to the HUDCanvas to add the new text object as a child, which is what
the GameObject.Find is for. Now the script will instantiate a new text object using
the damageTextPrefab with the HUDCanvas as its parent. The Mathf.FloorToInt function allows
the damage parameter to be shown as an integer, and is converted to a string because of the empty
quotes. The two lines of code dealing with the damageText.transform will set the position and
scale of the text that was just created.

The AttackTarget script should now have everything it needs to function, but you will need to make
the damageTextPrefab before you can test this.

Making the DamageText Prefab

Now open up the Battle scene. In the HUDCanvas, add a new Text object and change its name
to DamageText. Increase its size using the Rect Tool, and then change the Text field to be 9,999.
Increase the font size to be 50, the style to be Bold, and change the color to whatever you think
looks best. Change the alignment to be the center for both options. Save the DamageText as a
prefab by dragging it into your Prefabs folder.

Updating the Units

Make sure to save the Battle scene, and then go to your Title scene and click on your MageUnit. In
the UnitStats field, there should be a place for an Animator. Drag the MageUnit to this. For
the Damage Text Prefab, drag the prefab you just made into this field. Set the Damage Text
Position to be 0 for X and 0 for Y.

Do the same thing for the WarriorUnit.

Now drag an instance of your SnakeUnit prefab into the scene and do the same thing as you did for
the other two units. Make sure to then apply this change to the prefab, by clicking on Overrides and
then Apply. For newer versions of Unity, this will automatically update the SnakeEncounter prefab
and you won’t need to manually do this.

Making the Attack Prefabs

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

Save your Title scene, and then go to the Battle scene. Create a new empty GameObject that is
not a child of anything, and name it MagicalAttack. Add the AttackTarget script to this, either by
using the Add Component button or dragging it from your Scripts folder. In the Attack
Animation field, write MagicalAttack, the same as the animations that you made. Mark the Magic
Attack checkbox and set some values for the Multiplier fields.

Now duplicate the MagicalAttack object and rename it PhysicalAttack. Change the Attack
Animation field so that it says PhysicalAttack, uncheck the Magic Attack checkbox, and change
the mana cost to 0. You can also change the Multipliers if you want to.

Go to your Prefabs folder, make a new folder in it called Attacks, and put both of these new attacks
into it. Also put the DamageText into the Attacks folder. You should also make a new folder
named UI and put the TargetEnemy into it. This will just keep your Assets tree more organized.
Now you can delete the MagicalAttack and PhysicalAttack objects.

In the next lesson, you will be writing the scripts to allow the player units and the enemy units to do
actions.

Full code for the AttackTarget script:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AttackTarget : MonoBehaviour


{
public GameObject owner;

[SerializeField]
private string attackAnimation;

[SerializeField]
private bool magicAttack;

[SerializeField]
private float manaCost;

[SerializeField]
private float minAttackMultiplier;

[SerializeField]
private float maxAttackMultiplier;

[SerializeField]
private float minDefenseMultiplier;

[SerializeField]
private float maxDefenseMultiplier;

public void Hit(GameObject target)


{
UnitStats ownerStats = owner.GetComponent<UnitStats>();
UnitStats targetStats = target.GetComponent<UnitStats>();

if (ownerStats.mana >= manaCost)


{
float attackMultiplier = Random.Range(minAttackMultiplier, maxAttackMulti
plier);
float damage = (magicAttack) ? (attackMultiplier * ownerStats.magic) : (
attackMultiplier * ownerStats.attack);

float defenseMultiplier = Random.Range(minDefenseMultiplier, maxDefenseMu


ltiplier);
damage = Mathf.Max(0, damage - (defenseMultiplier * targetStats.defense))
;

owner.GetComponent<Animator>().Play(attackAnimation);

targetStats.ReceiveDamage(damage);

ownerStats.mana -= manaCost;
}
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

Full code for the updated UnitStats script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

using System;

public class UnitStats : MonoBehaviour, IComparable


{
[SerializeField]
private Animator animator;

[SerializeField]
private GameObject damageTextPrefab;

[SerializeField]
private Vector2 damageTextPosition;

public float health;


public float mana;
public float attack;
public float magic;
public float defense;
public float speed;

public int nextActTurn;

private bool dead = false;

public void CalculateNextActTurn (int currentTurn)


{
nextActTurn = currentTurn + Mathf.CeilToInt(100f / speed);
}

public bool IsDead()


{
return dead;
}

public int CompareTo(object otherStats)


{
return nextActTurn.CompareTo(((UnitStats)otherStats).nextActTurn);
}

public void ReceiveDamage(float damage)


{
health -= damage;
animator.Play("Hit");

GameObject HUDCanvas = GameObject.Find("HUDCanvas");


GameObject damageText = Instantiate(damageTextPrefab, HUDCanvas.transform);
damageText.GetComponent<Text>().text = "" + Mathf.FloorToInt(damage);
damageText.transform.localPosition = damageTextPosition;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Attack system

damageText.transform.localScale = Vector2.one;

if(health <= 0)
{
dead = true;
gameObject.tag = "DeadUnit";
Destroy(gameObject);
}
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Implementing attacks

In this lesson you will learn how to implement the attack systems.

Setting up the Scripts

In you Scripts folder, make a new folder and name it Attacks. Put the AttackTarget script there,
and then make two new C# scripts. Name them EnemyUnitAction and PlayerUnitAction.

Writing the EnemyUnitAction Script

The first thing you will need to do is add some variables. See the code below:

[SerializeField]
private GameObject attackPrefab;

[SerializeField]
private string targetsTag;

private GameObject attack;

The attackPrefab variable will be used by the enemy unit to attack a player unit, using a prefab
that you have created. The targetsTag will be used to choose a target. As this is for enemy units,
the targets will always be player units. The attack GameObject will be used to hold an instance of
the chosen attack, to make the code more organized.

Now you can delete the Start and Update methods and add the Awake method. See the code
below:

void Awake()
{
attack = Instantiate(attackPrefab);
attack.GetComponent<AttackTarget>().owner = gameObject;
}

You will be using the Awake method because this code will be sort of a pre-loading instruction for
the script and will ensure that this happens before any other code. What this code does is create a
new instance of the attackPrefab, and makes the enemy unit the owner of the attack.

The next step is to add a function to get a random target. See the code below:

private GameObject FindRandomTarget()


{
GameObject[] possibleTargets = GameObject.FindGameObjectsWithTag(targetsTag);

if(possibleTargets.Length > 0)
{
return possibleTargets[Random.Range(0, possibleTargets.Length)];
}
else
{
return null;
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Implementing attacks

This code will create an array of GameObjects that have the targetsTag, and then determine if
there are multiple targets. If there are targets, the code will use the Random.Range function to
give a number between 0 and the number of targets, minus 1. This will then be used as an index for
the array, and the FindRandomTarget function will return that object. Remember that arrays in C#
are 0 based. If there are no possible targets, in other words if the array is empty, then null will be
returned.

You can now add another method, to do the actual action. See the code below:

public void Act()


{
GameObject target = FindRandomTarget();
attack.GetComponent<AttackTarget>().Hit(target);
}

This code uses the FindRandomTarget function you just made to get a target, and then uses
the AttackTarget script to damage that target.

Writing the PlayerUnitAction Script

This code will be fairly similar to the EnemyUnitAction, with some minor differences. First, the
variables. See the code below:

[SerializeField]
private GameObject physicalAttackPrefab;

[SerializeField]
private GameObject magicalAttackPrefab;

private GameObject currentAttack;


private GameObject physicalAttack;
private GameObject magicalAttack;

As the player units have two different kinds of attacks, you need to include both options.
The currentAttack, magicalAttack, and physicalAttack are used to help keep the instances of
different attacks clear.

Next, you can add the Awake method. Make sure to delete the Start and Update method. See the
code below:

void Awake()
{
physicalAttack = Instantiate(physicalAttackPrefab, transform);
magicalAttack = Instantiate(magicalAttackPrefab, transform);

physicalAttack.GetComponent<AttackTarget>().owner = gameObject;
magicalAttack.GetComponent<AttackTarget>().owner = gameObject;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Implementing attacks

currentAttack = physicalAttack;
}

Both the physicalAttack and magicalAttack need to be instantiated so that they are a new
instance of their respective prefabs. They are both also set to be child objects of the object calling
this script. They are also both set so that the object calling the script is the owner in
the AttackTarget script. For now, you should set currentAttack to be physicalAttack, but this is
just a placeholder.

You will now need to implement the Act function. See the code below:

public void Act(GameObject target)


{
currentAttack.GetComponent<AttackTarget>().Hit(target);
}

This version of the Act method will take in a GameObject as a parameter, because unlike the
enemy unit, the player unit will be targeting specific enemy units. The targeting system will be done
in a later lesson. This code will use the AttackTarget script in the currentAttack to call
the Hit function with the target object being hit.

Adding the New Scripts to Units

Open the Title scene and then select both your MageUnit and your WarriorUnit. Click on the Add
Component button in the Inspector, and add the PlayerUnitAction script to it. Select
the MageUnit and then go to your Prefabs folder and drag the corresponding prefabs to the fields
in the Player Unit Action (Script) section.

Make sure to do this for both the WarriorUnit as well.

Next is to do the same sequence for the snake. Either drag the SnakeUnit prefab into your scene, or
open the prefab editor. Add the EnemyUnitAction script to the prefab, and then add
the PhysicalAttack prefab to the Attack Prefab field. For the Targets Tag field, you will need to
write in PlayerUnit, as that is the tag both of your player units have. Make sure that this is spelled
correctly, otherwise the code will not work.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Implementing attacks

Now, make sure to apply the changes to the SnakeUnit if you changed it in the scene editor. If you
used the Prefab editor, you don’t need to do anything. If you are using a new version of Unity,
the SnakeEncounter prefab will automatically update with the changes. Make sure to delete
the SnakeUnit if you added it to your scene.

Updating the TurnSystem script

Open your TurnSystem script. Go to the NextTurn method. You will be adding in the new action
scripts you just made. See the code below:

public void NextTurn()


{
UnitStats currentUnitStats = unitStats[0];
unitStats.Remove(currentUnitStats);

if (!currentUnitStats.IsDead())
{
GameObject currentUnit = currentUnitStats.gameObject;

currentUnitStats.CalculateNextActTurn(currentUnitStats.nextActTurn);
unitStats.Add(currentUnitStats);
unitStats.Sort();

if(currentUnit.tag == "PlayerUnit")
{
Debug.Log("Player unit should act!");
}
else
{
currentUnit.GetComponent<EnemyUnitAction>().Act(); # New code
}
}
else
{
NextTurn();
}
}

Instead of writing out a console message, your enemy unit will now attack one of your player units.
Feel free to test to game out now. You should see one of the SnakeUnit’s attacking one of the
players. The SnakeUnit should use the attack animation, and the player should use
the Hit animation. There should also be the DamageText on the screen. Unfortunately, it will stay
there permanently, so you need to update how it functions. See the code below:

public void ReceiveDamage(float damage)

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Implementing attacks

{
health -= damage;
animator.Play("Hit");

GameObject HUDCanvas = GameObject.Find("HUDCanvas");


GameObject damageText = Instantiate(damageTextPrefab, HUDCanvas.transform);
damageText.GetComponent<Text>().text = "" + Mathf.FloorToInt(damage);
damageText.transform.localPosition = damageTextPosition;
damageText.transform.localScale = Vector2.one;
Destroy(damageText.gameObject, 1f); # New code

if(health <= 0)
{
dead = true;
gameObject.tag = "DeadUnit";
Destroy(gameObject);
}
}

This added line of code makes it so that the DamageText object will be destroyed after 1 second. If
you want more or less time, simply change the number.

Don’t worry if the animation timing is off, that will be fixed in later lessons.

Full code for PlayerUnitAction:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerUnitAction : MonoBehaviour


{
[SerializeField]
private GameObject physicalAttackPrefab;

[SerializeField]
private GameObject magicalAttackPrefab;

private GameObject currentAttack;


private GameObject physicalAttack;
private GameObject magicalAttack;

void Awake()
{
physicalAttack = Instantiate(physicalAttackPrefab, transform);
magicalAttack = Instantiate(magicalAttackPrefab, transform);

physicalAttack.GetComponent<AttackTarget>().owner = gameObject;
magicalAttack.GetComponent<AttackTarget>().owner = gameObject;

currentAttack = physicalAttack;
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Implementing attacks

public void Act(GameObject target)


{
currentAttack.GetComponent<AttackTarget>().Hit(target);
}
}

Full code for EnemyUnitAction:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyUnitAction : MonoBehaviour


{
[SerializeField]
private GameObject attackPrefab;

[SerializeField]
private string targetsTag;

private GameObject attack;

void Awake()
{
attack = Instantiate(attackPrefab);
attack.GetComponent<AttackTarget>().owner = gameObject;
}

private GameObject FindRandomTarget()


{
GameObject[] possibleTargets = GameObject.FindGameObjectsWithTag(targetsTag);

if(possibleTargets.Length > 0)
{
return possibleTargets[Random.Range(0, possibleTargets.Length)];
}
else
{
return null;
}
}

public void Act()


{
GameObject target = FindRandomTarget();
attack.GetComponent<AttackTarget>().Hit(target);
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Controlling players

In this lesson you will learn how to select units and perform actions with them.

Writing the SelectUnit Script

Open the Scripts folder, and then make a new C# script and name it SelectUnit. Go to
your Title scene, select the PlayerParty, and add the new script to it. Open this script. You will
need to add the SceneManagement namespace and some variables. See the code below:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; # Add this

public class SelectUnit : MonoBehaviour


{
private GameObject currentUnit;
private GameObject actionsMenu;
private GameObject enemyUnitsMenu;
.
.
.
}

The currentUnit variable will be used to hold the active unit’s object for use in the script. The two
menus will be used to interact with the game menus.

Now you can delete the Start and Update method and add the Awake method. This code will be a
scene check as you have done before. See the code below:

void Awake()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)


{
if(scene.name == "Battle")
{
actionsMenu = GameObject.Find("ActionsMenu");
enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");
}
}

This code will check if the current scene is the Battle scene, and if it is, the two menu variables will
be set to the menu objects in the game.

Now you can add some code to set the current unit. See the code below:

public void SelectCurrentUnit(GameObject unit)


{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Controlling players

currentUnit = unit;
actionsMenu.SetActive(true);
}

This code will take in a GameObject as a parameter and set the currentUnit variable to that
GameObject. It will then activate the ActionsMenu.

Next, you need to add code to select the type of attack used. See the code below:

public void SelectAttack (bool physical)


{
currentUnit.GetComponent<PlayerUnitAction>().SelectAttack(physical);
}

The SelectAttack function for PlayerUnitAction has not been implemented yet, but you will be
doing that now. See the code:

public void SelectAttack(bool physical)


{
currentAttack = physical ? physicalAttack : magicalAttack;
}

This code uses a simple ternary operation to set the currentAttack to be either
the physicalAttack or the magicalAttack based on the boolean that is passed in as a parameter.

You can now finish the SelectAttack function in the SelectUnit script. See below:

public void SelectAttack (bool physical)


{
currentUnit.GetComponent<PlayerUnitAction>().SelectAttack(physical);
actionsMenu.SetActive(false);
enemyUnitsMenu.SetActive(true);
}

This will deactivate the ActionMenu, as an action has been chosen, and active
the EnemyUnitsMenu to allow the player to choose a target. You can now write the code to initiate
the attack. See the code below:

public void AttackEnemyTarget (GameObject target)


{
actionsMenu.SetActive(false);
enemyUnitsMenu.SetActive(false);

currentUnit.GetComponent<PlayerUnitAction>().Act(target);
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Controlling players

This code will take in a GameObject that will be the target. It will deactivate both of the menus, and
then will use the Act method you wrote earlier to perform the chosen attack on the chosen target.

The final step is to update the TurnSystem to enable player actions. See the code below:

public void NextTurn()


{
UnitStats currentUnitStats = unitStats[0];
unitStats.Remove(currentUnitStats);

if (!currentUnitStats.IsDead())
{
GameObject currentUnit = currentUnitStats.gameObject;

currentUnitStats.CalculateNextActTurn(currentUnitStats.nextActTurn);
unitStats.Add(currentUnitStats);
unitStats.Sort();

if(currentUnit.tag == "PlayerUnit") # New code


{
GameObject.Find("PlayerParty").GetComponent<SelectUnit>().SelectCurrentUn
it(currentUnit.gameObject);
}
else
{
currentUnit.GetComponent<EnemyUnitAction>().Act();
}
}
else
{
NextTurn();
}
}

This line of code will find the PlayerParty object, get its SelectUnit component, and activate
the SelectCurrentUnit function that you just wrote.

Selecting Attacks

Now you need to add the ability to select attacks to your game. Go to your Battle scene. Make a
new C# script in your Scripts folder, and name it AddButtonCallback. Open this code. You will
need to add a namespace and one variable. See the code below:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AddButtonCallBack : MonoBehaviour


{
[SerializeField]
private bool physical;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Controlling players

.
.
.
}

This will be the boolean that you will be passing to SelectAttack. Now you can add code to
the Start method. See the code below:

void Start()
{
gameObject.GetComponent<Button>().onClick.AddListener(() => AddCallback());
}

This will enable the Button to call the function AddCallback whenever the button is clicked. You
need to write this function, so delete the Update method and see the code below:

private void AddCallback()


{
GameObject playerParty = GameObject.Find("PlayerParty");
playerParty.GetComponent<SelectUnit>().SelectAttack(physical);
}

This code finds the GameObject that has the name PlayerParty, and then gets
the SelectUnit component you just made. It then calls the SelectAttack function using the
boolean physical.

You can now add this script to your button. Select the PhysicalAttackAction, which is under
the ActionsMenu under the HUDCanvas. Add the AddButtonCallback script to this. You will then
see a checkbox in the component named Physical. Select it.

Add the script to the MagicalAttackAction as well, but do not select the checkbox for this one.

Selecting Target Enemies

To enable the player to select enemy targets, you need to update


the CreateEnemyMenuItems script. You will need to add some code to
the SelectEnemyTarget function that you created in an earlier lesson. See the code below:

public void SelectEnemyTarget()


{
GameObject partyData = GameObject.Find("PlayerParty");
partyData.GetComponent<SelectUnit>().AttackEnemyTarget(gameObject);
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Controlling players

This code will find the PlayerParty object, and then will get the SelectUnit component. It will then
call the AttackEnemyTarget function, and pass the GameObject that this function is called from.
This means that when you click on an enemy unit, you will active the onClick method, which will call
the SelectEnemyTarget function, resulting in the current player unit attacking enemy unit.

Full SelectUnit script:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SelectUnit : MonoBehaviour


{
private GameObject currentUnit;
private GameObject actionsMenu;
private GameObject enemyUnitsMenu;

void Awake()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)


{
if(scene.name == "Battle")
{
actionsMenu = GameObject.Find("ActionsMenu");
enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");
}
}

public void SelectCurrentUnit(GameObject unit)


{
currentUnit = unit;
actionsMenu.SetActive(true);
}

public void SelectAttack (bool physical)


{
currentUnit.GetComponent<PlayerUnitAction>().SelectAttack(physical);
actionsMenu.SetActive(false);
enemyUnitsMenu.SetActive(true);
}

public void AttackEnemyTarget (GameObject target)


{
actionsMenu.SetActive(false);
enemyUnitsMenu.SetActive(false);

currentUnit.GetComponent<PlayerUnitAction>().Act(target);
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Controlling players

Full AddButtonCallback script:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AddButtonCallBack : MonoBehaviour


{
[SerializeField]
private bool physical;

// Start is called before the first frame update


void Start()
{
gameObject.GetComponent<Button>().onClick.AddListener(() => AddCallback());
}

private void AddCallback()


{
GameObject playerParty = GameObject.Find("PlayerParty");
playerParty.GetComponent<SelectUnit>().SelectAttack(physical);
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Updating UI stats

In this lesson you will learn how to update the HUD elements during battles.

Writing the ShowUnitStat Script

In you Scripts folder, make a new folder and name it UI. Open the UI folder and make a
new C# script and name it ShowUnitStat. Wait for it to compile and then open it. You will need to
add some variables to begin with. See the code below:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ShowUnitStat : MonoBehaviour


{
[SerializeField]
protected GameObject unit;

[SerializeField]
private float maxValue;

private Vector2 initialScale;


.
.
.
}

Note the abstract keyword added to the class declaration. This is necessary because you will be
extending this class later on. The unit variable is protected instead of private, again related to what
you will be doing later on. The maxValue variable will be used to keep track of the maximums for
the health and mana values. The initialScale variable will store what size the health and mana bars
are to begin with, so that they can be reduced properly.

Now you can add code to the Start method. See the code below:

void Start()
{
initialScale = gameObject.transform.localScale;
}

The code in the Start method will simply set the initialScale value to the scale value of
the GameObject that this script is attached to. You need to use localScale to make sure that it will
be correctly scaled.

Next comes the Update method. See the code below:

void Update()
{
if (unit != null)
{
float newValue = NewStatValue();

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Updating UI stats

float newScale = (initialScale.x * newValue) / maxValue;


gameObject.transform.localScale = new Vector2(newScale, initialScale.y);
}
}

This code will check whether the unit variable is null. If it is not, then it will get a newValue using
the NewStatValue function, which you will be adding later. It will then use this newValue to get
a newScale using a simple math operation with the initialScale and the maxValue. Then the scale
of the gameObject is updated using the newScale value for X and the initialScale.y value for Y.

The next step is to add a function to change what object the unit variable is. See the code below:

public void ChangeUnit(GameObject newUnit)


{
unit = newUnit;
}

This is relatively straightforward, this function simply takes in a GameObject as a parameter and
sets the unit variable to that GameObject.

You can now add the NewStatValue function that you used earlier. See the code below:

abstract protected float NewStatValue();

You won’t actually be putting anything for this function in this script. This is because this function will
be implemented in other scripts. Save this script and go back to the Unity Editor.

Specific Stat Scripts

The next step for updating the HUD is to create two more scripts in the UI folder. One will
be ShowUnitHealth and the other will be ShowUnitMana. Both of these scripts will be extending
the more general ShowUnitStat script. Open them both. As both of them are
extending ShowUnitStat, you need to replace Monobehavior with ShowUnitStat, See the code
below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShowUnitHealth : ShowUnitStat # New code


{
.
.
.
}

In the ShowUnitHealth script, delete the Start and Update method. You will be overriding

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Updating UI stats

the NewStatValue function. As a shortcut, simply type override, hit space, and
select NewStatValue. See the code below:

protected override float NewStatValue()


{
return unit.GetComponent<UnitStats>().health;
}

This function will simply return the health value in the UnitStats component of the unit object. The
function for ShowUnitMana will be almost identical, except that you use mana instead of health.

Now you can add these scripts to their respective bars. Go to your Battle scene and select
the PlayerUnitHealthBar. Add the ShowUnitHealth script to this. Set the maxValue field to 100.
Then go to the PlayerUnitManaBar and add the ShowUnitMana script to it. Set
the maxValue field to 100 for this as well.

Updating Previous Scripts

To make everything work together, you need to update some of your older scripts.

First, open your SelectUnit script. In the SelectCurrentUnit method, you need to add a line. See
the code below:

public void SelectCurrentUnit(GameObject unit)


{
currentUnit = unit;
actionsMenu.SetActive(true);

currentUnit.GetComponent<PlayerUnitAction>().UpdateHUD(); # New code


}

This line will get the PlayerUnitAction component of the currentUnit object, and then call
the UpdateHUD method. You have not yet written this method, so that is the next step.

Open the PlayerUnitAction script. First, you will need to add a new variable and a new namespace.
See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; # New code

public class PlayerUnitAction : MonoBehaviour


{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Updating UI stats

[SerializeField]
private GameObject physicalAttackPrefab;

[SerializeField]
private GameObject magicalAttackPrefab;

[SerializeField]
private Sprite faceSprite; # New code
}

This will be used to change the sprite that is displayed in your HUD. Now you can add
the UpdateHUD function. See the code below:

public void UpdateHUD()


{
GameObject playerUnitFace = GameObject.Find("PlayerUnitFace");
playerUnitFace.GetComponent<Image>().sprite = faceSprite;

GameObject playerUnitHealthBar = GameObject.Find("PlayerUnitHealthBar");


playerUnitHealthBar.GetComponent<ShowUnitHealth>().ChangeUnit(gameObject);

GameObject playerUnitManaBar = GameObject.Find("PlayerUnitManaBar");


playerUnitManaBar.GetComponent<ShowUnitMana>().ChangeUnit(gameObject);
}

This function will change the PlayerUnitFace object to be the faceSprite that will be added to this
script. It will also find the health and mana bar objects and use
the ShowUnitStat function changeUnit to set the unit object to be the current player unit.

Make sure to save all of your scripts before going back to the Unity editor.

Updating the PlayerParty

Go to your Title scene, making sure to save the Battle scene before changing. Select
the MageUnit and go to the Player Unit Action (Script) component in the Inspector. You should
see a new field that says Face Sprite. In this field, add the mage_face sprite.

Do the same for the WarriorUnit. It will use warrior_face. Make sure to save your scene after
these changes.

In the next lesson you will be implementing the logic to finish the battle.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Updating UI stats

Full code for the ShowUnitStat script:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ShowUnitStat : MonoBehaviour


{
[SerializeField]
protected GameObject unit;

[SerializeField]
private float maxValue;

private Vector2 initialScale;

// Start is called before the first frame update


void Start()
{
initialScale = gameObject.transform.localScale;
}

// Update is called once per frame


void Update()
{
if (unit != null)
{
float newValue = NewStatValue();
float newScale = (initialScale.x * newValue) / maxValue;
gameObject.transform.localScale = new Vector2(newScale, initialScale.y);
}
}

public void ChangeUnit(GameObject newUnit)


{
unit = newUnit;
}

abstract protected float NewStatValue();


}

Full code for the ShowUnitHealth script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShowUnitHealth : ShowUnitStat


{
protected override float NewStatValue()
{
return unit.GetComponent<UnitStats>().health;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Updating UI stats

}
}

Full code for the ShowUnitMana script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShowUnitMana : ShowUnitStat


{
protected override float NewStatValue()
{
return unit.GetComponent<UnitStats>().mana;
}
}

Full code for the updated PlayerUnitAction script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PlayerUnitAction : MonoBehaviour


{
[SerializeField]
private GameObject physicalAttackPrefab;

[SerializeField]
private GameObject magicalAttackPrefab;

[SerializeField]
private Sprite faceSprite;

private GameObject currentAttack;


private GameObject physicalAttack;
private GameObject magicalAttack;

void Awake()
{
physicalAttack = Instantiate(physicalAttackPrefab, transform);
magicalAttack = Instantiate(magicalAttackPrefab, transform);

physicalAttack.GetComponent<AttackTarget>().owner = gameObject;
magicalAttack.GetComponent<AttackTarget>().owner = gameObject;

currentAttack = physicalAttack;
}

public void Act(GameObject target)

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Updating UI stats

{
currentAttack.GetComponent<AttackTarget>().Hit(target);
}

public void SelectAttack(bool physical)


{
currentAttack = physical ? physicalAttack : magicalAttack;
}

public void UpdateHUD()


{
GameObject playerUnitFace = GameObject.Find("PlayerUnitFace");
playerUnitFace.GetComponent<Image>().sprite = faceSprite;

GameObject playerUnitHealthBar = GameObject.Find("PlayerUnitHealthBar");


playerUnitHealthBar.GetComponent<ShowUnitHealth>().ChangeUnit(gameObject);

GameObject playerUnitManaBar = GameObject.Find("PlayerUnitManaBar");


playerUnitManaBar.GetComponent<ShowUnitMana>().ChangeUnit(gameObject);
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Finishing the battle

In this lesson you will learn how to finish the battle.

The battle can end from one of three options. Either all the enemy units are dead and the player
wins, or all the player units are dead and the enemy wins, or the player runs from the battle.

Writing the CollectReward Script

For this option, you will need to make a script to collect a reward for winning the battle. Open
your Scripts folder and make a new C# script. Name it CollectReward. Open this script. You will
need to add a variable. See the code below:

[SerializeField]
private float experience;

This variable will be used to keep track of the experience the player gets from winning the battle.
Next is to add code to the Start method. See the code below:

void Start()
{
GameObject turnSystem = GameObject.Find("TurnSystem");
turnSystem.GetComponent<TurnSystem>().enemyEncounter = gameObject;
}

This code will assign your TurnSystem object to the turnSystem variable, and then set
the enemyEncounter variable in its TurnSystem component to be the current object. As
the TurnSystem script does not have an enemyEncounter variable, you will need to add one. See
the code below:

public class TurnSystem : MonoBehaviour


{
[SerializeField]
private GameObject actionsMenu, enemyUnitsMenu;

public GameObject enemyEncounter; # New code

private List<UnitStats> unitStats;


}

This is a GameObject to store which enemyEncounter the player is fighting against.

Now you can go back to the CollectReward script, and then delete the Update method. You will
then need to create a new method called GetReward. See the code below:

public void GetReward()


{
GameObject[] livingPlayerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
float experiencePerUnit = experience / livingPlayerUnits.Length;

foreach(GameObject playerUnit in livingPlayerUnits)

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Finishing the battle

{
playerUnit.GetComponent<UnitStats>().ReceiveExperience(experiencePerUnit);
}

Destroy(gameObject);
}

The GameObject array livingPlayerUnits will be filled with all of the remaining objects with the
tag PlayerUnit. If either of your units died, they will be destroyed and so would not be found. As the
amount of experience that each player unit receives from the battle is determined by the number of
remaining units, the experiencePerUnit variable will be the total experience divided by the length
of the livingPlayerUnits array. The foreach loop will then get each playerUnit in the array, get
its UnitStats component, and then call the ReceiveExperience function with
the experiencePerUnit variable that was just calculated as a parameter. The final step is to destroy
the gameObject that has called this script.

As the ReceiveExperience method has not yet been created, you need to do that now. Open
your UnitStats script. You will need to add a variable for the experience. See the code below:

public float health;


public float mana;
public float attack;
public float magic;
public float defense;
public float speed;
public float experience; # New code

Now you can add the ReceiveExperience function. See the code below:

public void ReceiveExperience(float newExperience)


{
experience += newExperience;
}

This code simply takes in a float parameter and adds it to the experience variable you just made.
You can use this later on to implement a leveling system for each player unit, but this course will not
be covering that.

Updating the TurnSystem Script

Now that you have the CollectReward script finished, you need to update the TurnSystem script
to check whether the player has won or lost. See the code below:

public void NextTurn()


{
// Check if we beat all enemies
GameObject[] remainingEnemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit")
;
if(remainingEnemyUnits.Length == 0)

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Finishing the battle

{
enemyEncounter.GetComponent<CollectReward>().GetReward();
SceneManager.LoadScene("Town");
}
}

This added code will make an array with all of the remaining enemy units. Remember that when a
unit is killed, their tag is changed to DeadUnit, so they would not be added to the array. Then a
check for the length is performed, and if it is 0, the CollectReward component of
the enemyEncounter can be used to call the GetReward function. Then, your player will go back
to the Town scene. You will need to add the SceneManagement namespace to enable this to work.
See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; # New code

public class TurnSystem : MonoBehaviour


{
# Body of script
}

There is also the chance that the player has lost. This will be a similar check to the one that was just
made. See the code below:

// Check if game over


GameObject[] remainingPlayerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
if (remainingPlayerUnits.Length == 0)
{
SceneManager.LoadScene("Title");
}

This code similarly makes an array of the remaining player units and checks the length of that array.
If it is zero, or in other words if there are no player units remaining, then the game will load
the Title scene. You could have this go to a dedicated game over scene if you would prefer, but this
course will not be covering that.

Writing the RunFromBattle Script

The final option for finishing the battle is to run away. To do this, you need to create a new C# script
in your Scripts folder, and name it RunFromBattle. Open this script. You will be adding a
namespace, a variable, and can delete the Start and Update methods. See the code below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Finishing the battle

public class RunFromBattle : MonoBehaviour


{
[SerializeField]
private float runningChance = 0.5f;
}

This variable will be used to determine whether or not the run attempt is successful. If it is not, then
the player unit loses their turn and can be hit.

Add a new method called TryRunning. See the code below:

public void TryRunning()


{
float randomNumber = Random.value;
if (randomNumber < runningChance)
{
SceneManager.LoadScene("Town");
}
else
{
GameObject.Find("TurnSystem").GetComponent<TurnSystem>().NextTurn();
}
}

This code will generate a random number between 0 and 1, and then check if that number is less
than the runningChance variable. If it is, then the run attempt is successful, and the game will load
the Town scene. If not, then the TurnSystem object will be found and its TurnSystem component
will be used to call the NextTurn method, ending the turn of the current unit.

In the next lesson, you will be putting everything together to finalize your game.

Full code for the CollectReward script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CollectReward : MonoBehaviour


{
[SerializeField]
private float experience;

// Start is called before the first frame update


void Start()
{
GameObject turnSystem = GameObject.Find("TurnSystem");
turnSystem.GetComponent<TurnSystem>().enemyEncounter = gameObject;
}

public void GetReward()


{

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Finishing the battle

GameObject[] livingPlayerUnits = GameObject.FindGameObjectsWithTag("PlayerUni


t");
float experiencePerUnit = experience / livingPlayerUnits.Length;

foreach(GameObject playerUnit in livingPlayerUnits)


{
playerUnit.GetComponent<UnitStats>().ReceiveExperience(experiencePerUnit)
;
}

Destroy(gameObject);
}
}

Full code for the RunFromBattle script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class RunFromBattle : MonoBehaviour


{
[SerializeField]
private float runningChance = 0.5f;

public void TryRunning()


{
float randomNumber = Random.value;
if (randomNumber < runningChance)
{
SceneManager.LoadScene("Town");
}
else
{
GameObject.Find("TurnSystem").GetComponent<TurnSystem>().NextTurn();
}
}
}

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)


RPG Game Development With Unity
Collecting the rewards

In this lesson you will be finishing your game.

Activating the NextTurn function

If you test your game now, you should get the snake attacking one of your player units, with the
damage text showing up and the Hit animation playing. However, you still cannot activate any of the
actions that you have coded in previous lessons.

This is because NextTurn is not being called properly. To fix this, you need to add some code to
the UnitStats script, in the ReceiveDamage function. See the code below:

public void ReceiveDamage(float damage)


{
health -= damage;
animator.Play("Hit");

GameObject HUDCanvas = GameObject.Find("HUDCanvas");


GameObject damageText = Instantiate(damageTextPrefab, HUDCanvas.transform);
damageText.GetComponent<Text>().text = "" + Mathf.FloorToInt(damage);
damageText.transform.localPosition = damageTextPosition;
damageText.transform.localScale = Vector2.one;
Destroy(damageText.gameObject, 1f);

if(health <= 0)
{
dead = true;
gameObject.tag = "DeadUnit";
Destroy(gameObject);
}

GameObject.Find("TurnSystem").GetComponent<TurnSystem>().WaitThenNextTurn(); #
New code
}

This line will find the TurnSystem object, get its TurnSystem component, and then call
the WaitThenNextTurn function. You have not written this function yet, so that is the next step.
Open up your TurnSystem script, and see the code below:

public void WaitThenNextTurn()


{
StartCoroutine(WaitThenNextTurnRoutine());
}

private IEnumerator WaitThenNextTurnRoutine()


{
yield return new WaitForSeconds(1.0f);
NextTurn();
}

This code will call a coroutine, which will allow the game to wait before executing the next step.
The IEnumerator WaitNextTurnRoutine is where you can put in how long to wait for as well as

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Collecting the rewards

the call for NextTurn function.

Make sure to save the updated scripts, and then go back to Unity and wait for the compilation to be
done. You can now test the game. Press the play button for your game. You should get to
the Battle scene and see the ActionMenu buttons on your screen. Play through the battle until
the SnakeUnits are dead. You will be stuck in the Battle scene, because there is a few more things
you need to do to finish this.

Implementing the Run Action

Go to the Battle scene. Select the RunAction object and add the RunFromBattle script to it. Then
in the Button (Script) component of the RunAction object, click on the plus button under On Click
().

Then under the Runtime Only field, you will see a place to add an object. Drag
the RunAction object here.

Then callback will then be under the RunFromBattle option in the dropdown list, and
then TryRunning().

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Collecting the rewards

Go ahead and test out this new action in your game. You may have to attempt running more than
once, as the RunChance is 50%. You should go back to your Town scene, and then you can go back
into the Battle.

Fixing the TurnSystem Script

If you kill both of the SnakeUnits, you will encounter an error, saying this, with a different time
stamp:

You can double click on this error, and it should open your editor to the line in TurnSystem that is
causing the issue. This is the code:

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com


RPG Game Development With Unity
Collecting the rewards

public void NextTurn()


{
// Check if we beat all enemies
GameObject[] remainingEnemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit")
;
if(remainingEnemyUnits.Length == 0)
{
enemyEncounter.GetComponent<CollectReward>().GetReward(); # This line
SceneManager.LoadScene("Town");
}
}

The problem here is that the CollectReward script has not yet been assigned to
the SnakeEncounter prefab. So, go to your Prefabs folder and then the EnemyEncounters folder,
and add the CollectReward script to your SnakeEncounter. Give it a value for
the Experience field, 100 is a good default choice.

Now save your scene and test it out again. Everything should work out, and you should be able to kill
the SnakeEncounter repeatedly. You will be able to gain Experience, as your PlayerParty is
never destroyed.

You could use this to create a leveling system and really expand upon this game.

This is the end of this course. Congratulations on finishing it, you now have a strong base to build
this game into something great.

© 2019 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com

Powered by TCPDF (www.tcpdf.org)

You might also like