Architecture for a spell system

I am currently working on an pixelated isometric dungeon crawler, in which the player can learn a variety of spells to use against the undead hordes that oppose them.

I am trying to design an architecture that will make the creation of new and unique spells easier down the line.

Spells will be broken into categories, such as projectile, buff, splash, conjure, etc.

Each individual spell script will inherit from one of the categories.
For instance, for a projectile spell, it will have global variables such as cooldown, impactVFX, impactDamage, flightLifetime, and flight pattern. The flight pattern would default to a straight line, but could be overridden to zigzag or curve.

The spells script will be attached to a prefab, which will be the complete spell. When the player presses a certain button it will simply instantiate a new spell prefab of the specified type. The prefab will have a collider, and when it collides with something, it will do all the OnCollision stuff; apply damage, play impactVFX, sounds, whatever.

My goal is to have a system setup so I can spend less time coding and more time designing the spells, making them look and sound nice, and just making them into something really fun.

This is my first time really trying to make the architecture of a game as efficient as possible, so I have very minimal experience with this sort of thing. Is there any way I can make this system more efficient or scalable? I would like to spend more time now building the foundation so that later I can focus more on making the game look good and be satisfying.

Has anybody made a similar game where the player can cast a lot of spells, and you have to make those spells? What sort of system did you use?

Feel free to share or give suggestions about my idea!

You essentially just want to identify all the common properties of your spells, and then use composition, inheritance or interfaces to create new spells with minimal coding.

You can also wrap methods inside objects if you want custom modular logic for your spell. In your projectile example.

public class ProjectileSpell : MonoBehaviour
{
    private IFlightPattern flightPattern = new LinearFlightPattern();

    private void Update()
    {
        flightPattern.Execute();
    }
}

public class LinearFlightPattern : IFlightPattern
{
    public void Execute()
    {
       // Some custom logic that requires more than just using variables.
    }
}

public class ZigZagPattern : IFlightPattern
{
   public void Execute()
   {
      // ZigZag logic.
   }
}

You could have a ProjectSpell for runtime processing that takes a ScriptableObject that defines it.

public class ProjectileSpellDefinition : ScriptableObject
{
    public FlightPatternEnum flightPattern;
    public int damage;
    public ParticleSystem vfx;
    public float cooldown;

    .. etc
}

This is just one of many ways, and I’m not saying this is the best way. Advantages is that it’s simple to create new ScriptableObjects to define behavior’s but its not very flexible or extensible.

Using Interfaces might be more modular and extensible, however would require much more code for the concrete implementations, some people find coding faster than editor authoring.

I would recommend just looking through some repos to see how others have tackled the problem:

Cool Thanks! Makes sense and I will look into what you said.