Project Type — Game Jam (team of 7)
Software Used — Unity
Language Used — C#
Role — Gameplay Programming, Implementation
Reap & Sow is a twin-stick shooter where the player kills haunted crops to get resources, and uses those resources to purchase upgrades to survive longer and progress further. My main contributions were designing and implementing a roguelike-style stacking upgrade system, inspired by games like Risk of Rain 2 and Hades.
The upgrade system was designed to fulfill four big goals:
Be Designer Friendly
Designers can create upgrades in the Unity inspector without needing to touch code.
Upgrades are Stackable
Stacking, where an upgrade gets more powerful the more times its obtained, allows extra depth with less design work. Also, as a player, it's fun to watch numbers go up!
Be Polymorphic
All upgrades should use the same framework to obtain, apply, and remove effects.
Upgrades use Unity's ScriptableObject asset class to store polymorphic lists of generic 'Effect' classes, which are given functionality in subclasses via inheritance.
Be Expandable
Avoid bloat ⇒ avoid processing upgrades on central player scripts.
Eg: If an upgrade causes extra gun damage close to enemies, the upgrade should calculate that, not the gun.
Make Effects as flexible as possible.
Eg: Instead of a “Player Defense Up” Effect and an “Enemy Vulnerable” Effect, use a “Modify Damage Received” Effect that can be used for any entity group.
"Player Defense Up" uses the damage-modification Effect to boost Player defense.
"Enemy Vulnerable" uses the same damage-modification Effect to boost player offense.
I was inspired by Risk of Rain 2's item system, specifically with how varied item effects could be! My system needed to support similar flexibility, and so I divided all Effects into one of two main classes: InitialEffects and HookEffects.
Initial Effects ⇒ effects are applied when the upgrade is obtained / when gameplay starts
Eg: Stat boosts, ability and progression unlocks
Hook Effects ⇒ effects are "hooked into" game actions and apply when actions are invoked via the observer pattern
Eg: Damage modifiers, gun pierce modifiers
Each type of Effect has an serializable base class without functionality, which the Upgrade wrapper class abstractly calls methods on. Subclasses implement all the functionality!
HookEffect Subclass, implementing a damage modifier that triggers if an enemy is at full health.
H_DmgModFirstHit in action!
Upgrades needed to be designer-friendly, so Effect lists needed to be fully serializable in the Unity Inspector window. By default, Unity serializes lists in the Inspector. However, because Upgrade assets held lists of base Effect classes (HookEffect and InitialEffect), by default, adding Effects in the Inspector added an empty Effect!
In order to properly add Effects to the Upgrade, I wrote a custom Editor script which automatically detected all available Effect subclasses, and allowed the designer to select the one they wanted to add.
Making this stable required a few key steps:
Using the [SerializeReference] tag on the Effect lists, to allow Unity to serialize them as subclasses instead of the base class
Manually adding subclass constructors to the editor script
Identifying subclasses involved scanning through a folder for scripts.
However, instantiating those subclasses is a much more complicated process and was not cost-effective given the tight game jam timeline.
The polymorphic Effect system and editor serialization allowed for me to create 18 effects and 25 upgrades in half a week! These upgrades were the backbone of our gameplay loop, and their number lent a lot to our gameplay depth.
Failing to add Effects using Unity's default editor.
Successfully adding Effects using my custom editor.
A portion of the Editor code for adding Initial Effects.