I feel like I’m mashing my head against a wall looking for an answer to something so seemingly trivial.
Here is what I want to do and how I think it would work:
// Start off my build stack
BuildPipeline.PushAssetDependencies();
// Build the player so that dependencies are captured
BuildPipeline.BuildPlayer(scenes, playerPath, BuildTarget.WebPlayer, BuildOptions.None);
// Mark the dependencies from the player build
BuildPipeline.PushAssetDependencies();
// Loop through my bundles and make them
foreach (Object obj in bundleObjects) {
// Start a bundle-local stack
BuildPipeline.PushAssetDependencies();
// Build a bundle with dependencies from the player extracted
BuildPipeline.BuildAssetBundle(obj, null, bundlePath,
BuildAssetBundleOptions.CollectDependencies |
BuildAssetBundleOptions.CompleteAssets |
BuildAssetBundleOptions.DeterministicAssetBundle);
// End the bundle-local stack
BuildPipeline.PopAssetDependencies();
}
// End the player dependencies stack
BuildPipeline.PopAssetDependencies();
// End the build stack
BuildPipeline.PopAssetDependencies();
However, when I do this my bundles refuse to load and I get:
The referenced script on this Behaviour is missing!
UnityEngine.AssetBundle:get_mainAsset()
BUT, if I comment out all the PushAssetDependencies() and PopAssetDependencies() it works perfectly fine. The only problem at that point is that my bundles are bloated in filesize with redundant data that is already in the player.
My bundles are complex prefabs with various linked meshes/textures/scripts, which store mostly unique data, however have a couple common textures that are shared with the main player binary.
I’m assuming I’m missing some key detail, please help!
what I read does not make much sense, this is what happens:
BuildPipeline.PushAssetDependencies();
//AFAIK build player is not affected by push and pop, however I could be wrong
//if I am wrong, this means that from now on the entire client is used as
//shared asset for the other assetbundles (that does not make sense :))
BuildPipeline.BuildPlayer(scenes, playerPath, BuildTarget.WebPlayer, BuildOptions.None);
// this is meaningless again, just because you do a push and pop inside the for already, pick up one or the other option
BuildPipeline.PushAssetDependencies();
foreach (Object obj in bundleObjects) {
// doing this the AB will not share any asset between them
BuildPipeline.PushAssetDependencies();
BuildPipeline.BuildAssetBundle(obj, null, bundlePath,
BuildAssetBundleOptions.CollectDependencies |
BuildAssetBundleOptions.CompleteAssets |
BuildAssetBundleOptions.DeterministicAssetBundle);
BuildPipeline.PopAssetDependencies();
}
BuildPipeline.PopAssetDependencies();
BuildPipeline.PopAssetDependencies();
What one usually wants instead is a process similar to this (I will use pseudo code to be quick):
Push
build all the assetbundles (I build
only texture and meshes)
Push
build all the scenes
Pop
Pop
build client
although if the client is affected by push and pop you can also try:
Push
build all the assetbundles (I build
only texture and meshes)
Push
build client
Pop
Pop
In this way what happens is that all the assets are shared between the scenes (take in account that I bundle all the scenes as well). I never tried to use push and pop with the client but it could work as well. In every case you first push the dependencies and then you build your scenes/client.
However be careful, all the resources between the dependencies are shared as well, so or your will be sure that they do not actually share any asset (that’s why I bundle tga and fbx) or you need to be sure that you load everything back (which is probably your case?)
The rule is to remember that everything is under a push/pop block you use the the dependencies of the parent block but you do not share the dependencies in side the block itself
eg:
push
foreach asset
{
push
buildasset
pop //forget the dependencies built since last push
}
buildclient //will not use any dependency
pop
Looks like the answer is that you cannot build the player that way. The way recommended to me by Unity premium support was to use a separate bundle with the shared dependencies which is built first. After that, build the bundles, and then build the player last.
The built player would then rely on the downloaded bundles, and work out okay. I am going to go test this now.