Search Unity

My Scriptable Objects keep losing data due to a parsing error. How can I avoid this?

Discussion in 'Editor & General Support' started by Deleted User, Jun 27, 2019.

  1. Deleted User

    Deleted User

    Guest

    I have a series of scriptable-objects which I use to hold dialogue data. On these scriptable-objects I have a TextClass which holds the data of the text and potential branches, kind of like a tree, to other dialogues. Whenever I press Play, switch-scenes, edit a script, or even blink, I have to take a deep-breath that I don't get this error "Unable to parse file .asset: [Parser Failure at line 25: Expect ':' between key and value within mapping]". Has anyone encountered this, I greatly appreciate any help.
     
  2. Deleted User

    Deleted User

    Guest

    So for anyone that is interested, I've come up with a thesis on the grand conundrum that is scriptable-object usage and instantiation:

    Under the hood Unity does not serialize Scriptable Objects (SO's) as a transformative instance but rather a base-object with different key-value pairs (like a dictionary).

    What this means is that if one were to try to refer to a non-native data-type such as a Class on a SO, unless the class is VERY simple, the class will be very volatile to resetting, as to create references to variables in the class would require ANOTHER key-value pair. Something that Unity does not support.

    All in all that means, if you want to store-data on SO via class, you're better off not doing it. Rather you can put all the variables you want to change in that SO as native types (i.e. lists, int, bool).

    OR

    Make a class that derives from ScriptableObject.

    It sucks, but due to the under-workings of Unity, there is no choice.

    Now mind you that this is just a theory. I can be completely wrong on all of this, but I will test this method and a reply back on my results. Hopefully I don't lose data :p.
     
  3. I don't think I have tried to serialize classes on SOs, but in theory Unity only uses one and only one serialization. And under the hood SOs are not that different from MonoBehaviours (other than the obvious assets versus components).
    Are you sure you have the [System.Serializable] on your TextClass? Would you mind show us the code of your SO which has the problem? Maybe we can spot something. Are you sure you save normally?
     
    Deleted User likes this.
  4. Deleted User

    Deleted User

    Guest

    Definitely, I'll paste it down below. These classes were stored separate from the scriptable-object on another script. I've removed the prior-implementation since, but all there was - was a List of either 'StoryBit' or 'ComplexStoryBit' on the SO. Also I save the scene using the File -> Save, and I updated my SO via the inspector.
     

    Attached Files:

  5. Please use the code tags and insert code as text in your posts, images are very nasty to read when it comes to code.

    I don't think abstract classes serialized properly and properties don't serialize properly (unless you introduce the backing field explicitly and serialize that).

    More to read and maybe get some ideas: https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
     
    Deleted User likes this.
  6. Deleted User

    Deleted User

    Guest

    I'll keep that in mind. And thank you for the read, I understand the issue in more depth now thanks to that. Please, correct me if I'm off, but I'll post this for future readers:

    I was attempting to make an object-graph using custom-classes (basically a tree) - but this isn't supported in Unity. This is because Unity's serialization nullifies unique-id's on custom classes which is essential to object-graphs (because you need to be able to tell each node apart).

    If you want to make a object-graph without extra-workaround, the "nodes" need to derive from UnityEngine.Object. In other words, a MonoBehavior or ScriptableObject. Otherwise data will eventually be lost, as when everything is re-serialized it will use the base custom-class (this erases all unique data).

    This also explains why the data was being lost on Play, after-updating the script, and closing unity - because this is when objects are re-serialized.

    The downside to this however is that you must find a place to store these objects in memory (i.e. making more ScriptableObjects / MonoBehaviors) which will bloat your project.

    In my case because each object takes up about 2.5 KB I'll be fine, but for larger SO this may become an issue. If your SO is large and memory is a concern, consider rethinking your implementation.

    Thanks again, cheers.
     
    Lurking-Ninja and mountblanc like this.
  7. One little extra info: In 2019.3 there will be a SerializeReference attribute.
     
    Deleted User likes this.
  8. Deleted User

    Deleted User

    Guest

    That sounds awesome! Thanks again. Also heads up to whoever reads this:

    Along with my previous error, DO NOT COPY AND PASTE TEXT INTO A STRING VARIABLE ON A SCRIPTABLE OBJECT.

    This was the stem of ALL of my woes, and while everything runs more smoothly because I fixed the serialization the original parsing error came from this.

    I want to cry, I've been pulling my hair out because of this :(

    Unity, if you see this, please add auto-line ending to Scriptable Objects!
     
  9. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Can you explain why? This seems incorrect to me.

    I can copy/paste into the text field of a SO, and Unity serializes the text fine. For example, I added a text field to an SO class of mine:

    upload_2019-6-27_15-42-38.png

    Then I pasted in some text. Here's what I pasted:
    Code (CSharp):
    1. Here's some text.
    2. I copy/pasted this from Notepad++;
    3.  
    Which resulted in the following data ending up in the SO asset:

    Code (CSharp):
    1.   MyText: "Here's some text.\r\nI copy/pasted this from Notepad++;\r\n"
    Then, I copied the entire contents of the SO asset itself, full of weird characters, and pasted that in too. It resulted in this saving to the SO:

    Code (CSharp):
    1.   MyText: "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n
    2.    \ m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance:
    3.    {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled:
    4.    1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 4670482b65cc65f498693718f3269e35,
    5.    type: 3}\n  m_Name: Main Menu Scene Settings\n  m_EditorClassIdentifier: \n  DefaultSoundtrackSettings:\n
    6.    \  AudioClip: {fileID: 8300000, guid: d6b659e0396ca4b49ba78014671d08fb, type:
    7.    3}\n    Volume: 0.1\n    Pitch: 1\n    TimeOffset: 0\n    NoLoop: 0\n  MyText:
    8.    \"Here's some text.\\r\\nI copy/pasted this from Notepad++;\\r\\n\"\n"
    No problems so far. Can you give an example of some text that you believe results in problems when pasted into a SO text field?
     
    Deleted User likes this.
  10. Giometric

    Giometric

    Joined:
    Dec 20, 2011
    Posts:
    170
    Might be a thing where the source of the copy paste was inserting weird stuff, like control characters etc.
     
  11. Deleted User

    Deleted User

    Guest

    Update:

    So as dgoyette has stated, the root of the issue is not due to copy-and-pasting from external source - even though it does contribute to the issue.

    It is just having Lists on ScriptableObject's in general, I'm 99% sure it is just bugged at the moment.

    I've conducted several tests and realized that if you have a List on a SO they are prone to parser-errors. All other non-listed variables are serialized and do not reset - even if the error occurs.

    I've changed my implementation since, but I am trying to report the bug through Unity.

    I assume this is because OnEnable() these variables are stuffed into an IEnumerable and at that point the error occurs, or it could be because without a capacity the List serializes infinite items, leading to the error.

    Who knows? I won't be able to make any concrete assumptions without looking at their implementation.

    As of today, the problem is still unsolved and I'll continue to update as I get more info.

    If you solve the problem, please leave the reason this occurs below.

    ,Cheers.
     
  12. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Having an example of the failure will be important. Also, to be clear, your SO contains List properties, not Array properties? I don't use List on serializable objects, only Array, so I suppose there could be some issue unique to Lists. But I'll say I have hundreds of SO instances across dozens of SO classes in my project, all using arrays of values, and I've never had a case where it got messed up and lost data.

    So, if you can reproduce this, please share the steps. If you don't want to spend a lot of time reproducing it, maybe just switch to array properties instead of List properties. No guarantee it'll solve the issue you're facing (maybe you're doing something else that's causing this to occur), but it's possible.