missing references after importing assetbundle with System.Reflection.Assembly.Load

I have a GameObject instantiated in a test scene in project A. The GameObject contains a script component. That script component is a MonoBehaviour class from a DLL which is contained in project A’s “Assets/Plugins” folder.

I am creating the following separate assetbundles:

  • bundletest1.assemblies - contains the DLL, renamed with a “.bytes” extension (since “.dll” files apparently can’t be included in assetbundles, due to them being an unknown asset type)

  • bundletest1.scenes - contains the scene file

In project B, I have some logic that loads these two assetbundles.

First, I’m loading the assembly bundle, which loads correctly. I’ve tested that the class functions from the DLL are working fine if I instantiate a new GameObject from inside the loading script, and add the DLL’s contained class as a new dynamic component, as per http://docs.unity3d.com/Manual/scriptsinassetbundles.html.

After loading the assembly bundle, I load the scene bundle, which has a few simple items in it, and it loads correctly as well, with one important exception. The GameObject that contains the script component comes up with a missing reference, instead of pointing to the class that I’ve brought over in the assembly bundle.

Furthermore, while project B is running (after the bundles are loaded as above), I can’t assign any of my DLLs classes to objects in the scene, even though they were just loaded and should be resident in memory. I don’t understand why this is the case.

How can I preserve the reference/GUID of the script from project A to project B?

If I copy the DLL directly into project B’s “Assets/Plugins” folder, the reference is preserved and my classes can be accessed without any problems. But the whole point of what I’m trying to do is to bring the DLL’s classes into project B via an assetbundle, using Reflection.

I must be missing one critical piece of the puzzle, but I’ve been working on this for more than a week and haven’t been able to figure out what I’m doing wrong. Any ideas?

No progress on this, I’m stuck! Someone must have an idea of how this is supposed to work. After I load an assembly is it supposed to stay around and be accessible? How am I supposed to make use of those classes if I can’t see them in the inspector at runtime? Is it possible I’m not loading them correctly, or possibly making the assetbundle incorrectly?

Is it simply not possible to use prefabs with scripts from AssetBundles?

Though I have not tried this myself, it seems to me that if you create a scene/prefab with an assembly built into the core code, Unity would expect that the scene/prefab would be loaded in a project using the same code.
If you’re loading an assembly at runtime, you probably need some other way of identifying what component classes you need to add.
Have you tried creating a component that exists in both projects that attach the desired component via reflection?
I’m not sure I’m making much sense.

Are you trying to use the editor to add these components, or are you doing it via reflection like I tried explaining above?

Thanks for your reply @ThermalFusion :slight_smile:

I’m not understanding how I’d do what you suggest. Can you explain further? My objective is to transfer an editor-created scene that includes prefabs with script components from project A to project B.

In project A I use the editor to add the components, then I save the scene, and create an assetbundle containing that scene.

If you’re suggesting that I should create another script that would load the target script via reflection, how would I then get the “other” script over to project B without having the same problem?

Or did I misunderstand?

You’ve established that loading an assetbundle that was created in one project that doesn’t have the same codebase as in the reading project doesn’t work. It seems noone else around here has any additional insight to share. So you need a way around this, right?
One way would be to recreate the script components in your loading project somehow.
So if you have a lightweight component that exists in both projects natively, this component should load properly.
You can set up this component with a string value containing the class name of the real component you wish to add.
Upon loading in your other project, this component would read this string and add the proper component derived from this string. But in order for this to work, you would indeed need some code that is shared natively between the projects.
Another way would be to pick prefabs clean of any non unity native components, and instead searilize this data out separately somehow. I have no idea how to go about this, but it would require cumbersome editor exporting/ runtime importing code on the other end.
I’m at my wits end, feels like I’m just ranting random words.
May I ask why you want to do this? What are you trying to gain by not having the assemblies included?

1 Like

Thanks @ThermalFusion for your continued thoughts!

I am actually including the assemblies. The whole problem is that they can’t be referenced in project B by prefabs I created in project A.

However, I may be starting to understand what you mean. I could have a component in both projects called something like “ComponentLoader”, which would contain the class name and non-default parameter settings for a dynamic class assigned to a prefab. In project A, I wouldn’t actually include the gameplay class, but instead I’d replace it with this ComponentLoader. Then at runtime in project A, it would dynamically replace itself with the actual intended component. Is that what you are thinking?

If so, it might work. I will try some testing in project A to see if I can create a ComponentLoader class that replaces itself with real gameplay classes at runtime.

Yes, that was what I was trying to convey :slight_smile:

Thanks for your thoughts. Here is my status:

I have been able to create the ComponentLoader class, which successfully replaces itself with another class at runtime, however I’m thinking that it seems like it will be too much overhead to have to serialize every variable and then re-typecast it when instantiating. Also, even loading the AssetBundles is hard to do efficiently, since now it needs to be done for each component, and not once per game or scene load. AssetBundles can’t be kept in memory and must be Unload()ed before the next one is loaded, or the 2nd one will fail with an error saying the file has already been loaded. But I can still only reference the contents from the immediate script where they’re in memory (before Unload()). So this would seem to require some kind of global cache of non-Unload()ed assetbundles… bottom line is this is getting uglier than I’d hoped it would be.

It seems much simpler to use a pre-game patching application to locate and download updated files and not worry about whether they have code or scenes or other assets inside.

My conclusion here is that AssetBundles are not practical for any serious use, unless you are absolutely sure you won’t ever need to change a line of code. This seems unlikely to me!

If you’re talking about putting new code inside them and patching your game just via AssetBundles, I’d agree it doesn’t seem worth the effort. If you’re not trying to patch code in runtime and just hold assets, they are absolutely beautiful.

Perhaps AssetBundles would be useful to stream in assets at runtime for the benefit of reducing initial download or application startup time, but these seem like very minor benefits. It also still fails to achieve the main goal that I was hoping to reach: creating a self-patching mechanism from within a running Unity application.

In today’s “post-Steam” game development environment, we all must continue to release code updates, bugfixes, patches, as well as storyline extensions, add-ons, and other product refinements on an ongoing basis. If we don’t, then nobody will play our games for very long.

This makes AssetBundles effectively “damaged goods” in my developer/publisher toolkit. They can’t be used effectively to update a game application over time. I’ll grant that they may have some limited use for specific kinds of content releases. But as soon as one script has to change, you’re going to need a full-fledged patcher application anyway. So why bother with AssetBundles at all? The patcher can take care of all your content updates as well as any program changes at the same time.

1 Like

True.
I just wanted to point out that there are uses for them. At the company Im working at we visualize a large areal of laser scanned terrain. the biggest chunk of data weve thrown at it was in excess of 300gb. we store them in chunks as assetbundles so we can load and unload the desired bits at will. invaluable for us.

I can see that for projects that include huge amounts of runtime data that doesn’t all need to be loaded concurrently, AssetBundles could be very useful.

1 Like