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
  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:
    338
    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:
    338
  7. Ryanc_unity

    Ryanc_unity

    Unity Technologies

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

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    338
    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:
    10
    So it is a static/fixed implementation based on the specific type?