Search Unity

Script Serialization Errors Feedback

Discussion in 'Scripting' started by lukaszunity, Jun 6, 2016.

  1. lukaszunity

    lukaszunity

    Administrator

    Joined:
    Jun 11, 2014
    Posts:
    461
    Last edited: Jun 6, 2016
    Deleted User likes this.
  2. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    So that wasnt an accident, huh?
     
    Ryiah, ArachnidAnimal and lighting like this.
  3. edm1606

    edm1606

    Joined:
    Oct 7, 2016
    Posts:
    3
    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?
     
    Last edited: Oct 10, 2016
  4. lukaszunity

    lukaszunity

    Administrator

    Joined:
    Jun 11, 2014
    Posts:
    461
    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
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,333
    The error messages have helped clean up some scripts, so they're welcome on our end.
     
  6. edm1606

    edm1606

    Joined:
    Oct 7, 2016
    Posts:
    3
    Thanks, that worked. Wasn't thinking straight
     
  7. renjop

    renjop

    Joined:
    Dec 3, 2015
    Posts:
    8
    While using Unity 4, on my other scripts I am able to Call MyGameObject.Instanstiate<OtherMyGameObject>() without any issues and no warnings.
    Code (CSharp):
    1.  
    2. public class MyGameObject : MonoBehaviour {
    3. public static T Instantiate<T>() where T :  MyGameObject{
    4.         var relatedGameObject = new GameObject("NewGameObject");
    5.         relatedGameObject.transform.localPosition = new Vector3(0,0,0);
    6.         var myGameObject =  relatedGameObject.AddComponent<T>();
    7.         return myGameObject;
    8. }
    9. }
    10.  
    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.
     
  8. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,333
    That code there is only doing legal things, I believe. You sure it's that snippet causing the issue?
     
  9. renjop

    renjop

    Joined:
    Dec 3, 2015
    Posts:
    8
    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
     
  10. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,333
    Looks like you're trying to do MyGameObject.Instantiate<T> for some T which calls Resources.Load in it's constructor. That probably means that your T does something like:

    Code (csharp):
    1. private GameObject obj = References.Load(...);
     
  11. renjop

    renjop

    Joined:
    Dec 3, 2015
    Posts:
    8
    I am guessing that Resources.Load cannot be in a method other than Start() or Awake().
     
  12. lukaszunity

    lukaszunity

    Administrator

    Joined:
    Jun 11, 2014
    Posts:
    461
    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.
     
  13. LastTalon

    LastTalon

    Joined:
    Jun 22, 2015
    Posts:
    3
    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.
     
  14. lukaszunity

    lukaszunity

    Administrator

    Joined:
    Jun 11, 2014
    Posts:
    461
    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.
     
  15. LastTalon

    LastTalon

    Joined:
    Jun 22, 2015
    Posts:
    3
    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?
     
  16. lukaszunity

    lukaszunity

    Administrator

    Joined:
    Jun 11, 2014
    Posts:
    461
    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.
     
  17. LastTalon

    LastTalon

    Joined:
    Jun 22, 2015
    Posts:
    3
    I'll try updating versions later.