top of page

Modular Spell Crafting System - Project Analysis

In this project I designed and implemented a modular spell crafting system. A way of having a player build a spell through modifiers during gameplay. These ‘modifiers’ act as the building blocks of any spell, affecting its interaction with the game world as well as with enemies. For example, allowing the spell to bounce off surfaces on contact, changing the spell’s trajectory to home in on a target, or more advanced effects such as causing shards of ice to erupt from nearby surfaces. Allowing many modifiers to affect a spell simultaneously requires a framework that prevents conflicts, while developing such a system must allow a large amount of modifiers to be implemented with ease.

Grade Achieved: 1st Class Honours

Gameplay programming is the specialism I have had the most interest in over the course of my game development experience. To improve my abilities in the area, I am on a constant lookout for interesting and complex mechanics to create, that can open up a lot of unique gameplay mechanics and test my skills. To build a modular spell crafting system in such a way that allows for rapid expansion, while keeping the possibility for synergy between any set of modifiers, seemed particularly challenging. I believe I have achieved this in this project, giving a method for creating the basis for any modifier concept in approximately 30 minutes each while also preventing any conflicts with others.

As the modifiers are the core component of the spells, I used that to form the foundations of the system. Each modifier had two key requirements: it would need to manage what code gets run when certain conditions are met; and it must be able to be stored in a list in both the script responsible for casting the spell, as well as the script attached to the spell object. Originally I was planning on having each modifier be assigned an ID, represented as a string; with a switch statement in a ‘Modifier Manager’ script to organise the conditions and functions for each modifier. I quickly realised this would suffer in terms of readability and clarity of the code. Therefore I designed a new method of implementation using a ‘Modifier’ class, of which each modifier is derived.

Modifier Class Script.png

This class contains a function for each condition; for example when the spell is cast, and when the spell hits an object. Each of which is a virtual function with an empty body as this allows an inherited class to override the functions only where necessary. Using functions also allows for code to be run whenever a condition is met, no matter which class; as well as passing parameters into a condition, such as passing collision data to the ‘OnImpact’ function.

Although this project is designed to manage large numbers of possible modifiers, I decided to set a goal of 10; while utilising several different styles of implementation to allow analysis of as many paired interactions as possible within the limited timeframe I had for this project. For example, I included at least one of each basic condition, meaning some modifiers trigger on impact where others were timed; and I created a diverse set of mechanics, such as some directly altering the attributes of a spell, where others give effects to the target, etc.

 

The following is an example of one of my modifiers, which shows how a modifier can override multiple conditions as and when necessary.

Due to the way in which Unity’s systems work, the physics of a collision are updated before the ‘OnCollisionEnter()’ function is called. Therefore, as a workaround, I had to utilise both the ‘OnUpdate’ to store the last velocity of the spell each frame, as well as the ‘OnImpact’ functions of the Modifier class, in order to successfully use the ‘Vector3.Reflect’ function.

​

This example also shows the ability to create modifiers that directly alter the functionality of others as opposed to creating a new class for a new modifier. The 'Targeted Bounce' modifier overrides the bounce velocity to direct it towards an enemy if in range. Since this modifier alters the output of a different modifier, having all the code in one class removes repeated code for similar functionality, making tweaks easier and less prone to issues.

Bounce Script.png

Adding more visual feedback when casting spells became a high priority requirement as I began implementing more modifier examples. When dealing with a large number of effects for each spell, I decided that a visual effects system would be most effective at providing a large contrast between modifiers.

VFX Manager Script.png

To implement vfx in the project, I first created a manager script that contains several function overloads for creating a vfx from a given ID. Using this method I could account for many different types of vfx in a much easier way. For example, I included an overload for effects that would appear on nearby surfaces. This overload was then able to contain a parameter for the ‘normal’ or direction for the vertical axis; which was necessary to determine whether the effect would appear from a wall or floor.

To explore the possibility of how this system can be adapted to different gameplay, I have also altered this system to create modular effects on enemies. As with modifiers, the effects are all classes that inherit from a base ‘Effect’ class. This class contains functions that correspond to different conditions for the effect triggers. For example, the ‘OnUpdate’ condition, which triggers every frame for effects that occur over time; or the ‘OnDamaged’ condition, which triggers when the enemy gets hit. Using this system allows for much more unique effects, implemented in a much faster and more structured process.

 

Other adaptations are also possible for this system. In particular I have been interested in exploring how this system could be used for managing the effects in a card game. Similar to my casting spells mechanic, card games often have some large quantities of conditions for actions they perform. Hearthstone, for example, has keywords such as Battlecry, Deathrattle and Divine Shield, which each trigger at different times and interact with other effects.

 

Implementing these mechanics into my an altered version of my system would be relatively straight forward. Each keyword the game introduces could be created as a new function of a 'Card' class; with a script for managing conditions and card stats. With over 3,000 cards in the game, my system could allow for quick and easy development; keeping the functionality of each card separated to improve formatting and ease of access.

For the future of this project, I will be hoping to expand this piece into a full game concept. I’ve enjoyed working on the system so far and feel as though there’s a significant room for expansion, especially when designing possible interactions with unique enemy concepts as the modifiers can be used as strengths and weaknesses when fighting against specific enemy types. For example, using the piercing modifier against armoured types, or using the homing modifier to increase accuracy against fast moving enemies.

 

Additionally, I am considering keeping this piece as an isolated project, which I can make public along with a guide on how others can implement it into their games. Rather than release the system as a finished project, I would aim to inspire others to adapt it in their own style. I believe this system has a large range of possible applications, such as in card games, due to its modular nature, and ability to manage a large range of effects in a structured format.

bottom of page