Explore Free RPG Tutorials – GameDev Academy https://gamedevacademy.org Tutorials on Game Development, Unity, Phaser and HTML5 Fri, 07 Apr 2023 05:00:35 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://gamedevacademy.org/wp-content/uploads/2015/09/cropped-GDA_logofinal_2015-h70-32x32.png Explore Free RPG Tutorials – GameDev Academy https://gamedevacademy.org 32 32 How to Create your First RPG UI in Godot https://gamedevacademy.org/godot-rpg-ui-tutorial/ Fri, 07 Apr 2023 05:00:35 +0000 https://gamedevacademy.org/?p=19841 Read more]]> Fact: the global RPG market is worth billions. Also fact: it’s no longer a realm for big gaming companies, but something solo and indie game developers can pursue as well.

If you’re looking to create your own games, you should definitely take into consideration making your own RPG. RPGs present you too with the opportunity to expand your coding and game design skills – as they incorporate lots of different game mechanics. However, no RPG really works without a UI, so this can’t be neglected as you develop your ideas.

In this Godot tutorial, we’re focusing on the implementation of UI elements for your RPG game. Here, we’ll be setting up a health bar together and we’ll also style a text label in order to display the amount of gold we have in the game.

Let’s dive in!

Project Files

In order to be able to follow along with this tutorial, you’ll need to download the assets found here. You can also download a copy of the source code files for the project done in the tutorial by clicking here.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

Creating the UI

Let’s start by creating the UI for our RPG game.

UI Scene

Let’s go up to Scene > New Scene:

Creating a new scene in Godot

We’re going to create a root node of ‘User Interface‘:

Select 'User Interface' for the root node

We’ll rename the node to “UI” and save the scene as “UI.tscn“:

Renaming the node to "UI"

Health Bar

Let’s right-click on our UI node and add a child node of type TextureProgress:

Adding a child node for the UI node in Godot

A TextureProgress is a bar, which can fill up a certain amount based on a given value:

TextureProgress bar in Godot

In the Inspector, we’ll drag in the image for our UI texture (UI > UI_WhiteSquare.png). into Textures > Under and Textures > Progress:

Dragging our UI texture image into the Textures' settings

We’ll also set Tint > Under to dark grey, Tint > Progress to red, and Range > Value to 50 so we can see that the progress is 50% of the way.

Enable ‘Nine Patch Stretch‘ so that the bar can be stretched to fit the size of the border:

Enabling 'Nine Patch Stretch' for the TextureProgress node in Godot

We’ll click and drag the anchor point down to the bottom left, so the health bar is snapped to the bottom left corner of the screen regardless of the screen size:

Snapping the health bar to the bottom left corner of the screen

Gold

Let’s create a new label node as a child of UI, and rename it to “GoldText”:

Creating a "GoldText" label for our UI node

Then position it above the health bar and extend it out sideways:

Positioning the GoldText node above the health bar on the screen

We’ll give it a sample text (“Gold: 500”) and align the text to the center:

Setting a sample text for our label in Godot

Sample text displaying on the screen

Custom Font

Let’s right-click on our font file (Font > Ubuntu-Regular.ttf), and click on “New Resource…“:

Adding a new font resource in Godot

… and create DynamicFont and save it as “Ubuntu-Regular.tres”:

Creating a DynamicFont in Godot

Save the new font as "Ubuntu-Regular.tres"

We’ll set the font size to 30 in the Inspector, and drag our font file (Ubuntu-Regular.ttf) into Font Data:

Setting up the new font's attributes in the Inspector

Now, let’s select the GoldText node, and assign a custom font here by dragging in the dynamic font (Ubuntu-Regular.tres) into Custom Fonts:

Assigning the dynamic custom font to the GoldText in Godot

Make sure that the anchor point of this node is also positioned at the bottom left corner of the screen:

Positionof the anchor point of the label node is at the bottom left corner of the screen

Implementing the UI

Now that our UI is all set up, let’s go back to our main scene and create a new node of type CanvasLayer:

Creating a new CanvasLayer node in Godot

Let’s drag in our UI (UI.tscn) as a child of the CanvasLayer:

Placing the UI.tscn as a child node of the CanvasLayer

UI node as a child of CanvasLayer in Godot

Our UI is now rendered on our screen:

UI rendered in Godot

UI Script

In the UI Scene, let’s go to our UI node and create a new script:

Creating a new script for our UI in Godot

Setting Up Variables

First of all, we’re going to be creating variables to get access to our UI nodes (get_node):

extends Control

onready var healthBar = get_node("HealthBar")
onready var goldText = get_node("GoldText")

Now we need to create a function for each of these variables, which will update their values.

Updating the Health Bar

Let’s update our health bar first. Note that the value of the health bar is a number between zero and 100. (0% ~ 100%):

extends Control 

onready var healthBar = get_node("HealthBar")
onready var goldText = get_node("GoldText")

# called when we take damage
func update_health_bar (curHp, maxHp):
  
  healthBar.value = (100 / maxHp) * curHp

We divided 100 by our maxHP to get the percentage value and then multiplied it by curHP to get our current health.

Updating the Text

Let’s update our gold text now. Make sure to include the text and the colon (“Gold :“) before the number:

Updating our gold text in Godot

extends Control

onready var healthBar = get_node("HealthBar")
onready var goldText = get_node("GoldText")

# called when we take damage
func update_health_bar (curHp, maxHp):
  
  healthBar.value = (100 / maxHp) * curHp


# called when our gold changes
func update_gold_text (gold):
  
  goldText.text = "Gold: " + str(gold)

Initializing The UI

Next, we need to connect this up to the actual Player node. Let’s open up our Player script:

Opening up the Player script in Godot

… and create a variable to get access to our UI node:

onready var ui = get_node("/root/MainScene/CanvasLayer/UI")

We need to initialize the UI inside of the ready() function for us to see the current values instead of the default values:

func _ready ():
  
  # initialize UI
  ui.update_health_bar(curHp, maxHp)
  ui.update_gold_text(gold)

Make sure that the UI node is placed at the top of the hierarchy as it’ll return an error otherwise. This is needed because Godot initializes and updates all their nodes from top to bottom:

Placing the CanvasLayer at the top of the hierarchy in Godot

The UI node must be placed above the Player node in order for the player script to access it.

Updating UI Elements

Finally, we have to update our UI values as we play. For that, let’s get our UI node to update the HP bar inside take_damage function:

func take_damage (damageToTake):
  
  curHp -= damageToTake
  ui.update_health_bar(curHp, maxHp)
  
  if curHp <= 0:
    die()

We also need to update the gold text inside give_gold function:

func give_gold (amount):
  
  gold += amount
  ui.update_gold_text(gold)

Now if we press play, you can see that our health starts to go down if we get attacked, and our gold goes up each time we collect a coin as expected:

UI elements updating correctly in Godot

Conclusion

Well done on completing this tutorial!

Here, you’ve learned how to implement the UI for your RPG game in Godot, something you can surely expand upon and also use in other game projects as well. This UI is also useable for any kind of subgenre you want to pursue as well – whether you want to go for an action RPG like we did or something more traditional and turn-based.

However, there’s a lot more to expand upon here even in the realm of UIs! Perhaps you want to create a second bar for mana, add a frame to your health bar, or even change the health bar’s shape entirely. There are endless possibilities even in this realm – in addition to learning tons of other core mechanics!

We hope that you have fun as you continue developing your games and wish you the best of luck in your future projects!

Want to learn more about RPGs in Godot? Try our complete Develop a 3D Action RPG with Godot 3 course.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Best RPG Tutorials – Making Role Playing Video Games https://gamedevacademy.org/best-rpg-tutorials/ Wed, 25 Jan 2023 09:54:00 +0000 https://gamedevacademy.org/?p=15481 Read more]]> One of the biggest reasons that people get into coding is to learn how to make their own games. However, every gaming genre has its own quirks and requirements to learn in order to successfully create your own game, especially when it comes to RPGs.

RPGs are one of the oldest and best-known game genres, taking in the likes of Final Fantasy, Pokemon, The Elder Scrolls and a variety of other famous series. The appeal of creating your own RPG is the ability to craft your own fantastic world and tell an epic story – but to do that, you first need to know how to actually code an RPG.

We’ve compiled some of the best RPG tutorials available to help you start your journey into creating your very own RPG. Whether you’re a novice coder or an experienced game-maker looking to expand your skill set, these tutorials cover all the skills you’ll need to craft your first RPG.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

Why Should I Learn To Make An RPG?

Best RPG Tutorials: Beginner’s Guides To Creating Your Own Role Playing Game

The games industry is also an absolutely huge sector and offers a wealth of opportunities for up-and-coming coders – especially when it comes to RPGs. The global RPG market is expected to be worth nearly $22.5 billion by 2023, clearly showing just how lucrative a career in RPG development can be! 

RPGs also happen to be one of the most successful genres for solo and indie game developers – you don’t have to be part of a large studio to create a fantastic and successful RPG. The huge success of indie titles like Undertale, CrossCode and Disco Elysium clearly shows the potential for indie RPG developers to make a huge splash with their games.

Aside from the career benefits of learning to make your own RPG, they also present a great opportunity to expand your coding and game design skillsets. RPGs incorporate many different game mechanics and systems like world design, NPC programming, battle mechanics, quest systems, inventories and more, all of which help you learn valuable transferable skills to use in other game design projects.

More than anything, creating your own RPG is fun! Designing and creating an RPG is a great way to let your imagination run wild, creating fantastic worlds and epic stories to share with others.

The following list includes some of the best tutorials currently available for learning the core mechanics of RPG games and how to code them. 

Most of these are designed for beginners – while some of them might require existing knowledge of certain tools or programming languages, they do a great job of introducing you to the basics of RPG design and providing a step-by-step guide to building your own RPG.

2D RPG Academy & 3D RPG Academy

The 2D RPG Academy and 3D RPG Academy are a set of comprehensive RPG design curriculums from Zenva Academy. The aim of the curriculums is to learn to create your own 2D and 3D RPGs (respectively) from scratch in Unity, teaching you to implement battles, NPCs, dungeons, and more. The RPG Academies cover everything you need to know about building RPGs in Unity, taking you from an RPG novice to a master of the craft by the end of their individual course sets. 

These curriculums are a great option for those who are just starting out with game design, since it covers the basics of game development in general in its first module before moving onto RPG-specific systems in subsequent sections. The curriculums are structured to walk you through world design, core gameplay systems and other essential features for building your own RPG.

Key Topics Covered:

  • Custom avatars
  • Explorable towns
  • NPCs and dialogues
  • Enemy AIs
  • Battles
  • Crafting
  • Game saving
  • Procedural Dungeons

Duration: 25 hours of video tutorials across a wide range of topics 

Learn Unity Engine And C# By Creating A Real Top Down RPG

Created by Unity tutor Epitome, the “Learn Unity Engine and C# by creating a real top down RPG” tutorial is an extensive guide to creating a top-down RPG in Unity from start to finish. 

It’s a comprehensive guide that takes you through absolutely everything you need to know about creating your own top-down RPG, from the initial installation and setup of Unity to implementing core RPG systems. Later sections also focus on improving the player experience by tightening up UI and other features, as well as adding new content to extend the length of the RPG.

This tutorial is slightly older than others on this list, having first been published on Udemy in 2017 before being made available for free on Epitome’s YouTube channel in 2021. However, it still coves a lot of useful subjects that budding RPG makers will find extremely useful when working on their own projects. 

Key Topics Covered:

  • Movement and manual collision detection
  • Tilemaps and creating top-down dungeons
  • Interactive objects and inheritance
  • Saving game states
  • Floating text systems
  • Top-down combat systems 
  • Key animations including weapon swings
  • Character menu and UI systems
  • Adding new content

Duration: A 7 hour, 45 minute-long video broken up into segments focusing on specific areas of RPG development.

Construct A Micro-Farming RPG

If you’re someone who’s already gained some experience in coding and game design and you’re looking for a shorter tutorial to learn some of the core mechanics of RPGs, then the Construct A Micro-Farming RPG tutorial may be the guide for you. 

This slightly shorter tutorial allows you to follow in the footsteps of classic series like Harvest Moon and recent hits such as Stardew Valley by creating your own farming-based RPG. The tutorial delves into various systems and mechanics prevalent in the popular farming RPG subgenre such as crop growing, scriptable objects, tilemaps and resource management.

By the end of the tutorial, you’ll have created your own micro-farming RPG project, which can make for a great addition to your portfolio. The skills you learn in this farming RPG tutorial can also help you to diversify and expand your future projects with new mechanics and systems. 

All you’ll need to successfully complete this course is a basic understanding of Unity and C#, making it an ideal course for game design beginners and pros alike.

Key Topics Covered: 

  • Setting up 4-direction player movement
  • Creating tilemaps with interactable tiles
  • Storing crop data as Scriptable Objects
  • Implementing crop growing and watering mechanics
  • Controlling resources such as money
  • Displaying information with a UI
  • General Unity principles like singleton programming patterns, pseudo-state machines and more

Duration: About 1 hour, 20 minutes of video tutorials covering farming RPG systems

How To Make An RPG In Unity

Another option for those who are looking for a shorter tutorial is the “How to make an RPG in Unity” series from Brackeys and Sebastian Lague. This tutorial series breaks down RPG development into a series of videos exploring core subjects, making it easier to get to grips with the basic skills needed to successfully create an RPG in Unity.

The series is split into gameplay tutorials delivered by Brackeys and Sebastian Lague’s tutorials on integrating graphical elements into your RPG, with further RPG graphics tutorials also available on Lague’s own channel. 

The gameplay tutorials cover subjects like player and camera movement, interactables and items, inventory systems, equipment, character stats and more. Meanwhile, the graphics tutorials teach you how to model, rig and animate simple characters in Blender, then integrate these and other graphical elements into your RPG. 

Key Topics Covered: 

  • Movement
  • Interaction
  • Items
  • Inventory UI and code
  • Equipment
  • Stats
  • Enemy AI
  • Combat
  • Integrating graphical elements
  • Triggering the correct animations in different scenarios
  • Graphics interfacing with the equipment system

Duration: Just over 3 hours of video tutorials organised in a dedicated YouTube playlist, plus additional graphics tutorials on Sebastian Lague’s channel.

Create A 3D Turn-Based RPG

Turn-based combat is a staple feature of the RPG genre, made famous by classics like the early Final Fantasy games, Pokemon, and more. To this day, it remains one of the most popular battle systems used in RPGs, so it makes sense to learn how to implement turn-based battle mechanics if you want to build your own RPG.

That’s where the Create A 3D Turn-Based RPG tutorial comes in. This tutorial helps you to master turn-based battle systems by building your own 3D RPG from scratch, teaching you to program different kinds of attacks and actions, customize enemy encounters and more. 

The project is fairly open-ended, giving the scope to create a larger 3D RPG project off the back of this course or simply to use it to create a smaller project and add new skills to your arsenal. All you need to get started is some existing knowledge of C# and Unity; the course will walk you through everything else.

Key Topics Covered: 

  • Setting up player and enemy sets
  • Managing turns and action displays
  • Implementing different attacks and skills
  • Creating simple, combat-ready enemy AI
  • Adding UI feedback for gameplay
  • Building a map board with encounters 
  • Unity skills such as singleton and observer programming patterns, class inheritance for efficient codebases, and more

Duration: Roughly 5 hours, 20 minutes of video tutorials guiding you through the project from start to finish.

Godot Action RPG Series

Most of the tutorials in this list are for the hugely popular Unity game engine; however, if you prefer to use other engines, then the Godot Action RPG tutorial series from HeartBeast may appeal more to you. 

Godot 3.2 is an open-source game engine specifically designed for use by indie game developers, so solo game designers may find it more appealing than Unity. The Godot Action RPG tutorial series teaches you how to use Godot to create a top-down action RPG in Godot, covering various topics like movement, hitboxes and hurtboxes, stats systems and more. 

The series is intended for beginners but expects you to have some level of coding knowledge before starting. If you’re a complete coding beginner you may need to learn some programming basics before taking on these tutorials, but otherwise, they’re very beginner-friendly with helpful explanations for each new concept or mechanic that’s introduced.

Key Topics Covered: 

  • Setting up Godot 
  • Player movement and animations
  • Autotiles and collisions 
  • Attacking and other actions
  • Hurtboxes and hitboxes
  • Enemy design, stats, variables and behaviours
  • Player stats, health and UI 

Duration: Roughly 8 hours, 40 minutes of video tutorials.

Build A Micro-RPG

If you’ve already gained some game design experience on other projects and want to dip your toes into RPG development to learn some new skills, then you might like the Build A Micro-RPG course. This tutorial takes you through the entire process of building a top-down micro-RPG in Unity, giving you the skills you need to take on bigger RPG projects or add RPG mechanics to other games. 

This course is a great option for beginners and experienced coders alike. It introduces you to a range of essential skills for developing fully-fledged RPGs while keeping the initial project short, simple and exciting. All you need is a basic understanding of C# and Unity; the course will teach you the rest. 

Once you’ve completed the Build A Micro-RPG tutorial, you’ll have mastered a variety of transferable skills that will help you expand and diversify your next project with new mechanics. Whether that means another RPG of larger scope or a completely different genre that you want to add RPG mechanics to is up to you.

Key Topics Covered: 

  • Setting up basic Tilemaps with Unity’s Tilemap system
  • Developing players and enemies that can move and attack each other
  • Implementing a simple experience system
  • Using Unity’s UI elements to display health, money, and other data
  • Controlling Unity’s camera to follow the player
  • Building a dynamic interaction system that works for a variety of objects (doors, chest, loot, etc.)

Duration: Just over 2 hours of video tutorials.

Conclusion

Learning to build your own RPG is a fun and rewarding process that helps you to master a variety of new game mechanics and systems at the same time as practicing and developing existing coding skills. By following the tutorials above, you’ll learn many of the foundational skills you’ll need to craft your own epic RPG – and hopefully, you’ll have fun at the same time!

Don’t forget though – RPGs are a broad genre, so don’t forget to continue to explore around. There are lots of learning resources out there – and the more you learn, the better your games will be!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Best Roguelike Tutorials – Learning Game Dev Online https://gamedevacademy.org/best-roguelike-tutorials/ Wed, 25 Jan 2023 08:32:40 +0000 https://gamedevacademy.org/?p=15561 Read more]]> Roguelikes are not only a popular genre of videogames, but they’re one of the most interesting as well. Focusing more on replayability and randomized worlds rather than tightly-structured level design, they provide players and developers with the chance to explore a wide variety of interesting mechanics through ever-shifting game worlds.

If you’re interested in creating your own roguelike games, we’ve put together this handy list of online tutorials that provide a perfect starting point for you to learn the essential game mechanics and programming skills you’ll need to succeed. 

Why Should You Learn To Create A Roguelike?

Roguelikes are a slightly more niche genre than others, but they still have plenty to offer to both players and developers. Recent hits like Hades and Darkest Dungeon prove that this genre can be used for extremely inventive gameplay and innovative storytelling, which makes roguelikes a very interesting project for game developers in-training to work on.

Roguelikes are often characterized by a randomized, procedurally generated game world that changes with every new playthrough. Learning procedural generation can be a valuable skill for game developers; as well as roguelikes, it can be applied to survival games, simulations, sandboxes and more. 

In addition to procedural generation, roguelikes give developers a chance to work with a variety of other game mechanics as well. Action-oriented roguelikes can help you to practice character movement, enemy scripting and combat mechanics, while roguelikes with RPG elements can help you to learn more about turn-based combat, stat systems, and game balance. 

Basically, roguelikes are a highly adaptable genre that you can use to practice new mechanics and experiment with systems from different genres, all while creating a fun and highly replayable gaming experience. As such, they make for great projects for beginners and more experienced game developers alike.

Roguelike Game Online

If you’re ready to get stuck into your first roguelike project, then the following list of tutorials will give you plenty of potential starting points. From dungeon-crawlers to survival games, these tutorials cover a variety of niches within the roguelike genre and will help you to build a range of essential skills to make a successful roguelike of your own.

Roguelikes are naturally slightly more complex than other genres, but we’ve made sure to include several tutorials in this list that are perfect for beginners as well as more experienced developers. 

The Complete 2D Roguelike Course

If you’re looking for somewhere to start your roguelike development journey, then there are few better options than this comprehensive tutorial from Zenva Academy. The Complete 2D Roguelike Course is a detailed introduction to the genre, exploring the fundamentals of roguelike development and guiding you through the process of making your first roguelike.

The tutorial walks you through a step-by-step guide to creating your own 2D dungeon-crawling roguelike in Unity. You’ll learn to procedurally generate dungeons, create enemies, code items and powerups, and more, all while learning a variety of skills that can help you to flesh out future projects with all sorts of new features. 

All you need to get started is a basic understanding of Unity and C#, making this tutorial a fantastic option for beginners. Even if you already have plenty of experience with the Unity platform, The Complete 2D Roguelike Course is still definitely worth taking – you’ll learn a range of useful skills for other projects and master a new genre at the same time as expanding your portfolio with a new game.

Key Topics Covered:

  • Creating random dungeon maps through code
  • Generating randomized dungeon room interiors
  • Implementing enemies and a simple battle system
  • Adding health and gold pickups with UI
  • Controlling gameplay flow with keys & doors
  • Setting up a mini-map system

Duration: Just over 3 hours of video tutorials explaining the entire process of building a 2D dungeon-crawler roguelike.

2D Roguelike Project

Another option for learning to make your own 2D roguelike in Unity comes from Unity itself in the form of the Unity 2D Roguelike Project tutorial series by Unity itself. These tutorials guide you through the process of creating a simple 2D roguelike where the player character must search for food and survive a wasteland for as long as possible.

The game project is turn-based and tile-based, with each tutorial teaching you to add new elements like level randomisation, enemies, audio and more. By the end of the series you’ll have mastered a variety of fundamental game mechanics for the roguelike genre and be ready to implement these systems into your own games to create your own roguelike. 

Key Topics Covered: 

  • Animating and moving the player character
  • Using tile prefabs 
  • Board and game managers
  • Moving objects and walls 
  • Player and enemy scripts
  • UI design
  • Level creation and transitions
  • Audio
  • Mobile controls 

Duration: A series of shorter tutorial videos lasting roughly 2 hours.

Build A Roguelike Game With C++ And SFML

Another option for roguelike development from Zenva is the Build a Roguelike Game with C++ and SFML tutorial. This tutorial works along similar lines to the 2D Roguelike Course, except it uses the Simple and Fast Multimedia Library rather than Unity, so if you’re not keen on using Unity then this is an ideal alternative. 

The tutorial guides you through the process of using SFML’s multimedia capabilities to build a 2D action-oriented roguelike where players must dodge moving enemies to reach the exit in each level. By the end you’ll have created your own version of the project, learning various skills such as user interaction, adding graphics, building dungeons and more along the way.

You’ll need some existing familiarity with the C++ language and SFML to get started with this project, but with a simple step-by-step structure, it’s easy to follow and perfect for beginners. It also makes for a fun project for more experienced developers who want to learn to use new tools, since the course acts as a great introduction to both C++ and SFML.

Key Topics Covered:

  • Setting up SFML game projects
  • Drawing sprites to the screen
  • Constructing tile-based maps with C++
  • Detecting user input for player movement
  • Moving enemies to available spaces randomly
  • Implementing logic for ending the game

Duration: 2 hours of video tutorials explaining how to make a 2D roguelike in SFML.

How To Create A 2D Roguelike Game

The How To Create A 2D Roguelike Game tutorial series from Dapper Dino provides another great entry point for game developers who are curious about dipping their toes into the roguelike genre. Like many of the other tutorials on this list, the tutorial focuses on using Unity to implement the various mechanics and systems that are commonly found in roguelike games.

The tutorial takes inspiration from the roguelike game Wizard of Legend, using it as a reference point for which systems to include in your own roguelike. Following the tutorial, you’ll steadily build up your own simplified roguelike in the style of Wizard of Legend, mastering core mechanics like combat, loot drops, class systems, map generation and more.

You’ll need some existing knowledge of Unity and C# to ensure you understand each part of the tutorial, but it does a good job of providing step-by-step instructions at each stage, so it’s fairly accessible even if you’re more of a beginner than a pro. 

Key Topics Covered: 

  • Creating a menu
  • Importing spritesheets and setting up character movement
  • Setting up animations and transitions
  • Creating health and stat systems
  • Programming simple spells and combat actions
  • Camera movement and controls 
  • Dashing mechanics
  • Collectible items including currency and loot drops
  • Currency UI 
  • Class systems 
  • Enemy spawning systems 

Duration: Just under 4 hours of video tutorials, each exploring different mechanics in the roguelike genre.

2D Procedural Maps For Beginners

If you’ve already worked on a few different game projects and want to try your hand at a roguelike next, but don’t want to have to sit through a tutorial covering game design fundamentals you’ve already learned, then this may be the tutorial for you. 

The 2D Procedural Maps for Beginners tutorial is a shorter tutorial series that provides step-by-step instructions for creating procedurally generated 2D game maps in Unity. You’ll learn the expandable programming logic needed to create these maps, plus key systems like noise maps, biome calculations, player controllers, and more.

Once you’ve used this tutorial to master procedural generation, you’ll be all set to implement these systems into your projects, allowing you to build roguelikes from the ground up or add randomized worlds into other projects to give them a roguelike twist. 

Key Topics Covered: 

  • Generating noise maps in Unity
  • Understanding noise settings for different effects
  • Calculating biomes based on noise map data
  • Organizing biome data with Scriptable Objects
  • Instantiating 2D tiles based on biome data
  • Implementing a player controller

Duration: 1 hour, 30 minutes of video tutorials explaining each step in creating procedurally generated maps in Unity.

Roguelike Python Tutorial

If you’re unfamiliar with Unity or C# and would like to learn to make a simple roguelike without using these, then another option is to follow the Roguelike Python Tutorial from Ombarus. This series guides you through the process of creating a very basic roguelike using standard keyboard symbols to represent the map and characters, giving it an appearance similar to the original Rogue game that the genre is named for. 

The tutorial follows the structure of the text-based 2020 Roguelike Tutorial, meaning you can refer to a written guide if you get stuck at any point. Through the course of the tutorial series, you’ll learn to create and control a player character, generate randomized maps, implement a turn system and more, allowing you to get to grips with many of the core mechanics of the roguelike genre.

While this tutorial leads to a much more simplistic finished project than some of the other options on this list, it’s still a fun way to learn more about the systems used in roguelike games, and it provides a fun entry point for coders more familiar with Python than Unity. 

Key Topics Covered: 

  • Setting up and controlling a player character
  • Generating random maps and enemies
  • Adding a field of view system
  • Adding a turn system 
  • Coding combat systems and UI
  • Adding interactable items, spells and other actions
  • Saving the game
  • Creating multiple levels
  • Balancing the game and adding equipment

Duration: Roughly 2 hours, 45 minutes of video tutorials covering each stage of creating a simple Python-based roguelike.

The Complete Procedural Terrain Generation Course

While the majority of the roguelike genre is made up of 2D games, there are no rules against using a 3D environment for your roguelike, especially when blending your roguelike with other genres. Recent hits like Returnal have shown that blending the random elements of the roguelike genre with 3D environments and fast-paced action can be a winning combination.

So, if you want to try your hand at creating your own 3D roguelike, the best place to start is to understand how procedural generation works in a 3D environment in order to craft random levels for your players. The Complete Procedural Terrain Generation Course allows you to do just that, teaching you the fundamentals of using procedural terrain generation to create randomized maps complete with varied biomes. 

The tutorial will help you learn to algorithmically generate a terrain’s shape with C# in Unity, and also provides a guide to performance optimization to ensure a smooth playing experience in your randomised world. You’ll need a basic understanding of Unity and C# to get started, but otherwise, this step-by-step guide is extremely accessible and beginner-friendly.

Key Topics Covered:

  • Generating noise maps to determine the shape of the terrain
  • Utilizing noise maps as height maps to produce terrain
  • Applying gradient textures to a mesh based on terrain shape
  • Setting up heat maps and moisture maps based on the terrain height
  • Combining various data elements to algorithmically determine biomes
  • Using biome types to determine how trees spawn

Duration: Roughly 3 hours, 40 minutes of video tutorials explaining the process of procedural terrain generation using Unity.

Conclusion

Roguelikes provide aspiring game developers with an exciting and unique challenge, tasking them with creating fun and replayable gameplay within randomized levels and worlds. As such, they’re a perfect next step for those who have completed a few different projects and want to tackle a more complex genre next. 

Using the tutorials above, you should be able to master many of the core mechanics found in roguelike games. Whether you choose to create your own roguelike or implement roguelike mechanics within your other projects to give them a new and unique twist is up to you!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Kaboom.js Tutorials – Complete Guide for Easy Game Dev https://gamedevacademy.org/kaboom-js-tutorials/ Sat, 21 Jan 2023 05:11:59 +0000 https://gamedevacademy.org/?p=14977 Read more]]> Do you want an easy-to-use game framework to build your dream projects?

Kaboom.js is a relative newcomer to the game development scene, but it is already making a big splash – especially among indie creators. This JavaScript-based library was made specifically with games in mind, in the same vein of frameworks such as Phaser or Pixi.js. However, there are many aspects that have made it stand above its competitors and worth your time checking out.

In this article, we’re going to introduce you to Kaboom.js and show you how you can get started learning this new tool.

Let’s get started!

What is Kaboom.js?

As mentioned, Kaboom.js is a JavaScript library in the vein of HTML5 games, which use the browser to render games made with it. The library was made with the idea of simplicity, but comes with many important game development features – such as layering, collision detection, input handling, and more. Regardless, though, the goal is to allow novice developers to create game scenes as quickly as possible.

Game objects in Kaboom.js are conveniently rendered with a component-based system. This means they’re extremely easy to manipulate and apply behaviors too. The behaviors can include everything from simple game mechanics like health to basic movement-based animations – so each game object essentially suits object oriented programming principles.

Beyond this, it is worth noting Kaboom.js is also an available template for Replit – a popular, in-browser coding environment. This means its well-suited for developers who aren’t interested in setting up local development environments or just want to play around with the library.

Key Pros of Kaboom.js

Why should you use Kaboom.js? Below, we’re going to explore what makes Kaboom.js stand out and how, as a developer, you can benefit from the advantages Kaboom.js offers.

Screenshot of the Kaboom.js playground

Fast and lightweight

Unfortunately, not everyone has a computer that can run game engines such as Unity or Unreal Engine – which both are pretty process intensive programs. However, Kaboom.js does not require a great computer and can be used even with low-end laptops. In fact, due to its incorporation with Replit, as mentioned above, you really only need a browser if you’re intent on using it – not even a code editor is required.

Likewise, because of how lightweight it is, games made with Kaboom.js run very smoothly as well. This means you don’t have to get hung up too much on optimization. Instead, your games will likely run quickly right out of the box, leaving you more time to focus on what matters.

No dependencies

Many frameworks and libraries out there require several layers of dependencies to be able to run properly. If you forget the dependency, or more tragically, if the dependency has a breaking change, your game isn’t going to work.

Kaboom.js doesn’t require any sort of dependencies. While you certainly can add packages such as webpack, natively you just need to import the Kaboom.js library itself. Once that is added, you won’t have the extra worry of maintaining the dependencies. This helps Kaboom.js achieve its goal of making it quick to setup and allowing you to dive straight into the fun stuff of actually making the game.

Cross-platform compatible

Since Kaboom.js is specifically for creating browser-based games, this means that there are no platform limitations. If the device can connect to the internet, your players can play it from anywhere.

For you as a developer, this means two things. First, this helps you avoid messy setups of needing multiple game versions just to have it available for multiple platforms. Second, this opens you up for a wider audience since you can tap into different sorts of players. All in all, though, this is a boon that makes it much easier for you to get the game into multiple different hands.

Simplicity

If you’ve ever tried to read documentation for frameworks or libraries before, you’ll know they can get rather complicated. If you don’t believe us, just go check out Unity’s documentation. While certainly this is fine for experienced developers, beginner developers are going to find this a nightmare.

Kaboom.js was designed to eliminate this problem and be as simple as possible. Not only does this help with keeping it lightweight, but makes the documentation much, much easier to understand when you’re just a beginner. This, in turn, just makes development itself easier.

Additionally, it comes with the extra benefit that this documentation can more easily be maintained as the library is updated. This means you won’t be reading old information that was relevant five versions ago.

Specifically made for beginners

As you might have seen from the previous points, beginners were at the heart of the design choices for Kaboom.js. Everything about the library is made to benefit beginners who have never made a game before. While there is a need for JavaScript experience before diving in, this is a much lower point of entry compared to heftier engines.

Thus, you’re only going to need a few tutorials to get the gist of how Kaboom.js works – and soon be able to develop your own projects with it.

Active development

Over the years, many HTML5 frameworks have come and gone. For others that remain, the development can often be slow and new versions, bug fixes, and features are few and far between. While many of these frameworks still technically work, the lack of developer support can eventually become a hindrance.

Kaboom.js, on the other hand, is very actively and caringly developed. Though we don’t expect them to break their principles of simplicity, improvements to the library come frequently. Thus, you can be assured the library will be supported for whatever time it needs for you to build your project.

Screenshot of the Kaboom.js GitHub page

What can you make with Kaboom.js?

Being based on HTML5 (i.e. for the browser), projects made with Kaboom.js do have limitations – as our browsers and internet are only so powerful no matter which JS library we’re talking about. So, you shouldn’t expect to make any kind of AAA game with the library. Kaboom.js was also specifically made for 2D development, so 3D graphics are kind of off the menu as well.

Past these two minor limitations, though, Kaboom.js does not put any further obstacles in your way. You can build small games in just about every genre, and only your imagination is there to hold you back. This includes everything from platformers to adventure games to old-style retro games like Breakout, Super Mario Bros.Space Invaders, and so forth.

If you want to explore the full scope of what people have already made, you can check out Kaboom.js made games below:

Kaboom.js & JavaScript Tutorials

Ready to create games with Kaboom.js? Check out the links of tutorials below which cover Kaboom.js, JavaScript for HTML5 development, and the game development process.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
How to Create an RPG Game in Unity – Comprehensive Guide https://gamedevacademy.org/how-to-create-an-rpg-game-in-unity-comprehensive-guide/ Mon, 19 Dec 2022 09:44:57 +0000 https://gamedevacademy.org/?p=4665 Read more]]> In this tutorial, we are going to build an RPG game using Unity. Our game will have three scenes: a title scene, a town scene, that represent the game world, where the player can navigate and find battles, and the battle scene. The battles will have different types of enemies, and the player units will have different actions such as: regular attack, magic attack, and running from the battle.

In order to follow this tutorial, you are expected to be familiar with the following concepts:

  • C# programming
  • Using Unity inspector, such as importing assets, creating prefabs and adding components
  • Basic Tiled map creation, such as adding a tileset and creating tile layers

Before starting reading the tutorial, create a new Unity project and import all sprites available through the source code. You will need to slice the spritesheets accordingly.

Source code files & Requirements

You can download the tutorial source code files here.

The sprites used in this tutorial are from the Superpowers Asset Packs by Pixel-boy. All sprites are available under the Creative Commons Zero (CC0) license. So, you can use them in your games, even commercial ones.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

Tutorial Requirements

Before beginning, it is assumed that you have the basics of Unity under your belt. If not, you can feel free to check out some of our other Unity tutorials first. Alternatively, you can also jump into more comprehensive online courses designed to take you from zero to industry-ready developer.

For teachers, you may also want to check out Zenva Schools. This platform made specifically for classroom usage offers several Unity-based courses (alongside other in-demand digital technologies topics). There are also plenty of useful features for classrooms including classroom management tools, reporting, course plans, and more.

Title Scene

Background canvas

First of all, we are going to create a Canvas to show the background image in the Title Scene. You can do that by creating a new Canvas called BackgroundCanvas, and setting its render mode as Screen Space – Camera. In order to do so, we need to specify the camera of the canvas, which will be our main camera. Also, the UI Scale Mode (in Canvas Scaler) will be set to follow the screen size, with a reference resolution of 1280×960.

Creating a canvas for the background.

After doing that, we create a new Image object as a child of this canvas. The source image will be the background image, and we can set its native size in order to properly show it.

HUD canvas

Now, we need another Canvas to show the HUD elements. In the Title Scene, those elements will be a title text, and a play button.

Let’s start by creating another Canvas following the same process as the BackgroundCanvas. However, in order to show this canvas over the background one, we need to properly set its sorting layer. We are going to create another layer called HUD, and put the HUDCanvas on this layer.

Creating the HUD canvas.

Finally, we need to create the two HUD objects. The first one is a Text, while the second one is a Button. For the Text object we only need to set its message. On the other hand, for the Button object we need to set its OnClick callback.

Creating the title text for the main menu.

Creating the play button which will launch the town scene.

The PlayButton object will have the following ChangeScene script for the OnClick callback. This script will simply define a method to start a new scene given its name. Then, we set the OnClick callback of the play button to call the loadNextScene method with “Town” as parameter.

public class ChangeScene : MonoBehaviour 
{  
    public void loadNextScene (string sceneName) 
    {
        SceneManager.LoadScene(sceneName);
    }
}

Player party

In our game, we want to keep the player units data saved even when changing scenes. In order to do so, we are going to create a PlayerParty persistent object, which won’t be destroyed when changing scenes. You will also need to properly set its position so that it will be created in the correct position in Battle Scene.

Stored data for the player party.

In order to keep the PlayerParty alive when changing scenes, we are going to use the following script, called StartBattle. This script keeps the object from being destroyed when changing scenes in the Start method. It also adds a callback when a new scene is loaded and set the object as inactive, so that it won’t be shown in the title screen.

The configured callback (OnSceneLoaded) checks if the current loaded scene is the Title scene. If so, the PlayerParty object must be destroyed, to avoid duplicates. Otherwise, it should be set as active if the current scene is the Battle scene.

public class StartBattle : MonoBehaviour 
{
    // Use this for initialization
    void Start () 
    {
        DontDestroyOnLoad(this.gameObject);
        SceneManager.sceneLoaded += OnSceneLoaded;
        this.gameObject.SetActive (false);
    }

    private void OnSceneLoaded (Scene scene, LoadSceneMode mode) 
    {
        if (scene.name == "Title") 
        {
            SceneManager.sceneLoaded -= OnSceneLoaded;
            Destroy(this.gameObject);
        }
        else
        {
            this.gameObject.SetActive(scene.name == "Battle");
        }
    }
}

Also, the PlayerParty will have two children to represent the player units. So, first let’s create a PlayerUnit prefab with only a few things for now. Later on this tutorial, we are going to add the rest of its behavior.

For now, the PlayerUnit will have only the Sprite Renderer and a script called UnitStats, which will store the stats of each unit, such as: health, mana, attack, magic attack, defense and speed.

public class UnitStats : MonoBehaviour 
{
    public float health;
    public float mana;
    public float attack;
    public float magic;
    public float defense;
    public float speed;
}

The figure below shows the example of one player unit, called MageUnit. In this example the UnitStats script has other attributes, which will be used later (such as Animator and Damage Text Prefab), but you can ignore those attributes for now.

Mage unit prefab with the unit stats script.

By now, you can already try running your game with the Title scene. You can create an empty Town scene only to test the play button.

Title screen for "Unity RPG" game with play button

Town Scene

We will start by creating the Town Scene. So, create a new Scene in your project and call it Town.

Creating our Tilemap

The Town scene will have a tilemap for us to walk around. To begin, let’s download the 2D Tilemap Editor package in the Package Manager (Window > Package Manager).

Installing the 2D Tilemap Editor in the Package Manager.

Then open the Tile Palette window (Window > 2D > Tile Palette). Here, create a new palette and save it in a new folder called Tilemap.

Creating a new palette in the Tile Palette window.

Now we need to go to our tilemap image. Set the “Sprite Mode” to Multiple, the “Pixels Per Unit” to 64, then click “Sprite Editor”.

Here, we want to slice the image up into 20 columns and 12 rows.

Slicing the sprite sheet in the Sprite Editor.

Then we can drag our tileset into the window to create the tiles.

Creating the the tiles by dragging the sprite sheet into the Tile Palette window.

In the Town scene, right click and create a 2D Object > Tilemap.

Creating a new tilemap game object.

Now, we can select a tile and draw it on the tilemap. Let’s create a grass background.

Painting the screen with grass in the tilemap.

In order to layer tiles, we can create a new tilemap for anything above the grass.

Creating another tilemap for the tiles above the grass.

Set the grid child object’s sorting layer to 1.

Create a scene, something like this.

Our final town scene tilemap layout.

Player prefab

Now that we added our town map to Unity, we are going to create a Player prefab. The player will be able to move around the town, and must collide with the collidable Tiles.

So, let’s start by creating a GameObject called Player, adding the correct sprite renderer, a Box Collider 2D and a Rigidbody 2D as shown below. Observe that we need to set the Gravity Scale attribute of the Rigidbody2D as 0, so that the Player won’t be affected by the gravity.

Player object which is going to navigate the town scene.

We also need to create the Player animations. The Player will have four walking animations and four idle animations, one for each direction. So, first, we create all the animations naming them IdleLeft, IdleRight, IdleUp, IldeDown, WalkingLeft, WalkingRight, WalkingUp and WalkingDown.

The next thing we need is the player animator. So, we create a new animator called PlayerAnimator and add all the created animations to it. Once we add the animator to the Player object in the inspector, we can create its animations using the Unity animation window and the player spritesheet. The figure below shows the example of the WalkingUp animation.

WalkingUp animation for the player which will affect their SpriteRenderer's sprite property.

Now we need to configure the animation transitions in the player animator. The animator will have two paremeters: DirectionX and DirectionY, which describes the current direction of the player movement. For example, if the player is moving to the left, DirectionX is equal to -1, while DirectionY is equal to 0. Those parameters will be correctly set later in a movement script.

Each idle animation will have a transition to each walking animation. The direction parameters should have the values according to the animation direction. For example, the Idle Left animation will change to Walking Left if DrectionX is equal to -1. Also, each walking animation will have a transition for its correspondent idle animation. Finally, if the player changes its walking direction without stopping, we need to update the animation. So, we need to add transitions between the walking animations as well.

In the end, the player animator should look like the figure below. The next figures show examples of transitions between animations (IdleLeft -> WalkingLeft and WalkingLeft -> IdleLeft).

The player animator layout. Connecting the animation states with transitions which are determined by parameters.

Animator transition between the IdleLeft and WalkingLeft animation.

Animator transition between the WalkingLeft and IdleLeft animation states.

Now let’s create the PlayerMovement script. All movement happens in the FixedUpdate method. We use the horizontal and vertical axis inputs to check if the player should move horizontally or vertically. The player can move to a given direction if it is not already moving to the opposite direction. For example, it can move to the left if it is not already moving to the right. We do that for both vertical and horizontal directions. When moving to a given direction, we need to set the animator parameters. In the end, we apply the velocity to the Player Rigidbody2D.

public class PlayerMovement : MonoBehaviour 
{	
    [SerializeField]
    private float speed;

    [SerializeField]
    private Animator animator;

    void FixedUpdate () 
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector2 currentVelocity = gameObject.GetComponent<Rigidbody2D>().velocity;

        float newVelocityX = 0f;

        if(moveHorizontal < 0 && currentVelocity.x <= 0) 
        {
            newVelocityX = -speed;
            animator.SetInteger("DirectionX", -1);
        } 
        else if(moveHorizontal > 0 && currentVelocity.x >= 0) 
        {
            newVelocityX = speed;
            animator.SetInteger("DirectionX", 1);
        } 
        else 
        {
            animator.SetInteger("DirectionX", 0);
        }

        float newVelocityY = 0f;

        if(moveVertical < 0 && currentVelocity.y <= 0) 
        {
            newVelocityY = -speed;
            animator.SetInteger("DirectionY", -1);
        } 
        else if(moveVertical > 0 && currentVelocity.y >= 0) 
        {
            newVelocityY = speed;
            animator.SetInteger("DirectionY", 1);
        } 
        else 
        {
            animator.SetInteger("DirectionY", 0);
        }

        gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(newVelocityX, newVelocityY);
    }
}

In the end, the Player prefab should look like the figure below.

Player prefab with the Animator component attached.

For now, you can start your game and try moving the player around the map. Remember to check if the tile collisions are properly working.

What our town scene looks like when we press play.

Starting Battle

The player can start battles by interacting with enemy spawners. The enemy spawner will be an immovable object that,  when touched by the player will switch to another scene called Battle Scene.

Also, the enemy spawner will be responsible for creating the enemy units objects in the Battle Scene. This will be done by creating an EnemyEncounter prefab, with enemy units as children. Like the player units from the Title Scene, for now we are only going to add the UnitStats script and the Sprite Renderer to enemy units. The figure below shows an example of an enemy unit. You can create the EnemyEncounter by creating a new prefab and adding the desired enemy units as children to it. You will also need to properly set its position so that it will be created in the correct position in Battle Scene.

Enemy unit object with the Unit Stats script.

So, let’s create a prefab called EnemySpawner. This prefab will have a collision box and a Rigidbody2D, in order to check for collisions with the Player prefab.

Snake spawner object which spawns a new snake enemy encounter.

Also, it will have a script called SpawnEnemy as below. This script implements the OnCollisionEnter2D method to check for collisions with the Player prefab. We do so by checking if the other object tag is “Player” (remember to properly set the Player prefab tag). If there is a collision, it is going to start the Battle Scene and set a spawning attribute to true.

In order to create the enemy units in the Battle Scene, the script needs as an attribute the enemy encounter prefab, and the enemy spawner must not be destroyed when changing scenes (done in the Start method). When loading a scene (in the OnSceneLoaded method), if the scene being loaded is the Battle Scene, the enemy spawner will destroy itself and will instantiate the enemy encounter if the spawning attribute is true. This way, we can make sure that only one spawner will instantiate the enemy encounter, but all of them will be destroyed.

public class SpawnEnemy : MonoBehaviour 
{
    [SerializeField]
    private GameObject enemyEncounterPrefab;

    private bool spawning = false;

    void Start () 
    {
        DontDestroyOnLoad(this.gameObject);
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    private void OnSceneLoaded (Scene scene, LoadSceneMode mode) 
    {
        if(scene.name == "Battle") 
        {
            if(this.spawning) 
            {
                Instantiate(enemyEncounterPrefab);
            }

            SceneManager.sceneLoaded -= OnSceneLoaded;
            Destroy(this.gameObject);
        }
    }

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

By now, you can try running your game and interacting with the enemy spawner. Try creating an empty Battle Scene to allow changing the scenes.

Snake encounter in the town scene which we can interact with.

Battle Scene

Background and HUD Canvases

Let’s start by creating the canvases that we are going to use for Battle Scene. Similarly to Title Scene, we are going to use one for the background and another for the HUD elements.

The background canvas will be the same as for the Title Scene, so I’m not going to show its creation. The HUD canvas, on the other hand, will need a lot of elements to allow proper player interaction.

First ,we will add an actions menu, which will show the possible actions for the player. This will be an empty object used as parent of all action menu items. Each action menu item, by its turn, will be a button, added as child of the ActionsMenu.

We are going to add three possible actions: attacking with physical attack (PhysicalAttackAction), attacking with magical attack (MagicAttackAction) and running from the battle (RunAction). Each action will have its OnClick event but, for now, we are not going to add it. The figure below shows only the PhysicalAttackAction, since the other ones will only change the source image for now. The source images for those menu items are from the icons Sprite, which was sliced in many icons.

Physical attack action button.

The second menu we are going to add to the HUD canvas is the EnemyUnitsMenu. This menu will be used to show the enemy units, so that the player can choose one to attack. Similarly to the ActionsMenu, it will be an empty object used to group its menu items. However, the enemy menu items will be created by the enemy units, when the Battle scene starts.

In order to make the enemy unit to create its menu item, we need to create the menu item prefab. This prefab will be called TargetEnemy and will be a button. The OnClick callback of this button will be used to select this enemy as the target.

Target enemy button created using Unity's UI.

We need to add two scripts to the EnemyUnit prefab to handle its menu item: KillEnemy and CreateEnemyMenuItem.

Snake1 object with our components attached.

The KillEnemy script is simple. It will have as an attribute the menu item of this unit, and when the unit is destroyed (OnDestroy method), the menu item must be destroyed too.

public class KillEnemy : MonoBehaviour 
{
    public GameObject menuItem;

    void OnDestroy () 
    {
        Destroy(this.menuItem);
    }
}

Now let’s create the CreateEnemyMenuItem script. This script will be responsible for creating its menu item and setting its OnClick callback. All this is done in the Awake method. First, the menu item position is calculated based on the number of existing items. Then, it is instantiated as children of EnemyUnitsMenu, and the script sets its localPosition and localScale. In the end, it sets the OnClick callback to be the selectEnemyTarget method, and sets the menu item as the one for this unit in KillEnemy.

The selectEnemyTarget method should make the player to attack this unit. However, we don’t have the code to do that now. So, for now we are going to leave this method empty.

public class CreateEnemyMenuItems : MonoBehaviour 
{
    [SerializeField]
    private GameObject targetEnemyUnitPrefab;

    [SerializeField]
    private Sprite menuItemSprite;

    [SerializeField]
    private Vector2 initialPosition, itemDimensions;

    [SerializeField]
    private KillEnemy killEnemyScript;

    // Use this for initialization
    void Awake () 
    {
        GameObject enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");

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

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

        killEnemyScript.menuItem = targetEnemyUnit;
    }

    public void selectEnemyTarget () 
    {
		
    }
}

The final HUD elements we are going to add are those to show the player unit information, such as health and mana. So, we are going to start by creating an empty GameObject called PlayerUnitInformation, to hold all those HUD elements.

Then, we are going to add an image as child of this object called PlayerUnitFace. This element will simply show the face of the current unit. For now, let’s select any unit face.

UI image with the player's warrior face.

The next elements will be the health bar and its text. The health bar will be an image showing the health bar sprite, while the text will show the HP message. Finally we do the same for the mana bar, only changing the sprite and the text message. The figures below show only the health bar, since the mana bar is very similar.

Player unit health bar UI object.

Player unit health text UI element.

By now, your Battle Scene should look like this. This figure corresponds to the Scene viewer, and not the running game, since there is a lot of content we still need to add to properly run the Battle Scene. The righthand figure shows the objects hierarchy in the scene.

What our battle scene now looks like with the UI.

Our Unity hierarchy at the current time.

Units Animations

The next thing we are going to do is creating the units animations. Each unit will have four animatios: Idle, PhysicalAttack, MagicalAttack and Hit. So, let’s start by creating an animator for one of the player units (for example, the MageUnit), and adding it to its correspondent prefab.

Player unit object with the unit stats and animator component.

Now, if we select this prefab and open the Animator view, we can configure its animations state machine as below. We are going to create a state for each animation, with Idle being the default one, and all other ones having transitions to Idle when they end.

Player animator, connecting the various animation states.

Magical attack animation state.

Now, we need to create the four animations to add them to their correspondent states. The figure below shows the MagicalAttack animation for MageUnit. You can create all animations following the same process with the animation  view, so I’m not going to show them all. Also, you have to do the same for all units (including the enemy ones).

Mage magical attack animation, changing the sprite over time.

We still need to define when to play those animations. However, we are going to do so when adding more functionalities for the units. For now, the units will only play the Idle animation, as it is the default one.

If you play the game now, it should show the units with the Idle animation. However, remeber you have to play Title Scene and go until the Battle Scene, in order to see the units.

What our final game looks like.

Turn-Based Battle System

The next thing we are going to add to our game is a turn-based battle system. So, let’s start by creating an empty game object with a script called TurnSystem.

Turn system object with the turn system script.

The TurnSystem script will keep a List with the UnitStats script of all units (player and enemy ones). Then, in each turn, it can pop the first element of the list, make the unit act and add it again to the list. Also, it needs to keep the list sorted according to the units acting turns.

This script is shown below. The UnitStats list is created in the Start method. This is done by iterating through all game objects with the tags “PlayerUnit” or “EnemyUnit” (remember to properly tag your objects). For each unit, the script gets its UnitStats script, calculate its next acting turn and add it to the list. After adding all units the list is sorted. Finally, the menus are disabled, since they will be used only on the player turns, and the first turn begins (by calling nextTurn).

The nextTurn method, by its turn, will start by removing the first UnitStats from the list and checking if it is not dead. If the unit is alive, it will calculate its next acting turn in order to add it again to the list. Finally, it will make it act. We still don’t have the acting methods of the units, so we are only going to print a message in the console for now. On the other hand, if the unit is dead, we are simply going to call nextTurn without adding it to the list again.

public class TurnSystem : MonoBehaviour 
{
    private List<UnitStats> unitsStats;

    [SerializeField]
    private GameObject actionsMenu, enemyUnitsMenu;

    void Start ()
    {
        unitsStats = new List<UnitStats>();
        GameObject[] playerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
        
        foreach(GameObject playerUnit in playerUnits) 
        {
            UnitStats currentUnitStats = playerUnit.GetComponent<UnitStats>();
            currentUnitStats.calculateNextActTurn(0);
            unitsStats.Add (currentUnitStats);
        }

        GameObject[] enemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit");

        foreach(GameObject enemyUnit in enemyUnits) 
        {
            UnitStats currentUnitStats = enemyUnit.GetComponent<UnitStats>();
            currentUnitStats.calculateNextActTurn(0);
            unitsStats.Add(currentUnitStats);
        }

        unitsStats.Sort();

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

        this.nextTurn();
    }

    public void nextTurn () 
    {
        UnitStats currentUnitStats = unitsStats [0];
        unitsStats.Remove(currentUnitStats);

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

            currentUnitStats.calculateNextActTurn(currentUnitStats.nextActTurn);
            unitsStats.Add(currentUnitStats);
            unitsStats.Sort();

            if(currentUnit.tag == "PlayerUnit")
            {
                Debug.Log("Player unit acting");
            } 
            else 
            {
                Debug.Log("Enemy unit acting");
            }
        } 
        else 
        {
            this.nextTurn();
        }
    }
}

Before moving on, we need to implement the UnitStats methods we used in TurnSystem, so let’s go back to the UnitStats script.

First, the calculateNextActTurn method is responsible for calculating the next acting turn based on the current one. This is done based on the unit speed, as shown below. Also, we need to make UnitStats to extend the IComparable interface, and implement the CompareTo method, so that we can properly sort the UnitStats list. The CompareTo method will simply compare the acting turn of the two scripts. Finally, we need to implement the isDead getter, which will simply return the dead attribute value. By default, this attribute is false, because the unit is alive at the beginning of the game.

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)
    {
        this.nextActTurn = currentTurn + (int)Math.Ceiling(100.0f / this.speed);
    }

    public int CompareTo (object otherStats)
    {
        return nextActTurn.CompareTo(((UnitStats)otherStats).nextActTurn);
    }

    public bool isDead ()
    {
        return this.dead;
    }
}

For now, you can try playing the game again, to see if the turn message is being properly printed in the console.

Attacking Units

Now that we have our turn-based battle system we are going to allow units to attack each other. First, we are going to create Attack prefabs, which will be used by the units. Then, we are going to add the action scripts of both player and enemy units, so that they can properly attack. When receiving damage, units will show a Text prefab with the damage value.

The Attack prefab will be an inivisible prefab with an script called AttackTarget. This script will describe the attack properties such as attack and defense multipliers and mana cost. Also, the attack will have an owner, which is the unit currently attacking.

First, the script checks if the owner has enough mana to execute the attack. If so, it picks random attack and defense multipliers based on the minimum and maximum values. So, the damage is calculated based on those multipliers and the attack and defense of the units. Observe that, if the attak is a magical attack (this.magicAttack is true), then it will use the magic stat of the unit, otherwise it uses the attack stat.

In the end, the script plays the attack animation, inflicts the damage to the target unit and reduces the mana of the owner accordingly.

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 = this.owner.GetComponent<UnitStats>();
        UnitStats targetStats = target.GetComponent<UnitStats>();

        if(ownerStats.mana >= this.manaCost) 
        {
            float attackMultiplier = (Random.value * (this.maxAttackMultiplier - this.minAttackMultiplier)) + this.minAttackMultiplier;
            float damage = (this.magicAttack) ? attackMultiplier * ownerStats.magic : attackMultiplier * ownerStats.attack;

            float defenseMultiplier = (Random.value * (this.maxDefenseMultiplier - this.minDefenseMultiplier)) + this.minDefenseMultiplier;
            damage = Mathf.Max(0, damage - (defenseMultiplier * targetStats.defense));

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

            targetStats.receiveDamage(damage);

            ownerStats.mana -= this.manaCost;
        }
    }
}

We are going to create two attack prefabs: PhysicalAttack and MagicalAttack, each one with its own multipliers.

Magical attack prefab with the attack target values.

Physical attack prefab with the attack target stats.

Now we need to implement the reiceveDamage method, used in the AttackTarget script. This will be a method from UnitStats that, besides reducing the unit health, it will also show the damage using a Text over the unit’s head.

This method is shown below. First, it will simply reduce the unit health and play the Hit animation. Then, it will create the damage text (using this.damageTextPrefab). Observe that the damage text must be a child of the HUDCanvas, since it is an UI element, and we need to properly set its localPosition and localScale. In the end, if the unit health is less than zero, the script set the unit as dead, change its tag and destroy it.

public void receiveDamage (float damage) 
{
    this.health -= damage;
    animator.Play("Hit");

    GameObject HUDCanvas = GameObject.Find("HUDCanvas");
    GameObject damageText = Instantiate(this.damageTextPrefab, HUDCanvas.transform) as GameObject;
    damageText.GetComponent<Text>().text = "" + damage;
    damageText.transform.localPosition = this.damageTextPosition;
    damageText.transform.localScale = new Vector2(1.0f, 1.0f);

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

Now we can already implement the act method of the units. An enemy unit will always attack a random enemy with the same attack. This attack will be an attribute in EnemyUnitAction. In the Awake method we are going to create a copy of it for the unit and properly set its owner. We need to create a copy since we want each unit to have its own attack object instance.

Then, the act method will pick a random target and attack it. The findRandomTarget method, by its turn, will start by listing all possible targets given their tags (for example, “PlayerUnit”). If there is at least one possible target in this list, it will generate a random index to pick the target.

public class EnemyUnitAction : MonoBehaviour 
{
    [SerializeField]
    private GameObject attack;

    [SerializeField]
    private string targetsTag;

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

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

        if(possibleTargets.Length > 0) 
        {
            int targetIndex = Random.Range(0, possibleTargets.Length);
            GameObject target = possibleTargets [targetIndex];

            return target;
        }

        return null;
    }

    public void act () 
    {
        GameObject target = findRandomTarget();
        this.attack.GetComponent<AttackTarget>().hit(target);
    }
}

Player units, by their turn, will have two different attacks: physical and magical. So, in the Awake method we need to properly instantiate and set the owner of these two attacks. Also, we are going to set the current attack as the physical one by default.

Then, the act method will receive as parameter the target unit and will simply attack it.

public class PlayerUnitAction : MonoBehaviour 
{
    [SerializeField]
    private GameObject physicalAttack;

    [SerializeField]
    private GameObject magicalAttack;

    private GameObject currentAttack;

    void Awake () 
    {
        this.physicalAttack = Instantiate(this.physicalAttack, this.transform) as GameObject;
        this.magicalAttack = Instantiate(this.magicalAttack, this.transform) as GameObject;

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

        this.currentAttack = this.physicalAttack;
    }

    public void act (GameObject target) 
    {
        this.currentAttack.GetComponent<AttackTarget>().hit(target);
    }
}

Now, we can already call the enemy unit act method in the TurnSystem script. We still can’t do the same for player units, since we still need to properly select the current unit and its attack. This is the next thing we are going to do.

public void nextTurn () 
{
    UnitStats currentUnitStats = unitsStats [0];
    unitsStats.Remove(currentUnitStats);
    
    if(!currentUnitStats.isDead()) 
    {
        GameObject currentUnit = currentUnitStats.gameObject;

        currentUnitStats.calculateNextActTurn(currentUnitStats.nextActTurn);
        unitsStats.Add(currentUnitStats);
        unitsStats.Sort();

        if(currentUnit.tag == "PlayerUnit") 
        {
            Debug.Log("Player unit acting");
        } 
        else 
        {
            currentUnit.GetComponent<EnemyUnitAction>().act();
        }
    } 
    else 
    {
        this.nextTurn();
    }
}

Selecting Unit and Action

We need to properly select the current player unit each turn. This will be done by adding the following script (SelectUnit) to the PlayerParty object. This script will need references to the battle menus, so when the Battle scene is loaded it is going to set them.

Then, we need to implement three methods: selectCurrentUnit, selectAttack and attackEnemyTarget. The first one will set a unit as the current one, enable the actions menu, so that the player can choose an action, and update the HUD to show the current unit face, health and mana (this last method will be implemented later).

The selectAttack method, by its turn, will call selectAttack for the current unit, and will change the current menu, by disabling the actions menu and enabling the enemies menu. The selectAttack method also needs to be implemented in the PlayerUnitAction script. This way, now that the player has selected an attack, it can select the target.

Finally, the attackEnemyTarget will disable both menus and call the act method for the current unit, with the selected enemy as the target.

public class SelectUnit : MonoBehaviour 
{
    private GameObject currentUnit;

    private GameObject actionsMenu, enemyUnitsMenu;

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

    private void OnSceneLoaded (Scene scene, LoadSceneMode mode) 
    {
        if(scene.name == "Battle") 
        {
            this.actionsMenu = GameObject.Find("ActionsMenu");
            this.enemyUnitsMenu = GameObject.Find("EnemyUnitsMenu");
        }
    }

    public void selectCurrentUnit (GameObject unit) 
    {
        this.currentUnit = unit;
        this.actionsMenu.SetActive(true);
    }

    public void selectAttack (bool physical) 
    {
        this.currentUnit.GetComponent<PlayerUnitAction>().selectAttack(physical);

        this.actionsMenu.SetActive(false);
        this.enemyUnitsMenu.SetActive(true);
    }

    public void attackEnemyTarget (GameObject target) 
    {
        this.actionsMenu.SetActive(false);
        this.enemyUnitsMenu.SetActive(false);

        this.currentUnit.GetComponent<PlayerUnitAction>().act(target);
    }
}
public class PlayerUnitAction : MonoBehaviour 
{
    [SerializeField]
    private GameObject physicalAttack;

    [SerializeField]
    private GameObject magicalAttack;

    private GameObject currentAttack;

    public void selectAttack (bool physical) 
    {
        this.currentAttack = (physical) ? this.physicalAttack : this.magicalAttack;
    }
}

Now, we need to properly call all those three methods. The first one (selectCurrentUnit) will be called in TurnSystem, when it is a player unit turn.

public void nextTurn () 
{
    UnitStats currentUnitStats = unitsStats [0];
    unitsStats.Remove(currentUnitStats);

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

        currentUnitStats.calculateNextActTurn(currentUnitStats.nextActTurn);
        unitsStats.Add(currentUnitStats);
        unitsStats.Sort();

        if(currentUnit.tag == "PlayerUnit") 
        {
            this.playerParty.GetComponent<SelectUnit>().selectCurrentUnit(currentUnit.gameObject);
        } 
        else 
        {
            currentUnit.GetComponent<EnemyUnitAction>().act();
        }
    } 
    else 
    {
        this.nextTurn();
    }
}

The second one (selectAttack), will be called by the PhysicalAttackAction and MagicalAttackAction buttons in the HUDCanvas. Since the PlayerParty object is not from the same scene as these buttons, we can’t add the OnClick callbacks in the inspector. So, we are going to do that using the following script (added to those buttons objects), which will add the callback in the Start method. The callback will simply call the selectAttack method from SelectUnit. This same script should be added to both buttons, only changing the “physical” attribute.

public class AddButtonCallback : MonoBehaviour 
{
    [SerializeField]
    private bool physical;

    // Use this for initialization
    void Start () 
    {
        this.gameObject.GetComponent<Button>().onClick.AddListener(() => addCallback());
    }

    private void addCallback () 
    {
        GameObject playerParty = GameObject.Find("PlayerParty");
        playerParty.GetComponent<SelectUnit>().selectAttack(this.physical);
    }
}

Physical attack action button to attack the enemy.

Magical attack action button to magically attack the enemy.

The third method (attackEnemyTarget) will be called from the enemy unit menu item. When creating the CreateEnemyMenuItems script, we left the selectEnemyTarget (which is the button callback) empty. Now, we are going to implement it. This method is going to find the PlayerParty object and call its attackEnemyTarget method.

public void selectEnemyTarget () 
{
    GameObject partyData = GameObject.Find("PlayerParty");
    partyData.GetComponent<SelectUnit>().attackEnemyTarget(this.gameObject);
}

Finally, now we need to update the HUD to show the current unit face, health and mana.

We are going to use the following script to show the unit health and mana. This script will start its initial localScale in the Start method. Then, in the Update method it will update the localScale according to the current stat value of the unit. Also, it will have a method do change the current unit being showed and an abstract method to retrieve the current stat value.

public abstract class ShowUnitStat : MonoBehaviour 
{
    [SerializeField]
    protected GameObject unit;

    [SerializeField]
    private float maxValue;

    private Vector2 initialScale;

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

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

    public void changeUnit (GameObject newUnit)
    {
        this.unit = newUnit;
    }

    abstract protected float newStatValue();
}

Instead of directly using this script, we are going to create two other ones that specialize it, implementing the abstract method: ShowUnitHealth and ShowUnitMana. The only method in those two scripts will be newStatValue, which will return the correct unit stats (health or mana).

public class ShowUnitHealth : ShowUnitStat 
{
    override protected float newStatValue () 
    {
        return unit.GetComponent<UnitStats>().health;
    }
}
public class ShowUnitMana : ShowUnitStat 
{
    override protected float newStatValue () 
    {
        return unit.GetComponent<UnitStats>().mana;
    }
}

Now we can add those two scripts to the health and mana bar objects. Another thing to do is to change their Pivot in the X coordinate to be zero, so that it will change the scale only on the right side of the bar.

Player unit health bar UI element.

Player unit mana bar UI element.

Finally, we need to call the changeUnit method in those scripts when the current unit changes. This will start in the selectCurrentUnit method of SelectUnit. After setting the actionsMenu as active, it will call a method called updateHUD for the current unit.

public void selectCurrentUnit (GameObject unit) 
{
    this.currentUnit = unit;
    this.actionsMenu.SetActive(true);
    this.currentUnit.GetComponent<PlayerUnitAction>().updateHUD();
}

The updateHUD method, by its turn, will start by setting the sprite of the PlayerUnitFace object to be the current unit face (saved as an attribute of PlayerUnitAction). Then, it will set itself as the current unit in both ShowUnitHealth and ShowUnitMana.

[SerializeField]
private Sprite faceSprite;

public void updateHUD () 
{
    GameObject playerUnitFace = GameObject.Find("PlayerUnitFace") as GameObject;
    playerUnitFace.GetComponent<Image>().sprite = this.faceSprite;

    GameObject playerUnitHealthBar = GameObject.Find("PlayerUnitHealthBar") as GameObject;
    playerUnitHealthBar.GetComponent<ShowUnitHealth>().changeUnit(this.gameObject);

    GameObject playerUnitManaBar = GameObject.Find("PlayerUnitManaBar") as GameObject;
    playerUnitManaBar.GetComponent<ShowUnitMana>().changeUnit(this.gameObject);
}

By now, you can try playing the game to see if you can select different actions, and if the stats are being correctly updated. The only action from the menu that we still have to implement is the Run action.

What the final unity rpg game looks like.

Finishing the Battle

We still have to add ways of finishing the battle. There are three ways of doing that:

  1. All enemy units are dead, and the player has won the battle
  2. All player units are dead, and the player has lost the battle
  3. The player ran from the battle

If the player wins the battle, it will receive a reward from the enemy encounter. In order to do that we are going to use the following script, which will be added to the enemy encounter object. In the Start method, it will set the enemy encounter in the TurnSystem object. Then, the collectReward method (which will be called from TurnSystem), will equally divide the encounter experience among all living player units.

public class CollectReward : MonoBehaviour 
{
    [SerializeField]
    private float experience;

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

    public void collectReward () 
    {
        GameObject[] livingPlayerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
        float experiencePerUnit = this.experience / (float)livingPlayerUnits.Length;
        
        foreach(GameObject playerUnit in livingPlayerUnits) 
        {
            playerUnit.GetComponent<UnitStats>().receiveExperience(experiencePerUnit);
        }

        Destroy(this.gameObject);
    }
}

Snake enemy encounter prefab with a collect reward script.

Now we need to implement the receiveExperience method used in collectReward. This will be a method from UnitStats used only to save the received experience. This can be used later to implement a level system in the game, but we are not going to do that in this tutorial.

public void receiveExperience (float experience) 
{
    this.currentExperience += experience;
}

Finally, let’s call the collectReward method in TurnSystem. We are going to change the nextTurn method to check if there are still living enemy units, by finding the objects with the “EnemyUnit” tag. Remember that when a unit dies, we change its tag to “DeadUnit”, so that it won’t be found by this method. If there are no remaining enemy units, it calls the collectReward method for the enemy encounter, and go backs to the Town scene.

On the other hand, if there are no remaining player units, that means the player has lost the battle, so the game goes back to the Title scene.

public void nextTurn () 
{
    GameObject[] remainingEnemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit");
    
    if(remainingEnemyUnits.Length == 0) 
    {
        this.enemyEncounter.GetComponent<CollectReward>().collectReward();
        SceneManager.LoadScene("Town");
    }

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

    UnitStats currentUnitStats = unitsStats [0];
    unitsStats.Remove(currentUnitStats);

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

        currentUnitStats.calculateNextActTurn(currentUnitStats.nextActTurn);
        unitsStats.Add(currentUnitStats);
        unitsStats.Sort();

        if(currentUnit.tag == "PlayerUnit") 
        {
            this.playerParty.GetComponent<SelectUnit>().selectCurrentUnit(currentUnit.gameObject);
        }
        else
        {
            currentUnit.GetComponent<EnemyUnitAction>().act();
        }
    } 
    else 
    {
        this.nextTurn();
    }
}

The last way of finishing a battle is by running from it. This can be done by selecting the run action in the actions menu. So, we need to attach the script below to the run button, and add its OnClick callback.

The RunFromBattle script will have a tryRunning method. This method will generate a random number between 0 and 1, and compare it with a runningChance attribute. If the generated random number is less than the running chance, the player successfully avoids the battle, and goes back to the Town scene. Otherwise, the next turn starts.

public class RunFromBattle : MonoBehaviour 
{
    [SerializeField]
    private float runnningChance;

    public void tryRunning () 
    {
        float randomNumber = Random.value;

        if(randomNumber < this.runnningChance) 
        {
            SceneManager.LoadScene("Town");
        } 
        else 
        {
            GameObject.Find("TurnSystem").GetComponent<TurnSystem>().nextTurn();
        }
    }
}

Run action button UI element which will make us run away.

Finally, by now you should have everything working. Try playing battles until the end to check if everything is working. Now you can also try adding different enemy encounters and tuning some game parameters, such as units stats and attack multipliers.

Also, try adding things that could not have been covered in the tutorial, such as more intelligent enemies and a level system. You might also consider mastering techniques for mobile development and optimizing your game for use on a smartphone!

Of course, you may wish to explore other genres as well to expand your skills further. So don’t be afraid to seek out other online courses or even find Unity courses to integrate into the classroom.

The sky is the limit here, so don’t be afraid to experiment!

Final appearance of RPG townFinal appears of the RPG battle screen

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Create a Third Person Camera for Action RPGs in Unreal https://gamedevacademy.org/unreal-engine-camera-tutorial/ Sun, 06 Nov 2022 01:00:27 +0000 https://coding.degree/?p=472 Read more]]>

You can access the full course here: Build an Action RPG in Unreal Engine

Player Setup

Creating the Player Blueprint

In the Blueprints folder, create a new blueprint of type Character called Player.

Player blueprint in Unreal Engine Content Browser

Double-click to open it up inside of the blueprint editor. You’ll see that we have a number of default components. These help us out with creating our player. To begin, select the Mesh component.

  • Set the Skeletal Mesh to PlayerModel
  • Set the Location to 0, 0, -90
  • Set the Rotation to 0, 0, -90

Character in Unreal Engine with model added

Next we’ll create the damage collider. Create a new Box Collision component as a child of the mesh component. Rename it to DamageCollider.

Damage Collider added to Player's Components

  • Set the Location to -20, 90, 110
  • Set the Box Extents to 25, 32, 32
  • Set the Collision Presets to Trigger (not pictured)

Unreal Engine collider added for damage detection

Now we need to create our camera which will follow the player. This will be done by using a spring arm. This is a component which connects the camera to the player and also allows for collision detection. Create a new Spring Arm component.

  • Set the Location to 0, 0, 70
  • Set the Rotation to 0, -20, 0

Player in Unreal Engine with SpringArm component added

As a child of the SpringArm component, create a new Camera component.

  • Set the Location to 0, 0, 70
  • Set the Rotation to 0, -20, 0

Camera added to Unreal Engine scene

We can then click compile, save then return to the level editor. In order for the game to know what our player is, we’ll need to create a new blueprint of type GameMode Base called MyGameMode. Open it up and inside, set the Default Pawn Class to Player. Save, compile, then return to the level editor.

Player Blueprint set as Defualt Pawn Class in Unreal

To assign this game mode, go to the Details panel and click on the World Settings tab. Here, set the GameMode Override to MyGameMode.

Unreal Engine World Settings

Now when you press play, you should see the player spawn in, with us looking through the camera.

Camera Setup

Orbiting the Camera

In this lesson, we’re going to set it up so that we can rotate the camera around the player with our mouse. Inside of the Player blueprint, let’s go over to the Event Graph. First, we want to create a new event node called Mouse X. This gets triggered when we move our mouse and it outputs the horizontal axis value.

Plug this into an AddControllerYawInput node like below.

Mouse X attached to Yaw Input in Unreal Engine Blueprint

Compile, save and press play. You’ll see that we can move the mouse horizontally to rotate the player.

Now let’s rotate the camera up and down. We can’t do it like before since this will rotate the player sideways. Instead, we want to set it up like this:

Mouse Y, Rotater, and Spring Arm attached to Local Rotation

One problem with this, is that the camera can rotate all the way around the player. To fix this, we need to clamp the vertical rotation. To begin, we want to set the spring arm rotation after we add to it.

SetRelativeRotation circled in Unreal Engine

To clamp, let’s start by getting the target rotation of the spring arm and breaking it.

Node setup for getting target rotation in Unreal Engine

Connect this to a Clamp Angle node.

  • Set the Min Angle Degrees to 45
  • Set the Max Angle Degrees to 20

Clamp Angle node added in Unreal Engine

Then we can plug that result into the Y of a make rotator node, and plug that into the set rotation node.

Make Rotator Node circled in Unreal Engine

Now you should see the camera rotation is clamped vertically.

 

Transcript

Player Setup

Welcome back everyone. In this lesson we are going to begin to create our Player Blueprint. This is gonna be featuring our Player model, it’s gonna to be featuring the colliders, the camera, everything we need in order to have our Player set up and ready to go.

So inside of our blueprints folder here, I’m gonna right click and create a new blueprint class. This is gonna be of type character, which basically gives us some preset things such as a Capsule Collider, a Mesh, a forward Direction, and also includes a Character movement Component which allows us to easily set up the player movement, the camera rotating, jumping, ground detection, and many other movement related things.

So it will create a character right here and we are gonna call this one player. We can then double click to open this up inside of the Blueprint Editor. I’m gonna dock it to the main window here. And as you can see here, we have a few things set up already for us. We have a capsule component here, which is collider, we have an arrow component, this is this blue arrow right here. And this just defines the forward direction. We have a mesh, which is going to be our Player mesh which we can then animate later on. And the character movement component, which as you can see here in the details panel includes a lot of different options we can tweak in order to find sharing our movement, okay?

So the first thing we’re gonna be doing is setting up a mesh. So I’m gonna select our mesh here, and I’m gonna select the skeletal mesh, and I’m gonna change this to our Player model right here. So there we go. We’ve got our Player model now in here, but it doesn’t really match the bounds or the direction of this capsule, we need to rotate it and move it down a bit. So I’m gonna set the Z location to be negative 90, so it is down in the correct position.

And now we just need to rotate it negative 90 on the Z as well, so it is facing in the correct forward direction it’s facing in its positive X direction luxor, okay? So we’ve got our player mesh there. Now what we need is the damage collider and the damage collider is basically going to be a collider that’s gonna check to see if there are any enemies inside of it when we are attacking.

So as a child of mesh, we can just select mesh here to arrow component and I’m gonna type box collision. And I’ll just call this one our damage collider luxor. And in terms of positioning it, we can just lift it up here, move it forward a bit and have it about there. So over here where we have the box extents, I’m gonna change this to be 25. And let’s also position it to the left a bit since that’s where the weapon is. Make sure it’s around in line like so and there we go.

Okay, so along with this, we also want to make sure that it is not a solid collider it needs to be a trigger that objects can move through. So down the details panel, let’s make sure generate overlap events is enabled. And let’s change the collision presets from overlap all dynamic to trigger okay, there we go.

Now what we can do is set up the camera. And the way we’re gonna do the camera is by attaching it to something known as a spring arm. And a spring arm is a very handy component which basically sets its child object or its child component a fixed direction and distance away from it. So what we can do then, is just rotate the spring arm and the camera is gonna rotate around our player.

So I’m gonna go add component, I’m gonna look for a spring arm. Make sure it is a child of the capsule component and not the mesh. So with this spring arm now, all we need to do is go to the details panel and change a few things.

First of all, we are on the point of orbit not to be around the waist of our player but probably up oops, probably up over near the players head right here. So to drag that up to the head there, we’ll set the wire rotation to be 20. Oh, negative 20 I mean, so we do have a bit of a downwards facing camera when we start off. And apart from this, we can leave everything as it is.

So what we’re gonna do now is as a child of spring arm, we’re gonna add component, we’re gonna look for camera, there we go. So now we got our camera in here, it is going to be right at the end of the spring arm as you can see here.

Now for our camera, what we want to do is move it over just a little bit to the right because since this is gonna be a third person controller, we probably don’t want the camera directly behind the play as that might sort of obstruct the view a bit. So normally what other games do, is they move the camera over to one of the sides a bit. So I’m gonna move this camera to be 60 on the Y location so it’s a bit to the right of the player.

And that is pretty much it. So if you select the spring arm on here, and we press E to get the rotation gizmo, you’ll see that if I rotate it, the camera follows along as well. Okay, so now what we can do is click save, click compile, we can go back to our main level here.

And we can set it up so that when we press play, our Player spawns in because right now if we press play, the play is not there, we just have controlled the default camera anchor, which just allows us to fly around similar to the main viewport.

So what we need to do is create a game mode so that it knows the default things such as the default player to spawn at the started level. So let’s right click here in the blueprint class, we’re gonna create a new blueprint. This one is gonna be a game mode base. And a game mode base basically defines some of the defaults, again such as the player, the default UI, the default multiplayer aspects, okay?

So we’ll go game mode base, I’m gonna call this one my game of mode. We can double click to open this up, this is also a blueprint. So we don’t actually have to add anything here if you do want some sort of global logic for your level, then you can probably add it to the event graph here, but we’re just gonna leave it as it is. And over in the details panel, we want to make sure that we have the default pawn class here. We want to change that our Player right here, okay? That’s all we need to do.

So we can click compile, we can click save, we can close out of the game mode here, I’m also gonna close out our project settings. And in our main level here, let’s go over to the world settings tab, which is inside of the details panel here, and world settings basically, global settings for the current level. So we can change things such as air game mode override. Right now it’s on none which means there’s no game mode active. So let’s select that and choose my game mode.

So now when we press play, the game is gonna look at the game mode and go okay, what is the default player class to spawn? It’s gonna see it is our Player blueprint. So it is gonna spawn the player blueprint in on this player start position right here. So we can press play and there we go.

This is our player blueprint setup, it’s spawning in. Now all we need to do is implement the functionality to actually look around with the mouse rotate the camera and move around with the keyboard. So we are gonna be beginning on setting up the camera orbiting in the next lesson. So I’ll see you all then.

Camera Setup

Welcome back everyone. In this lesson, we are gonna be setting up the camera orbiting system, for app play blueprint here. In the previous lesson, we set up the play blueprint, so it has all the components set up ready to go. We also have this spring arm component, which if we go to the rotation tool, we can rotate it around, which has the camera then orbiting around the player. Okay?

So in this lesson, we’re gonna make it so that whenever we move our mouse, the camera rotates around a player.

So, let’s go to the event graph here, and what we’re gonna do is start off by deleting these three nodes that are here by default, so that we have a blank canvas here, and to begin, we’re gonna set up the horizontal movement. So, when we move the mouse left or right, the camera is gonna rotate left to right around the player.

And to do this, I’m gonna right click, and I’m gonna go mouse X, and you’ll see that we can get mouse events. We want to get the mouse X input event. And what this means, is pretty much whenever the mouse moves, this gets triggered and it sends over an axis value of the current map of the current horizontal mouse movement. Okay? So, this value ranges from negative one to one, negative one, meaning the mouse is moving left, one, meaning the mouse is moving right, and zero, meaning the mouse isn’t moving at all.

But with this, we aren’t actually gonna be rotating the spring arm or the camera, instead we’re going to be moving the entire player, left or right. We’re gonna be rotating them around, because, when we move around, we want the player to always be facing in the forward direction that the camera is.

So, we’re gonna drag off from here, and, we are gonna go to the add controller, your input node right here. And what this does is, this adds a certain value to our control is your input, which is the vertical rotation. So if we plug access value into the value input, that is all we need to do. And this is a node here, that is set up for us by this character movement component. This involves all of the movement, variables and properties that we can modify.

So if we save this compile press play, you should see that when we moved the mouse left and right, the character rotates to face the forward direction. So no matter where we look the player’s always rotating with us as we move the mouse. Okay?

So, we got the left and right movement, but, what about the up and down? Well, that’s a bit different because with this, we are gonna be rotating the spring arm. We don’t want to rotate the entire player, because that will look a bit weird so, we can be irritating the camera up and down. Okay? So, what we’re gonna do for that, is just like getting mouse X.

We now need to get mouse Y, so, mouse events, mouse Y here. And this trick is when we moved the mouse up and down, axis value again ranging from, a one being moving the mouse up, and negative one being moving the mouse down. And, we want to plug this into an add local rotation. Add local rotation. On the spring arm component here. Okay? There we go, creates that.

So, what we’re doing here is, we are gonna add a rotation to the spring arm, and that rotation is going to be along the Y axis. And the Y axis, if we go to the viewpoint here, select the spring on. The Y axis, is this green one here. So we can move this up and down, so the camera goes like so.

Okay. So, in event graph, to do that, what we’re gonna do is right click, and create a new node called make rotator. This basically creates a rotation for us, which we can then plug into, this add local rotation node like so, and X value, we are gonna be plugging into the Y axis here, on the micro data node. So, basically it was sending over a delta rotation, which is gonna be added on to the existing spring arm rotation.

So, if we press play, you’ll see that we can move left and right, but we can also move up and down. Like so. But something you may notice, is that if we keep moving down, our camera just keeps going around, and we can actually go 360 degrees, which isn’t probably what you want.

And something else you may also notice, is that when the camera goes down, and it hits the ground, it sort of moves towards the player. This is really cool, as the spring arm already has included with it, basically detecting if there’s anything between, the start of the spring arm and the camera. So if there’s anything between it, it pretty much snaps the camera, so, it is always looking at the plan. Nothing can ever get in the way between the camera, and the player. Which is really good. Okay?

But we still need to fix the issue of actually being able to rotate all the way around like this, as it may be very disorientating, to use as the player. So, what we need to do for this is clamp the rotation. And clamping the rotation basically means, we get the Y axis here, the Y rotation, and, we want to make sure that it never goes below a certain number, and never goes above a certain number.

So to do this, I’m gonna plug this add local rotation node, into a set relative rotation for the spring arm. So after we add the rotation to this spring arm, we then want to set it, so that is, make sure it’s in between two certain values. So over here, what we’re then gonna do, is create the get targets rotation node on the spring arm. And this year basically just returns to us the rotation of the spring arm currently.

So, we wanna get that. And then we want to plug this rotation here into a break rotator node. And what this does, is pretty much the exact opposite of make rotator. Instead of creating a rotation, it gets a rotation and breaks it up into each of the individual axis, which we can use. Now, since a vertical rotations are only dependent on the Y axis, we’re gonna get this, and we are gonna plug this into a clamp angle node here.

Okay. And this clamp angle node, has a few things. First of all, it has the actual angle that we are inputting into it, which is our Y axis. And then we have a min angle degrees, and a max angle degrees. And these are basically the min and max values that these angle can possibly be. So, the minimum rotation, we’re gonna have it at about 45 degrees, and the max rotation, we are gonna have it at 20. Okay. You might wanna tweak these numbers a bit, as we continue on, as you may want it a bit higher, you may want it a bit lower. Okay. So we got this value here.

Now we need to make it into a rotator again, so we can plug it into this set relative rotation node, so we’re gonna put this into make rotator, we actually wanna delete this connection, and make sure it was connected to the Y axis here. And, then we can just plug that into the new rotation input, on the set relative rotation node. And there we go. So this is pretty much it, in order to set it up so that it clamps the rotation. So it can’t get too high, or too low, let’s now press play and see if it works.

So here we go, we can rotate left and right. And if I moved down, you’ll see that it stops, when I reach here. I can no longer move the camera down anymore. I can move it up and it stops here. So I can’t move it up anymore either. So there we go. We’ve got our camera rotation set up. We can rotate left or right, we can rotate up and down, and, that is all good.

So, in the next lesson, we are going to be looking at actually setting up app play movement. So that we can actually start moving around, jumping, and then later on, setting up the abilities to actually attack.

Okay. Now before we go real quick, I’m gonna probably put these in some comments, so that they’re a bit neater. So, I’m gonna get these here, select these two nodes, right click, go create comment from selection, and I’m gonna call this one our camera, rotate, (keyboard clicking) camera rotates, horizontal. (keyboard clicking) Okay. We can then readjust these, like so, shrink this down a bit. It’s really good practice to actually, comment your nodes as later on, once you have many, many new nodes in your project. It may be quite hard to understand what you shouldn’t do, especially if they’re all messy, like this right here. So I’m just gonna tidy them up a bit.

We can then select them again, and, I’m gonna right click, create comment from selection, and this one is going to be called, our camera rotate vertical. All right. We can always select these again, readjust them to a position where we want them, and, there we go.

Okay. So yeah, overall, make sure you do comment your nodes, we’ll be doing this again in the future, for a movement for our jumping. Just so you can see what each of the different segments here are, at a quick glance. Okay. So, thank you for watching. And, I’ll see you all in the next lesson.

Interested in continuing? Check out the full Build an Action RPG in Unreal Engine course, which is part of our Unreal Game Development Mini-Degree.

]]>
How to Set Up Crops in Unity for Farming Games https://gamedevacademy.org/unity-farm-crop-tutorial/ Tue, 09 Aug 2022 09:59:24 +0000 https://gamedevacademy.org/?p=16425 Read more]]> Since the success of Stardew Valley, farming sims are more popular than ever before – and it doesn’t take much development experience to make them.

In this Unity tutorial, we’re going to cover how to set up the most essential component of farming-based games: planting crops. This tutorial will be based around a grid-based, top-down 2D project, but many of these concepts can be retrofitted as needed for 3D as well.

While some basic Unity experience is required, including knowledge of how to set up top-down 2D player characters, these explanations will be very beginner-friendly!

If you’re ready to start learning farming mechanics, let’s dive into Unity!

Project Files

While you’ll need to set up your own Unity project, we have included a full copy of the code files used in this tutorial, as well as sprite assets used.

Download Project Files Here

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Setting up Crop Data

To start our tutorial off, we’re first going to set up our crop data and our game manager that will control the entire aspect of how crops are planted. We will be setting up our data based around a top-down, 2D game with grid-based, interactable tiles.

Data Setup

To start, let’s create a new C# script called “CropData”. This script is going to contain all the information specific to the crop we grow.

This script isn’t going to be attached to any GameObject. Instead, we want to create an asset for each of the different types of crop. To do this, simply replace MonoBehaviour with ScriptableObject and use the CreateAssetMenu property to create a menu item for it.

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

[CreateAssetMenu(fileName = "Crop Data", menuName = "New Crop Data")]
public class CropData : ScriptableObject
{
}

This will allow us to right-click on the Project window to create a new Crop Data asset.

Unity Create Menu showing New Crop Data menu item

We’re going to create one for “Wheat”.

Crops will display different sprites depending on the number of days it has grown for. Let’s declare the following variables inside the script to track these sprites, as well as a few other details related to the crop (such as sell price):

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

[CreateAssetMenu(fileName = "Crop Data", menuName = "New Crop Data")]
public class CropData : ScriptableObject
{
    public int daysToGrow;
    public Sprite[] growProgressSprites;
    public Sprite readyToHarvestSprite;

    public int purchasePrice;
    public int sellPrice;
}

Now we can save the script and go back to the Editor to start filling out the crop data for Wheat. You can fill whatever data you want, but we used:

  • Days to Grow: 6
  • Grow Progress Sprites & Ready To Harvest Sprite: With the course files, we includes our wheat crop sprite which we sliced from a single sprite.
  • Purchase Price: 20
  • Sell Price: 35

Unity Inspector showing crop data for Wheat

GameManager

To manage the crops, we will create a new C# script called “GameManager“. We need to know primarily what the current day is, how much money we have, and what crop we want to plant.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public CropData selectedCropToPlant;
}

We can set up a Singleton for this script so that we can easily access this script from other scripts as well.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public CropData selectedCropToPlant;

    // Singleton
    public static GameManager instance;

    void Awake ()
    {
        // Initialize the singleton.
        if(instance != null && instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
        }
    }
}

Now we want to implement the following functionalities:

  • Whenever a new day takes over, we will trigger an event to notify the crops to grow.
  • We can purchase, plant, and harvest crops

Let’s create some dummy functions first:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public int cropInventory;

    public CropData selectedCropToPlant;

    public event UnityAction onNewDay;

    // Singleton
    public static GameManager instance;

    void Awake ()
    {
        // Initialize the singleton.
        if(instance != null && instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
        }
    }

    // Called when a crop has been planted.
    // Listening to the Crop.onPlantCrop event.
    public void OnPlantCrop (CropData cop)
    {
    }

    // Called when a crop has been harvested.
    // Listening to the Crop.onCropHarvest event.
    public void OnHarvestCrop (CropData crop)
    {
    }

    // Called when we want to purchase a crop.
    public void PurchaseCrop (CropData crop)
    {
    }

    // Do we have enough crops to plant?
    public bool CanPlantCrop ()
    {
    }

    // Called when the buy crop button is pressed.
    public void OnBuyCropButton (CropData crop)
    {
    }
}

Crop Script

Next, let’s set up the ability to actually grow our crops.

Crop Variables

Let’s create a new C# script called “Crop“. This is going to spawn in the crops once we put the seeds down.

First of all, we need to declare the variables and make sure to set up UnityEngine.Events so we can automatically trigger events when we plant or harvest a crop:

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

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;
}

Harvesting & Watering

We can then keep track of the number of days that the crop has been planted (i.e. Crop Progress), by subtracting plantDay from GameManager.curday.

Let’s return a boolean to check if the crop is old enough for harvesting.

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

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Now, when we harvest the crop, we’re going to invoke the onHarvestCrop event and destroy the crop gameObject. At the same time, we’ll also add our water function, which simply changes daysSinceLastWatered to 0.

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

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Note that the question mark next to the unity event (onHarvestCrop?.Invoke) allows us to invoke it only if we have functions listening to the event. This effectively prevents errors from popping up.

When the crop has progressed, we can check if the crop is ready to be harvested. If it is, then we should change the sprite of the crop.

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

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when the crop has progressed.
    void UpdateCropSprite ()
    {
        int cropProg = CropProgress();

        if(cropProg < curCrop.daysToGrow)
        {
            sr.sprite = curCrop.growProgressSprites[cropProg];
        }
        else
        {
            sr.sprite = curCrop.readyToHarvestSprite;
        }
    }

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

New Day

When a new day takes over, we will increment the daySinceLastWatered, and destroy the crop if it has been more than 3 days.

If it hasn’t, then we can call UpdateCropSprite.

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

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when a new day ticks over.
    public void NewDayCheck ()
    {
        daysSinceLastWatered++;

        if(daysSinceLastWatered > 3)
        {
            Destroy(gameObject);
        }

        UpdateCropSprite();
    }

    // Called when the crop has progressed.
    void UpdateCropSprite ()
    {
        int cropProg = CropProgress();

        if(cropProg < curCrop.daysToGrow)
        {
            sr.sprite = curCrop.growProgressSprites[cropProg];
        }
        else
        {
            sr.sprite = curCrop.readyToHarvestSprite;
        }
    }

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Initial Values

Finally, we will set up the initial values for the variables when we first plant the crop (i.e. curCrop, plantDay, daysSinceLastWatered).

Once they’re set, we can update the crop sprite and invoke the onPlantCrop event.

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

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when the crop has been planted for the first time.
    public void Plant (CropData crop)
    {
        curCrop = crop;
        plantDay = GameManager.instance.curDay;
        daysSinceLastWatered = 1;
        UpdateCropSprite();

        onPlantCrop?.Invoke(crop);
    }

    // Called when a new day ticks over.
    public void NewDayCheck ()
    {
        daysSinceLastWatered++;

        if(daysSinceLastWatered > 3)
        {
            Destroy(gameObject);
        }

        UpdateCropSprite();
    }

    // Called when the crop has progressed.
    void UpdateCropSprite ()
    {
        int cropProg = CropProgress();

        if(cropProg < curCrop.daysToGrow)
        {
            sr.sprite = curCrop.growProgressSprites[cropProg];
        }
        else
        {
            sr.sprite = curCrop.readyToHarvestSprite;
        }
    }

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Event Listeners

We now need to register listeners for the events we made. Right now the events are invoked, but there are no functions listening to them.

Let’s open up the GameManager script, and subscribe to the events inside OnEnable.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public int cropInventory;

    public CropData selectedCropToPlant;

    public event UnityAction onNewDay;

    // Singleton
    public static GameManager instance;

    void OnEnable ()
    {
        Crop.onPlantCrop += OnPlantCrop;
        Crop.onHarvestCrop += OnHarvestCrop;
    }

    void OnDisable ()
    {
        Crop.onPlantCrop -= OnPlantCrop;
        Crop.onHarvestCrop -= OnHarvestCrop;
    }
  ...
}

Here we can define what to execute when onPlantCrop and onHarvestCrop are invoked.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public int cropInventory;

    public CropData selectedCropToPlant;

    public event UnityAction onNewDay;

    // Singleton
    public static GameManager instance;

    void OnEnable ()
    {
        Crop.onPlantCrop += OnPlantCrop;
        Crop.onHarvestCrop += OnHarvestCrop;
    }

    void OnDisable ()
    {
        Crop.onPlantCrop -= OnPlantCrop;
        Crop.onHarvestCrop -= OnHarvestCrop;
    }


    // Called when a crop has been planted.
    // Listening to the Crop.onPlantCrop event.
    public void OnPlantCrop (CropData cop)
    {
        cropInventory--;
    }

    // Called when a crop has been harvested.
    // Listening to the Crop.onCropHarvest event.
    public void OnHarvestCrop (CropData crop)
    {
        money += crop.sellPrice;
    }
}

Planting Crops

Last but not least, we need to be able to plant crops, so we will set up an Interact function that can be called by the player whenever they interact with the tiles we can plant on.

Tile Interaction

On any script that is controlling your field tiles, add in the Interact function (which will ultimately be invoked by your player character in whatever manner you choose):

// Called when the player interacts with the tile.
public void Interact ()
{
    if(!tilled)
    {
        Till();
    }
    else if(!HasCrop() && GameManager.instance.CanPlantCrop())
    {
        PlantNewCrop(GameManager.instance.selectedCropToPlant);
    }
    else if(HasCrop() && curCrop.CanHarvest())
    {
        curCrop.Harvest();
    }
    else
    {
        Water();
    }
}

After this, we’ll create a new function called PlantNewCrop, which takes a parameter of CropData (which is the crop we want to plant).

Planting should only occur if the tile is tilled.

// Called when we interact with a tilled tile and we have crops to plant.
void PlantNewCrop (CropData crop)
{
    if(!tilled)
        return;

    curCrop = Instantiate(cropPrefab, transform).GetComponent<Crop>();
    curCrop.Plant(crop);

    GameManager.instance.onNewDay += OnNewDay;
}

Note that we’re subscribing to the GameManager’s OnNewDay event here rather than OnEnable, because not every tile needs to listen to the event. We want to subscribe to it once we have a crop planted.

Next, we’ll create a function for Till and Water, where we will switch the tile’s sprite.

// Called when we interact with a grass tile.
void Till ()
{
    tilled = true;
    sr.sprite = tilledSprite;
}

// Called when we interact with a crop tile.
void Water ()
{
    sr.sprite = wateredTilledSprite;

    if(HasCrop())
    {
        curCrop.Water();
    }
}

If we no longer have any crop on this tile, then we just want to reset the tile and unsubscribe from the OnNewDay event.

If we do have a crop planted and a new day occurred, then we need to trigger the crop’s NewDayCheck:

// Called every time a new day occurs. 
// Only called if the tile contains a crop.
void OnNewDay ()
{
    if(curCrop == null)
    {
        tilled = false;
        sr.sprite = grassSprite;

        GameManager.instance.onNewDay -= OnNewDay;
    }
    else if(curCrop != null)
    {
        sr.sprite = tilledSprite;
        curCrop.NewDayCheck();
    }
}

Finishing Up

Let’s save this script and go to the Editor to test it out.

Make sure that the Crop script has the sprite renderer assigned:

Unity Inspector showing Crop with the Sprite Renderer

Save the Crop GameObject as a prefab and assign sprites to your tile object. We’ve included an example of our FieldTile script so you can see how we did it, but your results will vary.

Unity showing crop-based Prefabs for tutorial

Unity Inspector showing FieldTile example script

Finally, we can set up the GameManager with the public variables filled in.

Unity Inspector showing farming-based Game Manager

We can now till the ground, water the ground, and plant crops!

Screenshot of farming sim made with Unity

Conclusion

And that covers the basics of setting up farming mechanics for farming sim games! Congratulations for making it through!

As mentioned, farming is very popular, and it can add variety to tried and true genres. However, keep in mind our way is not the only way. Depending on your own game project, you may need to adapt these systems. However, we’ve designed these systems to be expandable and fit in with most top-down, 2D games.

From here, though, you can try out tons of other features using the same fundamentals. Perhaps you want to have livestock, which you can also set up as Scriptable Objects and utilize the Unity events system to also have an invokable Interact function. Or, maybe you want to create a farming sim on an alien world where the crops can be poisonous! The choice is yours!

Regardless, we hope you’ve expanded your horizons with farming, and we wish you the best of luck with your future projects!

Want to learn more about farming sims? Try our complete Construct a Micro-Farming RPG course.

]]>
Free Course – A Guide to 3rd Person Players in Unity https://gamedevacademy.org/3rd-person-player-unity-tutorial/ Wed, 30 Dec 2020 01:00:03 +0000 https://coding.degree/?p=800 Read more]]>

Start creating third-person action RPGs and more by first learning how to set up player movement with orbital camera! You can also extend the material covered here by checking out the full course below!

Action RPG Development for Beginners

About

Created by Daniel Buckley, this mini-course will show you step-by-step how to set up a third-person character controller using simple primitive objects in Unity. You’ll learn key skills including how to prepare the player in Unity, how to add standard movements like walking and jumping, and how to implement features for the camera to orbit around the player. Regardless of what sort of game you want to build, these player scripts will provide a strong foundation as you expand your skills and build your dream game projects!

]]>
Make Games without Coding – Free Unreal Engine Ebook https://gamedevacademy.org/make-games-without-coding-free-unreal-engine-ebook/ Mon, 28 Dec 2020 01:22:48 +0000 https://gamedevacademy.org/?p=2044 Read more]]> We are excited to announce our latest eBook: Unreal Engine Game Development for Beginners

Authored by Unreal Engine expert Daniel Buckley, this eBook explores all there is to know about getting started with Unreal Engine development. You’ll learn not only how to work with the foundations of the engine itself, but also develop several projects from scratch including an FPS game, an action RPG, a road-crossing game, a platfromer, and a puzzle-like game! In addition, you’ll do all this while using the Blueprints Visual Scripting system – meaning no prior coding knowledge is required or needed to create your game projects!

Whether you’ve always wanted to learn Unreal Engine or want to start putting knowledge into practice, this eBook will help you gain the in-demand skills necessary to start building your dream game projects!

Download the eBook here

]]>
Free Ebook – Unity Programming for Human Beings https://gamedevacademy.org/free-ebook-unity-programming-for-human-beings/ Sun, 27 Dec 2020 15:20:07 +0000 https://gamedevacademy.org/?p=4319 Read more]]> We are stoked to announce the launch of our free ebook Unity Programming for Human Beings, authored by game development experts Jesse GloverPablo Farias Navarro, Renan Oliveira, and Tim Bonzon, in collaboration with Daniel Buckley.

In over 230 pages of awesomeness, the book starts from zero and covers all the way to building simple 2D and 3D games with Unity. Some of the topics covered in the course are:

  • Fundamentals of 2D and 3D programming
  • Unity scripting, no prior programming experience required!
  • Shaders
  • How to build your first game in Unity
  • RPGs and multiplayer games
  • Animations

We hope this free ebook helps you gain valuable, real-world skills and we very much look forward to play your games!

This book is provided at no cost in PDF format.

Download the ebook

 

What type of game will you be building in Unity? Share it in the comments!

]]>