Reader small image

You're reading from  Game Development Patterns with Unity 2021 - Second Edition

Product typeBook
Published inJul 2021
Reading LevelBeginner
PublisherPackt
ISBN-139781800200814
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
David Baron
David Baron
author image
David Baron

David Baron is a game developer with over 15 years of experience in the industry. He has worked for some well-known AAA, mobile, and indie game studios in Montreal, Canada. His skill set includes programming, design, and 3D art. As a programmer, he has worked on various games for various platforms, including virtual reality, mobile, and consoles.
Read more about David Baron

Right arrow
Implementing Power-Ups with the Visitor Pattern

In this chapter, we are going to implement a power-up mechanic for our game. Power-ups have been a core ingredient of video games since their early inception. One of the first games that implemented power-ups is Pac-Man from 1980. In the game, you could eat Power Pellets that would give Pac-Man temporary invincibility. Another classic example is the mushrooms in Mario Bros., which made Mario taller and more robust.

The power-up ingredients that we will build will be similar to the classics but with a little more granularity. Instead of having a power-up boost a singular ability of an entity, we can create combos that give out multiple benefits at once. For instance, we could have a power-up named "Protector" that adds durability to the front-facing shield and increments the strength of the primary weapon.

And so, in...

Technical requirements

This chapter is hands-on. You will need to have a basic understanding of Unity and C#. We will be using the following Unity engine and C# language concepts:

  • Interfaces
  • ScriptableObjects

If you are unfamiliar with these concepts, please review them before starting this chapter. The code files for this chapter can be found on https://github.com/PacktPublishing/Game-Development-Patterns-with-Unity-2021-Second-Edition/tree/main/Assets/Chapters/Chapter10.

Check out the following video to see the code in action: https://bit.ly/3eeknGC.

We often use ScriptableObjects in the code examples of this book because when building game systems and mechanics, it is essential to make them easily configurable by non-programmers. The process of balancing systems and authoring new ingredients usually falls under the responsibility of game and level designers. Therefore, we use ScriptableObjects because it offers a consistent way of establishing an authoring pipeline to create...

Understanding the Visitor pattern

The primary purpose of the Visitor pattern is simple once you grasp it; a Visitable object permits a Visitor to operate on a specific element of its structure. This process allows the visited object to acquire new functionality from visitors without being directly modified. This description might seem very abstract at first, but it is easier to visualize if we imagine an object as a structure instead of a closed-off container of data and logic. Therefore, it is possible with the Visitor pattern to traverse an object's structure, operate on its elements, and extend its functionality without modifying it.

Another way to imagine the Visitor pattern in action is by visualizing the bike in our game colliding with a power-up. Like an electronic current, the power-up flows through the inner structure of the vehicle. Components marked as visitable get visited by the power-up, and new functionalities are added, but nothing is modified...

Benefits and drawbacks of the Visitor pattern

I've written a short list of the benefits and drawbacks of using this pattern.

The following are the benefits:

  • Open/Closed: You can add new behaviors that can work with objects of different classes without modifying them directly. This approach follows the object-oriented programming principle of Open/Closed that states that entities should be open for extension but closed for modification.
  •  Single Responsibility: The Visitor pattern can adhere to the single responsibility principle in the sense you can have an object (visitable) that holds the data and another object (visitor) is responsible for introducing specific behaviors.

The following are some of the potential drawbacks:

  • Accessibility: Visitors could lack the necessary access to specific private fields and methods of the elements that they are visiting. Therefore, we might need to expose more public properties in our classes than we usually would if we didn't use the...

Designing a power-up mechanic

As mentioned at the beginning of this chapter, the power-up is a staple of video games. And it's a core ingredient of our game. But first, we will review some of the key specifications of our mechanic:

  • Granularity: Our power-up entities will have the ability to boost multiple properties at the same time. For example, we could have a power-up that increases offensive capabilities such as the primary weapon's range while repairing the front-facing shield.
  • Time: The power-up effects are not temporal so they don't expire after a certain amount of time. And the benefits of the next power-up are added on top of the previous one until they hit the maximum settings of the boosted properties.

Take note that these specifications are limited to the following code example, but are not final. We could easily make the benefits of a power-up temporary or change the overall design of the mechanic with slight changes to the code example presented in...

Implementing a power-up mechanic

In this section, we will write the necessary skeleton code to implement a power-up system with the Visitor pattern. Our goal is to have a valid proof of concept by the end of this section.

Implementing the power-up system

Let's look at the steps for implementation: 

  1. We'll start by writing a core element of the pattern, the Visitor interface:
namespace Pattern.Visitor
{
public interface IVisitor
{
void Visit(BikeShield bikeShield);
void Visit(BikeEngine bikeEngine);
void Visit(BikeWeapon bikeWeapon);
}
}
  1. Next up, we are going to code an interface that each visitable element will have to implement:
namespace Pattern.Visitor
{
public interface IBikeElement
{
void Accept(IVisitor visitor);
}
}
  1. Now that we have our primary interfaces, let's implement the main class that makes our power-up mechanism work; because of its length, we will review it in two parts:
using UnityEngine;

namespace Pattern.Visitor
{
[CreateAssetMenu(fileName = "PowerUp", menuName = "PowerUp")]
public class PowerUp : ScriptableObject, IVisitor
{
public string powerupName;
public GameObject powerupPrefab...

Testing the power-up system implementation

To quickly test our implementation in your own instance of Unity, you need to follow these steps:

  1. Copy all the scripts we just reviewed into your Unity project.
  2. Create a new scene.
  3. Add a GameObject to the scene.
  4. Attach the following ClientVisitor script to the new GameObject:
using UnityEngine;

namespace Pattern.Visitor
{
public class ClientVisitor : MonoBehaviour
{
public PowerUp enginePowerUp;
public PowerUp shieldPowerUp;
public PowerUp weaponPowerUp;

private BikeController _bikeController;

void Start()
{
_bikeController =
gameObject.
AddComponent<BikeController>();
}

void OnGUI()
{
if (GUILayout.Button("PowerUp Shield"))
_bikeController.Accept(shieldPowerUp);

if (GUILayout.Button("PowerUp Engine"))
_bikeController.Accept(enginePowerUp);

if...

Reviewing the power-up system implementation

We were able to combine the structure of the Visitor pattern and the API features of ScriptableObjects to create a power-up mechanic that permits anyone on our project to author and configure new power-ups without writing a single line of code.

If we need to adjust how power-ups affect various components of our vehicle, we can do so by modifying a single class. So, in conclusion, we achieved a degree of scalability while keeping our code easily maintainable.

The implementations of the standard software design patterns in this book are experimental and adapted in creative ways. We are adapting them to utilize Unity API features and adjusting them for game development use cases. So we should not consider the examples to be academic or standardized references, just interpretations.

Summary

In this chapter of the book, we built a power-up mechanic for our game using the Visitor pattern as our foundation. We also established a workflow to create and configure power-ups. Therefore, we combined the technical and creative mindsets, which is the core of game development.

In the next chapter, we are going to design and implement attack maneuvers for enemy drones. We are going to use the Strategy pattern as the foundation of our system.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Game Development Patterns with Unity 2021 - Second Edition
Published in: Jul 2021Publisher: PacktISBN-13: 9781800200814
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
David Baron

David Baron is a game developer with over 15 years of experience in the industry. He has worked for some well-known AAA, mobile, and indie game studios in Montreal, Canada. His skill set includes programming, design, and 3D art. As a programmer, he has worked on various games for various platforms, including virtual reality, mobile, and consoles.
Read more about David Baron