- Home /
Streamed Scene Asset Bundles in a Streamed Web Player Causing Crashes
Long-time viewer, first time-caller here.
I'm running into a perplexing issue involving streamed scene asset bundles in a streamed web player.
I'm working on a large web game, where we want to have the basic streaming of Unity for the first few scenes, followed by AssetBundle streaming for the remaining scenes (since the user chooses a location).
Each streamed scene asset bundle is about 20-40 Mb and contains 10 scenes + assets. These scenes also contain Beast Lightmap information.
However, when attempting to access the .assetBundle property of the downloaded bundle, the Web Player crashes. (and just how this makes it available to Application.LoadLevel isn't really clear).
Now, it's actually downloading properly, and the code is used for other types of AssetBundles across the game without any issue. I'm thinking it may have to do with the combination of both streaming types, but haven't figured it out yet.
Hopefully someone here has seen something similar before.
Here's the actual download code -
public IEnumerator PrepareLevelBundle(string bundleName)
{
DownloadData bundleDownloadData = AssetBundleLoader.Instance.OpenAssetBundle(bundleName);
yield return new WaitForSeconds(.1f);
while (bundleDownloadData.download == null || !bundleDownloadData.download.isDone)
{
loadingPercent = AssetBundleLoader.downloadProgress;
yield return new WaitForSeconds(.1f);
}
Debug.Log ("SceneLoader done downloading bundle");
// this magically makes the levels inside available to Application.LoadLevel
AssetBundle loadedBundle = bundleDownloadData.download.assetBundle;
Debug.Log("loadedBundle assigned.");
}
This yields & downloads the bundle itself fine, but it's in the
AssetBundle loadedBundle = bundleDownloadData.download.assetBundle;
line that the problem occurs.
This seems to only be when trying to load a scene itself - like I said, we're loading other assets from AssetBundles without any issue.
For the record, they're being built with:
BuildPipeline.BuildStreamedSceneAssetBundle(bundledScenes, targetPath + "/" + regionPath+".unity3d", BuildTarget.WebPlayerStreamed);
And the same loading code works fine in the editor itself.
For completeness (and probably to jump-start anybody new to this), here's the function that downloads the bundle - nothing special, just multi-platform convenience.
private IEnumerator OpenAssetBundleCoroutine(DownloadData dd)
{
Debug.Log("Loading asset bundle: " + dd.url);
// Use fancy logic to get the actual path
if (dd.url.IndexOf("file://") == 0 || dd.url.IndexOf("http://") == 0)
{
dd.download = WWW.LoadFromCacheOrDownload(dd.url, ASS_VER_NUM);
}
else if (Application.platform == RuntimePlatform.OSXWebPlayer || Application.platform == RuntimePlatform.WindowsWebPlayer)
{
dd.download = WWW.LoadFromCacheOrDownload(AssetBundleLoader.ASS_URL+"/AssetBundles/" + dd.url, ASS_VER_NUM);
Debug.Log("downloading bundle: " + AssetBundleLoader.ASS_URL + "/AssetBundles/" + dd.url);
}
else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.WindowsEditor)
{
dd.download = new WWW("file://" + Application.dataPath + "/../AssetBundles/" + dd.url);
}
else if (Application.platform == RuntimePlatform.OSXPlayer)
{
dd.download = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/../AssetBundles/" + dd.url, ASS_VER_NUM);
}
else if (Application.platform == RuntimePlatform.WindowsPlayer)
{
dd.download = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/../AssetBundles/" + dd.url, ASS_VER_NUM);
}
while (!dd.download.isDone)
{
Debug.Log("dd: " + dd.url + " at : " + dd.download.progress);
downloadProgress = dd.download.progress;
yield return new WaitForSeconds(.1f);
}
Debug.Log("Download finished: " + dd.url);
}
Is combining the two streaming types even a supported feature? Has anyone seen problems with Beast lightmaps and streamed scene asset bundles? Any information would be greatly helpful!
Interesting - I performed this with a test scene (cube & cylinder), and it worked without issue.
I'll have to keep trying to narrow it down to bundle content, since the scenes were built & loaded in the same fashion.
$$anonymous$$ore pieces co$$anonymous$$g into play here!
I tested it with a single scene per-bundle, and it works fine that way!
However, there are a lot of shared assets between the 10 scenes that I want to bundle, so this is not ideal.
It seems like the error only occurs with two or more scenes where assets are shared - it simply fails to load them.
Unfortunately, no - I changed our loading structure to pull out the common elements manually into separate bundles, then instantiate those in each scene.
This actually turned out to be a much better approach memory-wise, though it's a bit of a tradeoff of complexity and editor-readiness.
Answer by CgShady · Jul 22, 2013 at 08:52 PM
Hi,
I'm using this right now on a project a little too specific to share full code, but here's what I'm doing in a nutshell :
use preconpiler instruction for target specific locations (http://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html)
don't download and load when in the editor. Unity recommends to Resources.LoadAssetAtPath instead (http://docs.unity3d.com/Documentation/Manual/abfaq.html)
just like you, I use a singleton instance to use a Coroutine to download and load
I also manage the downloads in a stack to avoid having too many running at the same time (I'm actually unsure as to how many downloads can run at the same time, I do only one, as there also are the main levels being downloaded, and some other audio streaming running in my case)
Hope this help you guys.
Here's my code :
private IEnumerator LoadSceneFromAssetBundle (string sceneFilename_, bool downloadOnly_)
{
string filename = sceneFilename_ + ".unity3d" ;
AssetBundle bundle = new AssetBundle ();
#if UNITY_EDITOR
// not using this if in the editor
#elif !UNITY_WEBPLAYER
string url = System.IO.Path.Combine(Application.streamingAssetsPath, "AssetBundles/AdditionnalScenes/" + filename) ;
#else
// if in WebPlayer, Streaming Assets are not supported, but the path will work relative to the unity file
string url = "StreamingAssets/AssetBundles/AdditionnalScenes/" + filename ;
#endif
#if !UNITY_EDITOR
WWW download = WWW.LoadFromCacheOrDownload (url, 1) ;
yield return download ;
if (download.error != null)
{
Debug.LogError(download.error);
return false ;
}
bundle = download.assetBundle ;
#endif
if (!downloadOnly_)
{
AsyncOperation async = Application.LoadLevelAdditiveAsync (sceneFilename_) ;
yield return async ;
}
else
{
yield return new WaitForSeconds (1.0f) ; // if in the editor and download only, IEnumerator needs to return something
}
if (!bundle)
bundle.Unload (false) ;
}
Your answer
Follow this Question
Related Questions
How to import the object from server to unity 2 Answers
How to build asset bundle without dependencies? 1 Answer
Streaming Tutorial anywhere? 2 Answers
Can I set an Asset as Addressable at Runtime? 0 Answers
Addessable asset download once 0 Answers