Search Unity

Best practice to separate data from logic and modifying it at runtime?

Discussion in 'Scripting' started by Mystic_Quest, Apr 25, 2019.

  1. Mystic_Quest

    Mystic_Quest

    Joined:
    Feb 22, 2016
    Posts:
    47
    Sorry for the long post. I am kind of a beginner and I am still discovering the wondrous world of clean, structured and re-usable code.

    Say I've got a character that has a few abilities (spells) with their own upgradable effects and stats damage, burn/freeze effect etc. That character also has various upgradable stats on his own e.g. cast time, health etc. There are also various power ups that can upgrade the characters stats or an ability's stats.

    I'm thinking of making scriptable objects to contain variables for the character, abilities, ability effects and power ups. I could for example add the character+powerup values to the character current values in the character monobehavior in order to register the power up. But that way I wouldn't have an separate scriptable object with my current character stats that could send events to other scripts.

    I googled this a lot, saw a few different methods e.g creating instances of scriptable objects, or saving a scriptable object into a json and reseting it. Or I guess I also could make dedicated scriptable objects with current stats and modify them at runtime so that other scripts look at them. All these methods I saw for changing scriptable objects at runtime seemed way too messy though. Or should I just calculate my current stats and just have everything look at the player monobehavior script?

    Any suggestions of how to organize this project?
     
  2. Mystic_Quest

    Mystic_Quest

    Joined:
    Feb 22, 2016
    Posts:
    47
    Update: Also watched the ECS and job system introduction that, if I understood correctly, uses prefabs with single piece of data structs/components (so I guess scriptableobjects are outdated in this system) to populate entities with them (without using the prefab itself) and jobs accessing entity components instead of using monobehaviors for objects.

    Should I get used to working with these? Anyone can shed some light?
     
  3. You're a beginner of what? Game development? Or development in general? If the later, then you should not start with ECS, and frankly, I wouldn't even bother with the ScriptableObject system and the separation of data and code and responsibility things. If you're truly a beginner, concentrate on your game first.
    Because you can learn how to code "clean" and you can learn what are you doing wrong in the mean time. You will recognize when you try to modify your game code after a while.
    If you're a beginner, just create games as you can, don't let the shiny "clean code", "ECS", etc things grab you away from making a game. Your first games will suck, no matter how you code them, so does not matter in the end. And as I said, you will learn these things along the way.
     
  4. Mystic_Quest

    Mystic_Quest

    Joined:
    Feb 22, 2016
    Posts:
    47
    Ah forgive me for not clarifying that, I already have gotten my hands dirty with Unity, making a couple of projects on my own and taking some courses and tried a few ways to organize them before looking into how to make re-usable, clean code. Also already have used scriptable objects for that spell system I am describing above. However not sure of a good way to modify and save a SO or a database at runtime other than using monobehavior.

    I did understand the logic of ECS and jobs, but it does seem that the logic of the game will become more complicated having to separate specific functions and all. As I've seen though the benefits are huge performance-wise. Atm I am working on some medium-scale 2D projects and I was wondering if it's worth getting used to them.
     
  5. ECS/DOD isn't complicated at all, in fact, it's more simple than the OOP model. It's just that we got used to think in objects, not in small tasks.
    ECS/DOD works if you think your game as a ToDo list. What is needed to be done to achieve X? You make a list what data you need how to translate this data to achieve the effect you need and you will get the DOD/ECS model.

    Well, you don't seem to be super-beginner, so scratch what I said in my previous post,
    I work with SOs extensively and they are comfortable and they aren't harder to save on disk than a MonoBehaviour.
    They are different, because if they are instantiated at design time than they are assets, so they are loaded with the game, not with the level.
    But as everything, there is no silver bullet, our job as developers to find the way which is the most optimal for us to handle data. If it's a pure OOP solution with all the virtualization and abstraction, and the performance is okay, then be it.
    If you're curious about other people's opinion about it, it has been asked on these forums, multiple times, sometimes with debate about game development, so you can search the General Discussion forums.
     
  6. TimmyTheTerrible

    TimmyTheTerrible

    Joined:
    Feb 18, 2017
    Posts:
    186
    There are infinite ways of doing something like this, and it sure seems like most of them can get a bit messy.

    Here's what I decided on for mine:

    CharacterClass is a scriptable object I create that contains a list of abilities for that class.

    Abilities are also scriptable objects, so they can be assigned to the character class profiles.

    The Actor component itself is on the player/NPC, and it is fed a CharacterClass so that on startup it can read from the class profile and clone the list of abilities.

    Now that the abilities are cloned, we can loop through them and add listeners to the instanced abilities.

    Ability modifiers or perks/talents would be stored on the actors class, and then added to the instanced abilities modifier list after the cloning.

    If anyone else has some alternative ways of doing this though I would love to hear them!
     
    CheekySparrow78 likes this.