Create a Role-playing Game Level

In this tutorial, you will use a Role-playing Game (RPG) system to create a basic role-playing game with enemies and quests.

Download the starting template for the project here: RPG Template

RPG Game Structure

Explanation of parts of an RPG

Role-playing games are some of the more complicated types of game that you can make. This is because role-playing games need to store lots of information about the world and the characters.

If you've played a role-playing game in the past, such as Skyrim, Pokemon, or Minecraft, think about all the different variables that are required for the characters in the game. Each character has health, attack, defense, a level, abilities, and countless other variables that need to be tracked inside the game.

After you've determined all the stats you need to track, then you need to think about all the different systems that you create inside of an RPG. Here's a short list of some of the different types of systems that RPGs commonly have.

System Description
Combat System The way that the player attacks enemies, and enemies attack the player character. Can involve melee attacks, range attacks, or magic spells that apply effects on enemies.
Level-Up System As the player defeats enemies, they gain experience points. Once they gain enough experience points, their character will grow a level and become more powerful. This could give the player more Health points, or more attack power, or unlock special abilities.
Ability System As players level up, they can unlock special abilities that can benefit their character inside and outside of combat.
Quest System A way to tell the player what they should do next in the RPG. Usually players receive a reward from completing the quest, either experience points or items.
Inventory System Players can collect items to use in combat, or to deliver as part of quests.
Equipment System Items that the players collect can be used to boost their stats.
Crafting System Items that players collect from the world can be combined into other items.
Dialogue System Players can talk to other characters in the game to gain quests, to buy or sell items, or just to learn about the overall world.

Creating an RPG can be daunting, but in this lesson we're going to make a very simple RPG by using the Combat, Level-Up, and Quest systems.

Scriptable Objects and Events

In the previous lessons, most of our variables were stored inside of scripts which were attached to objects inside of the scene. Because RPGs are more complicated than other types of games, the way that data will be managed inside of the game will be a little different.

Most of the variables for the game will be part of scripts that are called Scriptable Objects. Normally, you attach a script to an object inside of a specific scene. However, these scripts exist ONLY at the project level, and do not exist inside of a scene. This can be really helpful in an RPG, when you want to manage the player's stats globally, since lots of systems need to know about those variables.

In addition, because there are multiple systems that need to communicate with each other, you will be using a specific Event System to allow the different systems to communicate with each other. In the previous lessons, when you wanted one system to talk to another, such as the player's health and the UI, you would link up the player and the UI. By using the event system, it makes the system easier to add code to.

Create the World

Once you have downloaded and opened the template project, open the StarterScene scene inside the Scenes folder.

This scene is a very basic scene, but it does have a basic terrain. You'll see that there is a border around the terrain to prevent the player from leaving the edge of the world, and a small ramp up to a plateau. Once the basic setup of the level is done, you can update the terrain of the world. For now, leave it as it is as you learn how to add the different parts of the RPG to the scene, or later you can add in a terrain for a world that you've already made.

First, delete the MainCamera object from the scene, and find the PlayerController prefab inside of Prefabs > Player and add it to the scene and walk around the level using wasd. You can press the left mouse button to swing your sword, and press the shift key to sprint.

You can find enemies inside of the Prefabs > Enemies folder. There are three variants of enemies currently. Drag the Monster prefab to the scene and take a look at the object.

There are two colliders on the enemy object. One of them is a sphere collider which is marked as a trigger, and the other is a box collider. The sphere collider indicates the view range of the enemy. Once the player steps inside that range, the enemy will move towards the player. The box collider determines whether or not the player hits the enemy.

Right now, the enemy doesn't perform any animation when it hits the player, but just hits the player back and removes some of their health.

Take a look at the MonsterBehavior script attached to the Monster GameObject, and double-click the variable in the Monster Type field. This will take you to the Scriptable Object that is used to store the monster's basic stats.

In the past, if you wanted to update a variable on a prefab that was already inside of a scene, it might take a bit of work. With a Scriptable Object, you can update the variables for the monster inside of this inspector view and it will automatically update for all the monsters across the entire game who use this Scriptable Object.

Try to change the monster's move speed inside of the inspector and play again, and see that the monster now moves faster towards the player.

Add UI

It would be good for the player to know that they are gaining EXP from defeating enemies, and to know how much health they have left. This will be handled on the UI.

Go to Prefabs > UI and add the UICanvas Prefab to the scene.

You don't need to perform any additional setups or hook up any parts of the scene to the object. Why? Scriptable Objects! Because all the variables are stored at the Project level instead of the Scene level, the UI just works when you add it to the scene. This is one of the many benefits of using Scriptable Objects.

Defeat some enemies and you'll see that you gain EXP for each one you defeat, and a notification will appear telling you that you defeated an enemy.

This is one of the big advantages of using Scriptable Objects, rather than storing stats on the scene. You don't need to spend any time hooking up scripts when you set up the different systems on a scene, and you can add or remove systems like UI without having an impact on the other systems, like the combat system.

If you tried to create this UI without Scriptable Objects, you would need to have the Player script updating the UI, or have the UI script watching the player script. Right now, neither of these scripts need to know the other exists in order to function in the scene.

Add a Location Quest

Now you can defeat enemies and level up. But the player doesn't have a sense of direction without a location to travel to and a quest.

Go to Prefabs > Systems and add the Location_Name prefab to the scene, renaming it Arena.

This uses the Location script, which already has one event variable that is filled, and another one which is empty. Before doing anything else, play the game and walk inside the circle. The UI will show a notification saying that you walked inside the location.

Next, add the QuestManager Prefab to the scene. Inside the QuestManager script, update the Quest List variable to a size of 1. Then, inside of Variables > Quests, drag the GoToArena quest into the blank field.

When you start the game again, you'll see that the quest appears at the top-right of the screen. You can press q to enable and disable to list of quests in the UI. Then, when you travel into the location, the quest will be checked off and the amount of EXP you have will increase.

There is another variable where an event can be added inside the location script. You can use this field to turn off the location indicator once it has been reached the first time.

Inside the Events > SpecificEvents folder, add a new event called ArenaLocationReached by right-clicking and going to Create > Game Event. Drag this new event into the Specific Location Event variable.

Add a bunch of monsters around the location, and place them underneath another empty object called ArenaMonsters. Disable the monster objects, so that they won't appear at the initial start of the game.

On the ArenaMonsters object, add a GameEventListener component. This component will trigger certain actions when the event is raised by the Location script. Drag the ArenaLocationReached into the Event field, and under the Response section, click the plus button to add new responses, one for each of the enemies.

For each of those responses, have them set the game objects to be active when the event is fired. Now, when the player enters the location, the enemies will appear on the map to surprise the player.

Add one more response to disable the Location object after it has been reached from the ArenaEnemies object. That way it can only be triggered once, and will disappear once you reach it.

When you're building a game with programmers, it can be helpful to tell your programmers to add event capabilities to their scripts. That way, if you want to have something neat happen as a result of the player's actions, you don't need to ask the programmers to alter their code, you can perform the necessary steps inside of the Unity editor to have an object somewhere else in the scene listen for when that event is triggered.

Adding a New Enemy Type

You can create your own new enemy type very easily. Look at the objects that are children of the Monster object. Right now, the monster's appearance is made up of a couple of basic shapes.

Duplicate the object, rename it to SkeletonMonster, and unpack the prefab completely so that you can remove the basic shape objects.

Delete the objects that are currently used to represent the enemy, find the BasicSkeletonAnimation in Prefabs > Enemies, and add it where those objects used to be. Resize the object so that it fits the box collider (or resize the box collider so that it fits the size of the model.)

When you play the game, the skeleton will play a walking animation.

Having models that match the theme of your world makes a big difference for the immersion of your player.

Okay, so right now the skeleton just continually walks, even when it's standing in one place. Also, it would be great if it had an attack, rather just bumping against the player.

These concepts are beyond the scope of this lesson, but if you want to learn about how to set up animations for enemies, check out the Character Animation lesson after you're done with this lesson.

In that lesson, you'll learn how to have the skeleton have an idle state, walk around the map on a path, and play an attack animation when it is next to the player.

You might have noticed the notification said that you defeated a Basic Monster, but your skeleton is no ordinary monster. Next, you're going to give the skeleton monster his own stats. Inside of Variables > Enemies, right-click and create a new Monster Type Scriptable Object called skeletonMonster.

You can compare his stats with the other Monster Types already in the folder to set up his basic stats. If you want to have a notification display when the monster is defeated, make sure the MonsterDefeated event is in the Monster Defeated Event field.

Lastly, attach the new Scriptable Object to the Skeleton Monster inside of the scene, and make a new prefab out of your completed monster. The monster now has the new properties that you provided on the global Scriptable Object.

Spawn Enemies Over Time

For the player to be able to level up, they need to be able to defeat lots of enemies. You can create a zone where enemies continually spawn, so the player can go back there and level up before they go to the next area.

Find the prefab MonsterSpawnLocation inside of Prefabs > Systems and drag it into the scene.

The Box Collider on the script determines the locations where the enemies will spawn. You can resize the box collider to make the enemy spawn area larger or smaller.

In the MonsterSpawner component, you can change the monster prefab that is spawned in the Monster Prefab field, you can change the amount of time in between monster spawns in the Time to Spawn field, and change the max number of enemies to spawn in the Max Enemy Number field.

Design Considerations

With the tools that you have, you can create a basic RPG. There's lots more to think about that you could add to the RPG, but this is a good start.

The lessons that you learned in creating an Adventure game level will help you here. Try to design the terrain in a way that gives the player a sense of direction. You can place enemies along a line, so that the player defeats one after the other on the way to their destination. You can also build your terrain in such a way as to direct the player to the final area of the game.

One of the hardest parts about developing an RPG is determining how difficult enemies should be, and how much you should require the player to level up before they go to the next area. In this RPG system, you want to have a variety of enemies, some easier and some more difficult, as the player continues their journey. But that's not the only way to manage a level up system, as indicated by the level scaling video below.

Extra Credits