Search Unity

  1. Calling all beginners! Join the FPS Beginners Mods Challenge until December 13.
    Dismiss Notice
  2. It's Cyber Week at the Asset Store!
    Dismiss Notice

System Design, A Large Project Problem

Discussion in 'Scripting' started by Donsantos, Apr 13, 2019.

  1. Donsantos

    Donsantos

    Joined:
    Dec 5, 2014
    Posts:
    2
    Its usually easy to find answers about implementing a specific solution. But it's a lot harder to find answers concerning general system design

    I am currently designing a system for casting spells in a game, but the system has grown out of proportion, of course it was also poorly planned and implemented from the start. I am not looking for an out of box solution, but rather pointers, your thoughts, pseudo-code or references to reading material that may help.The goal of the system is
    • for an entity(player, enemy, or some other thing that can cast spells) to use the same classes and tools to throw spells.
    • To be able to add lots of different varied and unique spell effects without too much hassle, writing the actual code only once in a single method, and then call that method with different data from different "entities" such as the player or an enemy etc.
    • To separate data and behaviour, each entity carries a "spellbook" with the data for a spell. But the behaviour lies elsewhere, accessible for other entities as well.
    It mainly works around every entity sending data to one global system that casts all magic, it has all the actual "performing" code.

    The problems of the system:
    • Passing the same arguments through several classes and methods
    • These arguments are all sent, but not all of it is used every time
    • Can't find a good substitute for a single large switch-case
    • Not abstract enough, any change to data sent will require a rewrite of every case in the switch and also most of the actual implementing code
    Let me explain..
    The system looks something like this very poor drawing:
    Each circle represents an entity, the player for example. They send data into a general execution(The large square in the middle) class that performs some function. I don't quite know what to call it here, so I will call it the "execution class"

    Any magic-throwing entity carries 3 classes.
    • Input (player input, ai input or random timers)
    • Spell data (Intensity, duration, particles to play etc)
    • Spell formulation
    The last one isnt even clearly defined, but it combines and sends the data to the execution class. For example: our position, rotation, where we are aiming, current target etc.
    The execution class in the middle is a global class, it carries 0 data and only executes upon the data it recieves.

    I am happy with this solution, as these 3 classes added to any object will allow them to cast any spell, because the implementation for the spell rests with the global execution class. I simply define spell-data on these entities however I want, and write the implementation only once.

    But the problems start with the large execution class. It takes a very lage amount of data in form of arguments, and it has to pass those through a large switchcase that determines what the actual effect is going to be and then sends all the data to that function. This "sieveing" of data leads to problems, any change to the data sent or the actual implementation requires a rewrite of the other.

    The switch works through an enum. Each defined spell has an enum that roughly describes the implementation. For example: "Ignite, push, slow_time, change_gravity, etc." The switch is based on this enum. But each "effect" is vastly different from any other. And the arguments that only affects slowing time is still passed through to the method that ignites things and vice versa..

    And so I get this huge switch case in the middle that only takes arguments, finds the execution method I need and then passes all those arguments to that method. I am passing arguments through classes and through methods, this seems stupid.

    Not only is the switch-case immense, but there are also so many different methods for each different magic spell that can be cast, that the script is becoming daunting to work in. With only a few tens of spells, its sitting at hundreds of rows of code. Each new "spell" that has a unique effect will require a new case in the switch and also its own implementing method of code.

    I would love to be able to add new spells as easily as possible, but adding more to this current system will probably just add more harm.

    I realize there is no simple answer to something like this, indeed I am not even giving a straight question. But I am at a loss at how to more effectively design something of this scope. How would I even continue with something like this, how does one start with a system of this scope.

    I also apoligize for the long post, and if the lingo used is confusing. I am a self taught C# programmer since I started unity a few years back, I only know the very limited things I have taught myself over the years with the help of forums and tutorials.
     
  2. NicBischoff

    NicBischoff

    Joined:
    Mar 19, 2014
    Posts:
    145
    Scriptable objects will solve your complex input problem.
     
    Donsantos likes this.
  3. Donsantos

    Donsantos

    Joined:
    Dec 5, 2014
    Posts:
    2
    How did I not know about scriptable objects before, implementing this seems to have cleaned up my project and code quite a bit. Thanks for the advice!