Search Unity

Data Storage?

Discussion in 'Scripting' started by Art_Izon, May 30, 2019.

  1. Art_Izon

    Art_Izon

    Joined:
    May 29, 2019
    Posts:
    2
    I'm not super-experienced with the possibilities for data storage in Unity, and rather than spending thirty hours trying to implement one and finding out it won't suit my project, I figured I should just ask.

    A game I'm developing at the moment is somewhat Final-Fantasy-esque. I need a way to store data for all the different abilities available to players and enemies. However, these abilities are more complex than run-of-the-mill "this ability has power modifier x and element y." Sometimes they're multiple hits (which can mean creating multiple hitboxes, because the game has a simple timing-based evasion system), with each hit having a different power modifier and/or element, possibly using different stats. Many of them have unique effects such as "this move negates enemy defense when landing a critical hit" or "the earlier in the turn this move is used, the more powerful it will be." I know how to program those two cases, but not how to store those instructions and access them.

    Each of up to eight entities has up to 12 different abilities they can choose from per battle -- and each of these entities can be using something concurrently, as the system isn't (strictly) turn-based.

    So basically I need something that can efficiently move around a pretty solid chunk of data without slowing down. I can only think of one way to accomplish the above-listed examples, but it seems like it would need lists of lists of lists. For example, if an attack has 20+ hits, and the first 19 have small power modifiers and the last has a large one, I need a 20-item list of those power modifiers. I also need information on the element of each of those hits, the duration of each hitbox, etc. etc.

    I guess what I'm saying is, I probably can do that, but I'm worried it will run too slowly. Would an SQLite database be quicker? Some kind of hash table?

    I'm new to game development so please forgive my ignorance about the processing load of different storage types.
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    The only answer is, "profile it and stress test", for what you need. Then worry, if you hit bottle neck.
    What you describe, is nothing like intensive task.

    Storing in memory is the fastest way of accessing data.
    Saving and loading from disk will be of course slower. And HDD will be definitely slower than SSD.
    So if anything, store on drive during saving. Otherwise, run data on memory.
     
  3. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Performance should not be a major concern with this I think- those numbers are pretty trivial. More important is how manageable the data is IMHO, for you, as the developer. Lists of Lists of Lists implies to me that this is going to be painful to update and debug. I would argue that your biggest concern should be how to perform updates to your data, to tweak timings and number of hits and such without having to rewrite a ton of code or manually edit XML datasets or something.

    You should consider what data needs to be mutable, and what is set in stone when Play is pressed/the game is built.

    Definitely look into ScriptableObjects. They're assets, files that physically exist on the disk (technically YAML data files), so you can treat them as immutable at runtime, which makes them perfect for storing "definitions" of data. Anything that doesn't need to be altered once Play is pressed can be stored as a ScriptableObject- anything that needs to change based on the current game state probably shouldn't be. I wouldn't use them to hold "state" of any kind, because there's just one instance being shared between all consumers. If its data changes, it changes everywhere. That's actually great- it means that you're not creating a bunch of copies of data unnecessarily.

    You also get the benefit of being able to edit its values in the inspector. For simple things like storing "Status Effect" definition data, which just hold a name, description, and a Sprite icon for each status effect type in a game, this means that you can drag and drop the sprite asset into the icon reference without needing to use Resources.Load or something at runtime. For more complex objects, like sequences of "hits" within an attack ability, the benefits are much, much greater.

    By making a ScriptableObject type for your "AttackSkill" class, you can make a collection of "Hit" objects within that class displayed in the inspector, making adding, re-ordering, and removing elements from the sequence very easy, and having different power levels, different status effects, elemental bonuses, hit percentages, etc, for each hit. Then, it exists as an asset that can be loaded as-is, an immutable definition of a particular "skill", which can be referenced and used by any characters in your game freely with no performance penalty. If you have hitboxes to concern yourself with (for instance, hit #3 in a skill connects low and to the left), create 'prefabs' of those hit areas relative to the character, make a GameObject member in your ScriptableObject class to reference one of those prefabs for each 'hit', and instantiate a copy of the prefab when the hit is being used. Alternatively, simply save the Transform information for the hit area instead, and move your own "hit area" box around to reflect it as needed, so that you aren't creating and destroying a bunch of GameObjects unnecessarily (which actually would be pretty poor, performance-wise).

    If you do that, then the "instance data" for these skills is simply which ones the characters have access to, and which ones they have equipped in each slot.

    Does that make sense?
     
    Last edited: May 30, 2019