Create an RPG Combat System

In this tutorial, you will use advanced programming techniques to create an RPG

RPG Programming Architecture Issues

Understand the challenges of creating a Role-Playing Game (RPG).


Role-playing games can be a lot of fun to play. In a role-playing game, some of the common things that you can do are:

Defeat monsters
Get items in an inventory
Take on quests and get rewards for completing them
Talk to other characters in the world
Equip items to boost your stats
Gain experience points

This presents a challenge. All the other games that you've made so far only have a few systems. But to create a role-playing game, you need to find a way to create a large variety of systems that all work with each other as part of the game.

Below is one very, very simplified diagram showing the connections between all the different types of systems in an RPG that you have to consider, and how those systems interact with each other.



As you can see, there are...a lot of different systems inside an RPG. If you don't find a way to fit them together and make it expandable without a lot of rework, the RPG can be hard to restructure and debug.

We're going to use some advanced programming concepts to create a structure that will be expandable. But we're going to start with some of the basic mechanics of the RPG first, in particular the combat system.

Importing the Basic Project

Understand the challenges of creating a Role-Playing Game (RPG).

The basic project template we'll start with has a terrain and an FPSController set up in a scene. There are also some other prefabs set up in the project that you will use. Download the RPG Base Project

The terrain is basic, but you can update it later once the code has been implemented.

Adding a Monster

Adding an enemy that will attack the player when they see them.

To add an enemy, you're going to start with a prefab object. The enemy will be very simple. When the player enters a trigger nearby, it will move towards the player.

Then, when the player is close enough for the unit to attack, it will attack the player.

To start, grab the Monster Prefab and place it on the scene in front of the controller. This prefab is a very basic collection of various shapes.



Create a Scripts folder and create a new script called MonsterBehavior, This script will handle how our monster reacts to the player.

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

public class MonsterBehavior : MonoBehaviour {

    public float moveSpeed = 2f;
    public float turnSpeed = 40f;

    private GameObject player;
    private bool playerSpotted;

    private float speed;

	void Start () {
        player = GameObject.FindGameObjectWithTag("Player");
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            playerSpotted = true;
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            playerSpotted = false;
        }
    }

    void Update()
    {

        if (playerSpotted)
        {
            //Identify the location to move towards
            Vector3 targetPosition = new Vector3(player.transform.position.x,
                                                transform.position.y,
                                                player.transform.position.z);
            Quaternion q = Quaternion.LookRotation(targetPosition - transform.position);
            transform.rotation = Quaternion.RotateTowards(transform.rotation, q, turnSpeed * Time.deltaTime);
            transform.position = Vector3.MoveTowards(transform.position, player.transform.position, moveSpeed * Time.deltaTime);

            // Drop the character to the terrain, so that it can handle walking on hills
            float height = Terrain.activeTerrain.SampleHeight(new Vector3(transform.position.x, 0, transform.position.z));
            transform.position = new Vector3(transform.position.x, height, transform.position.z);
        }
    }
}
            


After you've added this script to the monster, add a sphere collider to the monster, make it a trigger and expand its size.

This trigger will be the way the monster finds the player. If the player walks inside this zone, the monster will start moving towards the player. If the player leaves the trigger zone, the monster will stop moving.



Next, you're going to add basic code that lets the monster kill the player.

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject == player)
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }
    }
			


This code isn't a trigger, it's a collision. When the monster collides with the player, the scene will reload.

After this code has been added, go back out to the Monster object and add another box collider to the object. For this collider, do not make it a trigger.

Try out your game and see how when the monster touches the player the scene restarts.



Adding a Basic Sword Attack

Give the player the ability to use a sword to hit the enemy.



It would be no fun if our player didn't have the ability to fight back against monsters. We're going to give the player the ability to use a sword.

Note: Considering you already know how to make an FPS game, you could apply the concepts behind an RPG to that game type as well, if you wanted to.

Look inside the Prefabs folder and find the Sword prefab, and place it as a child underneath the PlayerController's MainCamera. That way, the position of the sword will update as the player looks around.



The sword prefab has some animations connected to it, but we will need to write the code to enable those animations when the player clicks. This sword will have a collider that will activate when the attack animation is playing.

Create a script called Sword and write this code for the script.

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

public class Sword : MonoBehaviour
{
    Animator anim;

    private void Start()
    {
        anim = GetComponent<Animator>();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            anim.SetTrigger("attack");
        }
    }
}
			


Attach the Sword script to the Sword object in the hierarchy. Now you will be able to press the mouse button to play the attack animation, but it won't have any effect on the enemy.



To have the sword defeat the enemy, add a tag called Blade to the blade object of the sword. Add a rigidbody component to the blade, and freeze all positions and rotations.



Then add the below code to the MonsterBehavior script.

void OnCollisionEnter(Collision other)
    {
        if (other.gameObject == player)
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        } else if (other.gameObject.tag == "Blade")
        {
            Destroy(this.gameObject);
        }
    }
			


This code will destroy the monster any time it is hit by a blade



Now we have a game where the player can kill monsters, but it's a bit bland. In the next sections we'll learn how to give enemies health, add a UI to the game, and gain experience from killing monsters.