Standard Manager
Introduction
This manager uses AssetBundles and unity functions to load and update bundles, works online and offline, compatible with other store updates.
Modes
Classic mode
Smart mix. Bundles should be included with a standard game installation.
var streamingAssetsPath = Application.isEditor ? "../../Build/{Unity Project}_Data/StreamingAssets" : "";
// AssetBundles Init
var status = await ABStandardManager.Init(streamingAssetsPath, "http://wonderland.eode.studio/AssetBundles/Bundles");
if (status == ABStandardManager.EStatus.Ok) {
// Start game
}
else {
// Fatal error (cache, online and local data not found)
}
// load a prefab (select the object in asset bundle browser to see its path)
var prefab = await AssetBundles.LoadAsset<GameObject>("mybundle/name", "MyPrefab");
When the application starts:
- Local files and Online valid: compare online and local manifests, update local files if not equals.
- Offline: use local files. If no local file found, return the fatal error status.
- Online but no local files: download all data.
Automatically clear the Cache when the application is quitting.
Online mode
var status = await ABStandardManager.Init(null, "http://wonderland.eode.studio/AssetBundles/Bundles");
All bundles updates are downloaded in the game. A connection is required the first time (this case triggers the fatal error).
Offline mode
If your game is "asset bundles ready" but actually not used.
var status = await ABStandardManager.Init(Application.isEditor ? "../../Build/{Unity Project}_Data/StreamingAssets" : "");
Test your application (build mode)
You can test a final build in editor:
- Build asset bundles with the Asset bundles browser. The final folder name must be
{MyPlatform}
like "Windows" - Copy your
{MyPlatform}
folder in "{Build directory}/{MyProject}_Data/StreamingAssets" - Uncheck the "simulation" mode in "Wonderland/AssetBundles/Simulation" menu.
- Be sure the path is the right one in param of Init function
ABStandardManager.Init(Application.isEditor ? {This path} : "", ...)
On this screen, we export directly bundles in the build folder. For a big project with many data, we create a copy after. A future build or update from your server probably removes that exported files, so always make a copy if you have a lot of assets.
Prepare a final build
- Build your application.
- Build your bundles with asset bundles browser.
- If you have a bundle server, export your bundles on it. (we recommend to create a major version using an argument of the main url like "http://mysite.com/{version}/". You should create a project variable using Configuration Windows and an automatic url update using Prebuild)
- Distribute.
Debug
This is probably the hardest part of asset bundles.
Particles and effects
For missing materials, try to force the bundle to stay open. (remove it if there is no effect).
Use this solution with caution.
// on a scene loaded
AssetBundles.LoadBundle("fxs");
// on destroy
AssetBundles.UnloadBundle("fxs"); // note: this function is automatically called on a scene switch
Missing an object
If a bundled object (like scriptable or prefab) is null, try to replace the reference by an AssetField
Shader problem
Have you forget to add your shader in a bundle ? Sometimes, a material does not link automatically its shader.
Postprocess rendering
Find("shader") function not work in a build, it is an editor function. Load your shaders with AssetBundles like this example.
Post process example
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
using PPSP = MyProject.PostProcessShaderPreloading;
[Serializable]
[PostProcess(typeof(FullscreenMWaveRenderer), PostProcessEvent.AfterStack, "MyProject/FullscreenMWave")]
public sealed class FullscreenMWave : PostProcessEffectSettings {
public TextureParameter TextureNormal = new TextureParameter { defaultState = TextureParameterDefault.Black };
public TextureParameter TextureMWave = new TextureParameter { defaultState = TextureParameterDefault.Black };
public Matrix4x4Parameter CameraMatrix = new Matrix4x4Parameter();
}
public sealed class FullscreenMWaveRenderer : PostProcessEffectRenderer<FullscreenMWave> {
[RuntimeInitializeOnLoadMethod]
static void InitShader() {
PPSP.LoadShader("fxs", "FullscreenMWave");
}
public override void Render(PostProcessRenderContext context) {
var shader = PPSP.GetShader("fxs", "FullscreenMWave");
if (shader == null) return;
var sheet = context.propertySheets.Get(shader);
sheet.properties.SetTexture("_TextureNormal", settings.TextureNormal);
if (settings.TextureMWave != null) {
sheet.properties.SetTexture("_TextureMWave", settings.TextureMWave);
sheet.properties.SetFloat("_Tratx", 1f / settings.TextureMWave.value.width);
sheet.properties.SetFloat("_Traty", 1f / settings.TextureMWave.value.height);
}
sheet.properties.SetMatrix("_CameraMatrix", settings.CameraMatrix);
context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
}
}
PostProcessShaderPreloading
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
namespace MyProject {
public static class PostProcessShaderPreloading {
public static Dictionary<string, Shader> Shaders = new Dictionary<string, Shader>();
static async Task Add(string bundle, string name) {
await new WaitUntil(() => EODE.Wonderland.AssetBundles.Initialized);
await Load(bundle, name);
}
static async Task<Shader> Load(string bundle, string name) {
string path = bundle + "/" + name;
if (Shaders.ContainsKey(path)) {
return Shaders[path];
}
var shader = await EODE.Wonderland.AssetBundles.LoadAsset<Shader>(bundle, name);
Shaders[path] = shader;
return Shaders[path];
}
public static void LoadShader(string bundle, string name) {
PostProcessShaderPreloading.Add(bundle, name).WrapErrors();
}
public static Shader GetShader(string bundle, string name) {
var path = bundle + "/" + name;
if (PostProcessShaderPreloading.Shaders.ContainsKey(path)) {
return PostProcessShaderPreloading.Shaders[path];
}
return null;
}
}
}
TextMeshPro material rendering problem
Be sure TextMeshPro shader is in a bundle.