I’ve been researching all the resources I could find on implementing ability/skill systems in Unity, and I’ve come to the conclusion that there’s no way to properly design and implement one using Unity tools.
Here’s the fundamental problem: a proper ability system will build abilities out of modular components like targeting, effects, etc.
For example, take a look at DotA 2’s ability system: Abilities Data Driven Examples - Valve Developer Community
Abilities are built with nested components like modifiers, events,and actions. You define an event block, and then define the various actions that will occur on that event.
However, Unity does not have tools to create a system with nested components that can be modified in the editor.
The Unity tool best suited for an ability system seems to be ScriptableObjects. For example, this is an official Unity tutorial on how to create abilities using ScriptableObjects: Create an Ability System with Scriptable Objects - Unity Learn
Instead of defining modular components, like different targeting types, that can be plugged into abilities freely, that tutorial creates an inheritance hierarchy, with a base Ability class and each type of targeting being a separate derived class.
This seems like a horrible idea that does not extend well at all. In that example code, each ability defines its actions (e.g. applying damage) explicitly in the derived class. What about when there are multiple different types of actions (applying damage, applying debuffs, stunning, pushing, teleporting, etc.) that you want to mix and match with different targeting? Then the inheritance tree quickly breaks down and becomes unmanageable.
The ideal solution would be to be able to define nested ScriptableObjects inside of ScriptableObjects. The problem is that Unity does not handle this well. If you try to add the nested SOs as subassets, then they don’t get properly removed and deleted and you can end up with a bunch of orphaned assets. This basic functionality that is required for any modular ability system does not seem to be properly supported by Unity for some reason.
If you simply create all nested SOs as separate assets, then you get a bunch of horrible redundancy and wasted manual effort. For example, imagine if you have a targeting modules that you define as SOs. Then, you’d have to create multiple SOs representing stuff “single target, range 5, enemies only”. You’d need a single SO for every combination of parameters, which seems absurd.
You also can’t use simple Serializable classes, because Unity’s serialization doesn’t support polymorphism.
So in conclusion it seems like there isn’t actually any way to implement a modular, component-based ability system with Unity’s tools. Every example I’ve seen using an inheritance hierarchy or just enumerates every single possible attribute an ability could have and requires you to set the unused ones to null. Both systems quickly break down as the complexity and number of abilities grows.