Search Unity

Serialization lost when loading asset bundles in runtime

Discussion in 'Asset Bundles' started by Roelof, Nov 23, 2018.

  1. Roelof

    Roelof

    Joined:
    Jun 25, 2013
    Posts:
    8
    Hello,

    We have been working with asset bundles to load code and scenes at runtime, but we couldn't find a way to get serializable classes/structs to work as well. So we have two different Unity projects: 1 in which we create a scene and 1 in which we want to load that scene at runtime.

    Project 1: Creating the Scene
    The scene that is going to be in the assetbundle contains an object called 'MyObject' which has a component with 3 fields: a string, a Vector3 and a custom serializable struct.
    SerializeSource.png

    The code of this component is this:
    Code (CSharp):
    1. public class SerializeThis : MonoBehaviour {
    2.     public string MainName;
    3.     public Vector3 vector;
    4.     public SerializedField field;
    5.  
    6.     private void Start()
    7.     {
    8.         Debug.Log(string.Format("{0};{1};{2}", field.Name, field.Number, field.Check));
    9.     }
    10. }
    11.  
    12. [Serializable]
    13. public struct SerializedField
    14. {
    15.     public string Name;
    16.     public int Number;
    17.     public bool Check;
    18. }


    This script is added to its own assembly via assembly definitions and I then build 2 assetbundles (1 for the code and 1 for the scene):
    Code (CSharp):
    1. public static class BuildBundles {
    2.  
    3.         private static List<AssetBundleBuild> Bundles;
    4.  
    5.         [MenuItem("BuildBundles/Build")]
    6.         public static void Build()
    7.         {
    8.             Bundles = new List<AssetBundleBuild>();
    9.             Bundles.Add(new AssetBundleBuild()
    10.             {
    11.                 assetBundleName = "SceneBundle",
    12.                 assetNames = new string[] { "Assets/Scenes/SampleScene.unity" }
    13.             });
    14.             Bundles.Add(new AssetBundleBuild
    15.             {
    16.                 assetBundleName = "ScriptBundle",
    17.                 assetNames = new string[] { "Assets/ScriptsAssembly.bytes" }
    18.             });
    19.             BuildPipeline.BuildAssetBundles(@"[build location]", Bundles.ToArray(), BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
    20.         }
    21.    
    22. }

    Project 2: Loading the scene
    I then open the loading project where I load the assetbundles like so:
    Code (CSharp):
    1. public class Loader : MonoBehaviour {
    2.  
    3.     void Start ()
    4.     {
    5.         LoadCode();
    6.         LoadScene();
    7.     }
    8.  
    9.     private void LoadCode()
    10.     {
    11.         var filename = @"[build location]\scriptbundle";
    12.         var codeBundle = AssetBundle.LoadFromFile(filename);
    13.         var assetName = codeBundle.GetAllAssetNames()[0];
    14.         var txt = codeBundle.LoadAsset<TextAsset>(assetName);
    15.         Assembly.Load(txt.bytes);
    16.    
    17.     }
    18.  
    19.     private void LoadScene()
    20.     {
    21.         var filename = @"[build location]\scenebundle";
    22.         var sceneBundle = AssetBundle.LoadFromFile(filename);
    23.         var scenePath = sceneBundle.GetAllScenePaths().First();
    24.         SceneManager.LoadScene(Path.GetFileNameWithoutExtension(scenePath));
    25.     }
    26. }

    Result vs expectation
    If I then run the loading project from the editor, I expect the scene to load, the 'MyObject' to be present and all variables set as they were in the above attachment. However, the serialized struct is not shown and empty according to the console.
    SerializeLoader.png

    When we try to load the assetbundles in the same project as they were created, the result was as expected, so we think something is going wrong with the loading of assemblies vs the serialization in Unity. The code is loading as we can see the 'SerializeThis' class as component in the loading project.

    Any thoughts/advice on how to get the expected result?
     
    Last edited: Nov 30, 2018
    bx2sms likes this.
  2. Roelof

    Roelof

    Joined:
    Jun 25, 2013
    Posts:
    8
    I suppose the post was a bit too long to read easily, so I edited all code/images into spoilers. Hopefully someone can help me point to why the serialization is not present in the loading project.
     
  3. soumen

    soumen

    Joined:
    Jul 8, 2013
    Posts:
    8
    I'm also having the same issue...
     
  4. soumen

    soumen

    Joined:
    Jul 8, 2013
    Posts:
    8
    did you find any solution...
     
  5. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Having the same issue here in Unity 2018.4.4. Loading a scene or prefab with custom serializable class attributes does not work when the corresponding class is also loaded via reflection at runtime.

    For example, a custom UnityEngine.UI Button implementation click handler event is unable to maintain the serialized click handler callback as it comes through as null after loading the asset bundle.

    Anyone have any idea?
     
    Last edited: Jul 23, 2019
  6. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
  7. Ryanc_unity

    Ryanc_unity

    Unity Technologies

    Joined:
    Jul 22, 2015
    Posts:
    332
    caroliengilbers and slumtrimpet like this.
  8. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Chiming back in that I resolved this issue (for now) by implementing customer serializers:
    https://docs.unity3d.com/Manual/script-Serialization-Custom.html
    for the custom serializable class that was being dropped. It's an ugly hack but it keeps us going for now.

    I voted on and will keep an eye on that issuetracker item for a proper fix.
     
    caroliengilbers likes this.
  9. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    So it is a static/fixed implementation based on the specific type?
     
  10. SxWx

    SxWx

    Joined:
    Apr 13, 2013
    Posts:
    3
    Probably this is solution which slumtrimpet write about (at least it works) :

    Code (CSharp):
    1. [System.Serializable]
    2. public class SerClassSample
    3. {
    4.     public string Text;
    5.     public int Number;
    6. }
    7.  
    8. public class ExampleMonoBehaviour : MonoBehaviour, ISerializationCallbackReceiver
    9. {
    10.     [SerializeField]
    11.     private SerClassSample _test;
    12.  
    13.     [HideInInspector, SerializeField]
    14.     private string _testText;
    15.     [HideInInspector, SerializeField]
    16.     private int _testNumber;
    17.  
    18.     public void OnAfterDeserialize()
    19.     {
    20.         _test = new SerClassSample()
    21.         {
    22.             Number = _testNumber,
    23.             Text = _testText
    24.         };
    25.     }
    26.  
    27.     public void OnBeforeSerialize()
    28.     {
    29.         _testNumber = _test.Number;
    30.         _testText = _test.Text;
    31.     }
    32. }
    Also you can just serialize SerClassSample to json and save it to string field
     
    Last edited: Apr 23, 2021
  11. UnbridledGames

    UnbridledGames

    Joined:
    May 12, 2020
    Posts:
    139
    I see it's not fixed here either. Just posting so I can follow up on the thread if I find a solution. The solution posted above won't work if you need to serialize a List - which is the issue I'm dealing with. I'm gonna submit to ugly hacks and instead of a list, I'm going to add a MonoBehavior to my gameObject for each item thatwould be in the list, then instead of foreaching the list, I'll foreach a GetComponents<WhyWontYouSerializeYouBastard>().

    Ugh. Doing it that way makes me feel sick.
     
  12. Bshsf_9527

    Bshsf_9527

    Joined:
    Sep 6, 2017
    Posts:
    43
    i dont understand why you do this, monobehaviour contain all member that you need while you write them agin.
     
  13. bdovaz

    bdovaz

    Joined:
    Dec 10, 2011
    Posts:
    1,053
    Alex_Heizenrader likes this.