Search Unity

Custom Asset Backwards Compatibility

Discussion in 'Scripting' started by AnsonRutherford, Feb 17, 2018.

  1. AnsonRutherford

    AnsonRutherford

    Joined:
    Jan 16, 2014
    Posts:
    12
    I have a few custom assets that I want to handle is a special way. We recently updated our Unity version from 5.3.4 to Unity 2018, and it looks like there are features for handling this (AssetImporter?), but I'd appreciate some advice.

    I have a class that I want to store as a custom asset. Let's say this class is called StatBlock, and it looks like this

    Code (CSharp):
    1. public class StatBlock : ScriptableObject {
    2.     public int str; //Strength
    3.     public int dex; //Dexterity
    4.     public int con; //Constitution
    5.     public int int; //Intelligence
    6.     public int wis; //Wisdom
    7.     public int cha; //Charisma
    8. }
    When imported as an asset, I want this to function normally. If I have a MonoBehaviour component with a StatBlock variable on a gameObject in scene, I want to be able to drag the asset directly from the Project pane into the variable slot, etc.

    I have this working right now. What I ALSO want, is to be able to directly control how Unity interprets this file. Rather than just serializing this object into binary or text, I'd like to control how Unity imports the associated .asset file into an object, and vice versa. The main reason for wanting this is for backwards compatibility.

    For example, let's say later on in development, I decide Intelligence and Wisdom aren't different enough, and I merge them into a new stat called Brain. But I have 500, or some other large number, of StatBlocks that will suddenly not have a value for this. Let's say I decide that the Brain stat for each StatBlock should be equivalent to whichever of Intelligence and Wisdom used to be higher. This is a sort of contrived example, but I assure you this exact case, or something similar, has come up, most commonly with wanting to change how data is stored, or adding additional functionality. Another example might be wanting to store an int array of all six stats, rather than six variables, but wanting the Unity to be able to interpret and create objects out of older files.

    I know my way around serialization. If I were able to specify the contents of the .asset file myself, I'd probably put it in json, xml, or csv, and have it store this:

    Code (CSharp):
    1. VERSION: 0.1
    2. STRENGTH: 11
    3. DEXTERITY: 11
    4. CONSTITUTION: 11
    5. INTELLIGENCE: 12
    6. WISDOM: 10
    7. CHARISMA: 11
    Then, in my hypothetical custom StatBlock importer, I'd have this file generate a StatBlock. If I were using Brain now, I could do something like this

    Code (CSharp):
    1. public StatBlock ImportAsset(values v) {
    2.     StatBlock sb = new StatBlock();
    3.     sb.str = v.STRENGTH;
    4.     sb.dex = v.DEXTERITY;
    5.     sb.con = v.CONSTITUTION;
    6.     sb.bra = Mathf.Max(v.INTELLIGENCE, v.WISDOM);
    7.     sb.cha = v.CHARISMA
    8.     return sb;
    9. }
    , and I could run a switch statement on VERSION to help older assets be imported correctly.

    I'd rather that Unity use its normal serialization when it builds the game, so it doesn't have to deal with my ugly asset formatting. Ideally, when this object gets stored back in the file it came from, it would now store a value for BRAIN and none for INTELLIGENCE or WISDOM. This would involve a custom exporter as well. I can't figure out the easiest way to implement this. It seems hard to differentiate between when Unity is serializing something to store on disk as an asset file, or serializing it for a build.

    Sorry if this is a bit confusing, I'm still trying to figure out the best way to do this. I can clarify anything if needed.
     
    Last edited: Feb 18, 2018
  2. AnsonRutherford

    AnsonRutherford

    Joined:
    Jan 16, 2014
    Posts:
    12
    So, I'm still trying to puzzle this out. This is what I've been able to gather from what I've read in the Unity documentation, can someone who understands this better than me confirm/clarify?



    The asset file, which exists within your computer's file system, is used by the Unity Editor to generate an Object file. In my example above, you might create a MyStatBlock.asset file, which Unity would import and use to create an instance of the StatBlock class, which can be placed in StatBlock variables, etc.

    This Object can also be edited via Unity's editors, and those changes on the object reflect back on the MyStatBlock.asset file... somehow. I couldn't find much documentation on that subject.

    Unity also serializes(?) the data of the Object and stores it in a Library file. This is what Unity works with when running, and this file is packaged with all builds of your project. This is what your Unity project's build accesses at runtime.


    Is this right? What am I missing?