Script Serialization Errors Feedback

Post any feedback you might have on the new script serialization errors added in Unity 5.4

More details in this blog post:

1 Like

So that wasnt an accident, huh?

3 Likes

Just upgraded to Unity 5.4.1. I was using Application.streamingAssetsPath in the constructor and now I get the error. I cannot shift it to Start() or Awake() as the path will affect other code that needs to be in the constructor.

And I understand how something like GameObject.Find(“foo”) would be unsafe as given in the article, but why would Application.streamingAssetsPath be unsafe?

What other code do you have that needs to be in the constructor? I would advise to refactor the code so that any code in the constructor is moved to Awake, as explained in the documentation.

“use Awake instead of the constructor for initialization, as the serialized state of the component is undefined at construction time. Awake is called once, just like the constructor.”

https://docs.unity3d.com/ScriptReference/MonoBehaviour.Awake.html

The error messages have helped clean up some scripts, so they’re welcome on our end.

Thanks, that worked. Wasn’t thinking straight

While using Unity 4, on my other scripts I am able to Call MyGameObject.Instanstiate() without any issues and no warnings.

public class MyGameObject : MonoBehaviour {
public static T Instantiate<T>() where T :  MyGameObject{
        var relatedGameObject = new GameObject("NewGameObject");
        relatedGameObject.transform.localPosition = new Vector3(0,0,0);
        var myGameObject =  relatedGameObject.AddComponent<T>();
        return myGameObject;
}
}

However the same code using Unity 5.4, I get a “Load is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead”. From what I understand, this is no longer supported with the new Script Serailization. Is there a way to accomplish the same features without changing all of my code.

That code there is only doing legal things, I believe. You sure it’s that snippet causing the issue?

Hi,
When looking into the full stack trace, that line is the one that shows the issue:
UnityEngine.Resources.Load (System.String path) (at C:/buildslave/unity/build/artifacts/generated/Metro/runtime/ResourcesBindings.gen.cs:53)
UnityEngine.GameObject:AddComponent()
MyGameObject:Instantiate()
Thanks again

Looks like you’re trying to do MyGameObject.Instantiate for some T which calls Resources.Load in it’s constructor. That probably means that your T does something like:

private GameObject obj = References.Load(...);

I am guessing that Resources.Load cannot be in a method other than Start() or Awake().

Resources.Load and the rest of the Unity API is always safe to call from any of MonoBehaviuor/ScriptableObject callbacks: Start/Awake/Update/OnEnable/OnDisable/etc.

I’m a bit late on this, but it appears to throw the error when initializing a static field, such as using Application.persistentDataPath to form a static path as well. As far as I know this shouldn’t cause any kind of serialization issue as the static fields shouldn’t be serialized.

Also this logs as an error, but appears to run anyway, shouldn’t this log as a warning with this behavior? As it stands it has been giving me the impression that the code would not be able to run in this state, but it clearly is for me.

There are scenarios where it is safe to call the Unity API from serialization. But as systems change, it might no longer be true. The stance we have taken with the errors is that everything is not allowed to be called by default and we then exclude APIs from this, such as Mathf.

In this specific case the C++ code for Application.persistentDataPath calls into the file system and you do not want that to happen from other threads than the main thread. Since we are limiting API access from threads, we also limit the API access from serialization. Which makes it safe for us to change underlying systems without having to worry about them not being fully initialized before serialization is run at any point in time during the life time of the editor.

Alright, what about my question about the error message though? The code still appears to continue running just fine, wouldn’t an error imply the code can’t run? Shouldn’t it instead be a warning notifying you that future problems might occur?

Which version of Unity are you using? The errors initially were just emitted as an error message in the console, but in recent versions they throw an exception. I think this changed in Unity 5.6, if I remember correctly.

I’ll try updating versions later.