经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
AssetBundleMaster_ReadMe_EN
来源:cnblogs  作者:tiancaiKG  时间:2019/9/10 10:31:01  对本文有异议

  Before we start use it, you'd better import it to an empty project, following the ReadMe to learn this framework step by step.

  Let's see the folder structure :

 

It has 4 folders in the AssetBundleMaster folder:

  [AssetBundleMasterExample] is Demo for leaning basical APIs, It include load assets, load scenes, and how to do unload.

  [AssetBundleMasterExample2] is Demo for testing how Built-In Shader multi compiled and how AssetBundleMaster to optimize it.

  [Editor] is editor scripts.

  [Plugins] is runtime scripts, asset load is basic logic for a project, so we put it in Plugins.

Let's try to run API Demo scenes in Editor Mode, open AssetBundleMaster Window first :

window shows :

We need to set only 2 variables can make it run in Editor, developer friendly, ignor other options now : 

  1. Editor Asset LoadMode : load mode in Editor, select AssetDataBase_Editor, it means load asset directly.

  2. Build Root : It is the root folder for loading assets, click [Change Build Root...]  to change the folder, set to AssetBundleMasterExample so that we can run API Demo scenes. The entry scene is StartScene1, you can find it in AssetBundleMasterExample/Scenes folder:

 

Run StartScene1, the bottom-left shows a dropdown for selecting demo scenes : 

 

  These are all the API demo scenes, select any scene, you can see the hierarchy that a GameObject has the same name with the scene, and the same named script attached on it, check it.

  We must explain how the scene load proccess working, when we select any scene it will unload all assets loaded before, so that any asset will be loaded in the new scene will be new loaded, this is convenient for testing asset load and unload, you can open Profiler window to check all the time. The unload proccess has a padding time such as you changed the scene, it will trigger unload. You can see Hierarchy select [AssetLoadManager] GameObject and the inspector will shows it : 

Change the scene, then you can see [AssetLoadManager] Inspector has a count down Slider:

  If you use Profiler : Memory > Detailed > Take Sample to check assets in memory, check after the unload proccess done.

  Let's see every demo scene and how to use APIs, we set the Build Root path, so all the asset load paths are relative path from it, the assets in this folder are called main assets that commonly are the assets should be load by your script, like Scenes, and assets not in this folder called referenced assets like Meshes will not be load directly by your code, so you don't need to put all assets into the Build Root. keep this in mind.

  PS : when using AssetDataBase_Editor mode, it has no asynchronous loading, all asset loading will be sync load because we use AssetDataBase.LoadAssetAtPath as Editor load function.

  You can check what kinds of assets we have in the AssetBundleMasterExample folder.

  After all the setting was done for Editor load, not so much things to learn, if you want it work for your project,  only to set Build Root to your asset folder.

  Now you can see AssetBundleMaster generated a file in your Resources Folder, this is the basic setting of AssetBundleMaster, you just upload it for other teammates can use it : 

  Let's start learn how to use API by Demo scenes. How to create AssetBundle written at the end.

 

1. Example_LoadAsset (Script : Example_LoadAsset.cs)

  This Demo shows how to load common assets, loading with ResourceLoadManager .

  

API (namespace AssetBundleMaster.ResourceLoad): 

  ResourceLoadManager.Instance.Load<T>(string loadPath)

  ResourceLoadManager.Instance.LoadAsync<T>(string loadPath, System.Action<T> loaded)

  ResourceLoadManager.Instance.LoadAll<T>(string loadPath)

  It load assets in Sprites and Textures folder, the path "Sprites/Pic1" is kind of special, let's see : 

  It contains 3 assets have the same asset name Pic1.jpg / Pic1.png / Pic1.txt, in this situation our asset load API use no ext name path to load assets, so these 3 assets have the same load path, the API can load asset by limit its type, for example ResourceLoadManager.Instance.Load<TextAsset>("Sprites/Pic1").text; loaded the first TextAsset in the path, and ResourceLoadManager.Instance.LoadAll<Sprite>("Sprites/Pic1"); load all Sprites from this path, if you change "Sprites/Pic1" to "Sprites" that targeting the folder, it will also load asset, the logic is the same as UnityEngine.Resources load API. This feather solved the problem when in Android load from StreamingAssets that has no way to load all assets from target folder.

  Tips for AssetBunlde load mode : if you are loading asset async, and a sync requst happened while the asset is still loading, the Console will pop an error message, but the function still work. see below :  

Load Sync while Async loading

  This is because Unity has no provide any API for stop an AssetBundle async load, and load sync while async loading will pop error, the AssetBundleMaster Low-Level API handles it to ensure all call backs and returns working correctly. you don't need to worry about it.

  Other APIs can be check in ResourceLoadManager.cs, include Generic and Non-Generic version, convenient for users using Lua script.

 

2. Example_LoadPrefab (Script : Example_LoadPrefab.cs)

  This demo shows how to load and Instantiate GameObjects. load with PrefabLoadManager.

API (namespace AssetBundleMaster.ResourceLoad): 

  PrefabLoadManager.Instance.Spawn(string loadPath, string poolName = null, bool active = true)

  Spawn is to load and Instantiate GameObject.

  PrefabLoadManager.Instance.SpawnAsync(string loadPath, System.Action<GameObject> loaded = null, string poolName = null, bool active = true)

  SpawnAsync is to load Async and Instantiate GameObject.

  PrefabLoadManager.Instance.LoadAssetToPoolAsync(string loadPath, System.Action<GameObject, GameObjectPool> loaded = null, string poolName = null)

  LoadAssetToPoolAsync  is to load prefab asset Async to target pool.

 

  PrefabLoadManger using objectpool to control the instantiated GameObjecs. you can check PrefabLoadManager.cs, the asset load is based on ResourceLoadManager. 

  You should always load and instantiate GameObject with these API(UI, Particle Effect, Weapon...etc), with PrefabLoadManger you are not only get benefit from ObjectPool, but also get auto resources control.

 

3. Example_LoadScene (Script : Example_LoadScene.cs)

  This demo shows how to load scenes, be aware no need to add scenes to Build Settings, developer friendly. If no special needs you should not add scenes to Build Settings when publish app.

  Don't add any scene to  Build Settings, the scene load is like asset load which using relative load path.

API (namespace AssetBundleMaster.ResourceLoad): 

  SceneLoadManager.Instance.LoadScene(string sceneLoadPath,

    AssetBundleMaster.AssetLoad.LoadThreadMode loadMode = AssetBundleMaster.AssetLoad.LoadThreadMode.Asynchronous,

    UnityEngine.SceneManagement.LoadSceneMode loadSceneMode = LoadSceneMode.Single,

    System.Action<int, Scene> loaded = null )

  It do load scene like an asset using its relative load path, can load with async/sync mode and LoadSceneMode. Please notice it that load scene must wait for the call back UnityEngine.SceneManagement.SceneManager.sceneLoaded that means no matter load scene Sync or Async, you'd better wait for loaded call back.

  It returns a hashcode as handler of this scene.

 

4. Example_SpawnDespawn (Script : Example_SpawnDespawn.cs)

  This demo shows how the objectpool do spawn and despawn GameObject.

API (namespace AssetBundleMaster.ResourceLoad): 

  PrefabLoadManager.Instance.Spawn(string loadPath, string poolName = null, bool active = true);

  PrefabLoadManager.Instance.Despawn(GameObject go, string poolName = null);

  We do auto load and Instantiate prefab, and set active when spawn a GameObject, with the set poolName you must despawn GameObject to the same pool where it spawn from. The GameObject will be set active false while despawn to pool, if you have spacial needs, rewrite the code at AssetBundleMaster.ObjectPool.GameObjectPool.Despawn.

 

5. Example_SpawnPoolAndUnload (Script : Example_SpawnPoolAndUnload.cs)

  This deom shows how to destroy GameObject and how's the auto unload working.

 

API (namespace AssetBundleMaster.ResourceLoad): 

  PrefabLoadManager.Instance.DestroyTargetInPool(string loadPath, string poolName = null, bool tryUnloadAsset = true);

  This API is to destroy a target all spawned GameObject from target Pool, the mark of the asset is the load path, and with target poolName. if tryUnloadAsset is true, PrefabLoadManager will do check referenced assets, if all pools do not reference to the prefab asset, it will do unload asset proccess.

  PS : click [Spawn Cubes] button in scene, there are 2 pools was created, and every pool create some Cubes, see Hierarchy there are some Cubes was set no parent, it just for telling you that the connection of spawned GameObject to pool will not be break from parent changed. GameObject still controlled by pool even not child of the pool in Hierarchy.

  click [DestroyCubesInPool:MyCubes[1]] button, the MyCubes[1] pool will destroy all Cubes controlled by it, we can see pool is alive but spawned cubes was destroied.

  The asset(prefab) is still referenced by MyCubes[2] pool, so it will not trigger the unload asset proccess, click [DestroyCubesInPool:MyCubes[2]] button, now all GameObjects was destroied, see [AssetLoadManager] inspector, unload asset was triggered.

  So that PrefabLoadManager can auto control the resources.

 

6. Example_UnloadAsset (Script : Example_UnloadAsset.cs)

   This deom shows common asset unload proccess. the API is to unload asset :

API (namespace AssetBundleMaster.ResourceLoad): 

  ResourceLoadManager.Instance.UnloadAsset(string loadPath, System.Type systemTypeInstance, bool inherit = false);

  ResourceLoadManager.Instance.UnloadAsset<T>(string loadPath, bool inherit = false);

  Unload asset is not like UnityEngine.Resources.UnloadAsset , the parameter is not the asset, but the load path + load type, this is because to load the same asset it may have diferent load types, for example a picture can be load as Texture2D or Object, so the unload logic is also the same. The unload type can be inherit, like the picture shows above, ResourceLoadManager.Instance.UnloadAsset<Object>("Sprites/Pic1", true); means to unload all type inherit from Object that load from path "Sprites/Pic1", and the ResourceLoadManager.Instance.UnloadAsset<Sprite>("Sprites/Pic2", false); means only to unload Sprite type load from "Sprites/Pic2". this API is more accurate than the UnityEngine.Resources.UnloadAsset.

  This API is privide a flexible asset unload logic that it do reduce the reference count of assets, if any asset reference count was set to 0, the unload proccess will be triggered. if you set all references of assets to null, the assets will be unloaded, but if not, the ResourceLoadManager holds weakreference to the assets too, and someone request the same asset next time, ResourceLoadManager will return the weakreferenced target and no need to reload asset, this is the core logic to make sure asset will not duplicated in memory.

  Unload procccess based on Resources.UnloadUnusedAssets(); we are not sure it will spike your runtime or not, in middle-class project it is unnoticeable, if it works smooth, all project members will not need to do overhead jobs to do resource control. Just load and unload by your need, no mess on resource control.

  If it do spike your project, you can adjust the unload padding time and unload assets at appropriate time, you can still get benefit from no duplicated assets.

  Adjust padding time : AssetBundleMaster.AssetLoad.AssetLoadManager.Instance.unloadPaddingTime

 

7. Example_UnloadScene (Script : Example_UnloadScene.cs)

  This demo shows unload scene features, scene loading can have both async and sync proccess, the scene loaded event is triggered by SceneManager.sceneLoaded, so to unload scene is a little complex : 

API (namespace AssetBundleMaster.ResourceLoad, AssetBundleMaster.AssetLoad): 

  AssetLoadManager.Instance.UnloadLevelAssets(int hashCode);

  This is a Low-Level API to clear scene assets, it only works in AssetBundle mode, and only can clear AssetBundle serializedfile which scene referenced, if you don't load scene again while this scene exists, and the serializedfile was eat up your memory, you can call it but we recommand don't call it, it may cause asset duplicated. This example is to show if you call this function and load scene again, the assets in memory will duplicated(if you don't unload any scene).

  SceneLoadManager.Instance.UnloadScene(int id, System.Action<Scene> unloaded = null);  

  The scene load API ( SceneLoadManager.Instance.LoadScene ) retuen a HashCode, UnloadScene is use this HashCode. and the unload asset proccess will triggered if any scene asset can be unload. it is also auto resource control. The scene load has async proccess, the unload flow chart is like below(if not AssetBundle mode, no AssetBundle step) : 

 

  The Async loading may be :

  1. Async load AssetBundle

  2. Async load Scene

  3. Wait SceneManager.sceneLoaded called no matter load scene Async/Sync

  So the UnloadScene function wrapped all situations to make sure unload request work at any loading step.

  This is to test UnloadScene function, it do load scene Aync and unload after Wait Frames, change to 1,2,3...etc, can see in all step it works.

  

  Thats all the Asset load, GameObject load, Scene load and unload logic, controlled by only 3 managers:

  1. ResourceLoadManager

  2. PrefabLoadManager

  3. SceneLoadManager

  if you run in editor mode, some tests may not work as well such as Async load and asset duplicate. Let's start build AssetBundle, and runs it in Editor and published app.

 

--------------------------------------- Build AssetBundles -----------------------------------------

  Open the AssetBundleMaster Window

 We have 5 load modes, and have 3 published asset load modes.

  1. Resoueces mode: used as default Resources load mode, meaningless for us.

  2. AssetBundle_StreamingAssets mode: load AssetBundle from StreamingAssets.

  3. AssetBundle_PersistentDataPath mode : updatable resource mode, load from PersistentDataPath, if no asset in PersistentDataPath, load from StreamingAssets.

  4. AssetBundle_EditorTest mode: load from temp AssetBundle folder, build AssetBundle will build to temp folde (Editor Only).

  5. AssetDataBase_Editor mode: no need to build AssetBundle, load asset directly (Editor Only).

 

  Let's check all the settings on AssetBundleMaster Window :

  1. Editor Asset LoadMode (EnumPop) : Asset load mode in Editor.

  2. Runtime Asset LoadMode (EnumPop) : Asset load mode in Published.

  3. Platform Selection (EnumPop) : AssetBundle target platform, click [Set Current Platform] can set to current platform.

  4. Set Bundle Version (Text) : The version of AssetBundle.

  5. BuildAssetBundleOptions (EnumFlagPop) : BuildAssetBundleOptions.

  6. Build Update File (CheckBox) : Create Patch between versions, Patch file is Josn, serialized from AssetBundleMaster.AssetLoad.LocalVersion.UpdateInfo.

  7. Clean TempBuildFolder (CheckBox) : Clear any file in temp folder not in this build.

  8. Built-In Shader Collection (Scroll View CheckBox) : Deal with Built-In Shader, no multi compiled.

  9. Build Root (Label, Button) : Root folder, asset in this folder can be load.

  10. Step1 Clear Old Datas (Button) : Clear all AssetImporter.AssetBundleName.

  11. Step 2 Set AssetBundle Names (Button) : Auto set AssetBundleNames, some asset auto proccess. see appendix.

  12. Step 3 Start Build AssetBundles (Button) : Start Build AssetBundles.

  13. Custom BundleNameSettings (Scroll View) : Custom force set all files in target folder to a same AssetBundleName.

  14. Search Target Asset By AssetBundle Name :  Search AssetBundleName files, Debug.

 

  That's all settings. Let's set editor load mode and runtime load mode to AssetBundle_StreamingAssets, this is the most simple publish mode. and click : 

  Step1...

  Step2...

  Step3...

  It will auto build AssetBundle for you. every step shows tips : 

Step1

Step2

Step3

  When build finished, It will ask you to copy built AssetBundles from temp folder to StreamingAssets? Yes.

  You can see StreamingAssets got built AssetBundles :

   So the AssetBundle build successed, if you run in Editor, just open the StartScene1, repeat the API tutorial again. This time the Async load is working.

  And the [AssetLoadManager] shows different if you noticed : 

AssetDataBase_Editor no AssetBundle load

AssetBundle_StreamingAssets loaded AssetBundle

   We did successed building AssetBundles and load AssetBundle in Editor, if we want to publish it, make sure your Platform Selection correct, the next one is very important, scene and the Build Settings : 

  When you pubilsh your project, there is no need to add any scene to build Settings, because the scenes in Build Root folder will be built to AssetBundle, and any scene added to Build Settings will be packed to Resources too. So how to publish the app and load the StartScene1 as default scene? there are 2 ways :

  1. Add entry scene to scene build as default scene

 

  2. Or you can use the [UnityEngine.RuntimeInitializeOnLoadMethod] attribute to load the entry scene.

  You should add this code to any script yourself. This is pretty good to avoid scene build duplicated.

  No need to add any scene, just build it and run. it is quite simple to build App.

 

 

  Now let' me explain the function 8. Built-In Shader Collection, change the Build Root to AssetBundleMasterExample2 : 

 

  And chagne the version to 2.0.0, We Built 1.0.0 before, so Exists Versions shows 1.0.0 Exists, check the Build Update File, we can see Patch file will be generated later. Build Root is AssetBundleMasterExample2, let's see what is in this folder :

  There are 44 materials were used in the Example_ShaderCollection scene, they all used the Standard Shader :  

  These materials may cause the issue. We need to change the entry scene to StartScene2, it will load Example_ShaderCollection, now change the entry scene :

  1. Change the entry scene by Build Settings

  2. Or change code

  Do build AssetBundle Steps again,

  Step1...

  Step2...

  Step3...

  This time the Step3 shows new tips :

  This is because we built 1.0.0 version bundles already, and if we create 2.0.0 version it can be a incremental build, it will be faster than build a totally new version. But this build is to build AssetBundleMasterExample2, is totally diferent with AssetBundleMasterExample, no shared assets, so whatever you choose, it will build a totally new version.

  So the function 7. Clean TempBuildFolder (CheckBox) is used for it, if checked, the temp folder will do clean files that not in this version.

  After the build AssetBunlde finished, we build app to check what happened at the runtime. don't forget to select the [Development Build] and [Autoconnect Profiler] in Build Settings. My platform is macro soft windows 10.

Total AssetBundle size : 11.2MB

The task manager shows the app runtime memory : 219.7MB

Profiler

Profiler : ShaderLab 62.9MB

Profiler : Shader > Standard was compiled many times

  This issue happend on Standard Shader, let's use the Shader Collection to collect Standard Shader, and build a 3.0.0 version, the shader changes will not cause the changes of referencing assets, so we must select the ForeRebuildAssetBundle on BuildAssetBundleOption, otherwise we will lost the reference of materials : 

  PS : the default setting of BuildAssetBundleOption is ChunkBasedCompression, it is just for building AssetBundle faster, you can change the settings by your need, and the setting serialized files is in the editor folder shows below, you can upload to SVN share to your teammate : 

  Do build AssetBundle Steps again,

  Step1...

  Step2...

  Step3...

  And build app to run :

Total AssetBundle size : 2.62MB VS 11.2MB

Task manager shows runtime memory 81.6MB VS 219.7MB

Profiler

Profiler : ShaderLab 4.8M VS 62.9MB

Profiler : Shader > Standard compiled once only.

  You can see the big different between 2.0.0 and 3.0.0, this issue mainly caused by Built-In Shader, so the shader collectoin is used for Built-In Shader, other shader s in project can be packed to AssetBundle automatically, they will not cause this problem.

  All tests was tested on Unity5/Unity2017/Unity2018/Unity2019, nearly got the same result.

 

  Let's take a look at AssetBundle temp folder, it is at the same layer as the Assets folder, in the AssetBundles folder :

  The patch file was generated between versions, it is a update list, serialized from AssetBundleMaster.AssetLoad.LocalVersion.UpdateInfo, json format.

  If you are using AssetBundle_EditorTest mode, it load AssetBundles from temp folder, you can switch load between built versions easily, just change the [Platform Selection] and [Set Bundle Version] : 

 

  Other functions in the Tools Bar: 

  1. Copy built AssetBundle from temp folder to StreamingAssetsfolder :

  

  This is the same function as to the AssetBundle build finished tips.

  

  2. Clear AssetBundleMaster serialized datas :

  

  It will clear the generated settings files said before, AssetBundleMaster can not run without  these files.

 

  These are all about AssetBundleMaster, it was designed for small or middle-class projects and provide the convenience and correctness for your project, give you a friendly developing flow chat. we are insist on : don't set assetbundle manually, even though your project has special need for updating or something else, in most cases they don't match the requirment of the engine. Have Fun.

 

Appendix

  Auto asset processing, the Editor code written in AssetBundleBuildWindow.cs, we do proccess some assets : 

  1. SpriteAtlas, you can not create SpriteAtlas yourself in Unity5, it can be created after Unity2017, code in AssetBundleBuildWindow::1759 line, CreateSpriteAtlasAssets function, it do set all Sprites with same Packing Tag to the same AssetBundle, avoid the SpriteAtlas duplicated(works in Unity5). The Packing Tag is the basis for packing AssetBundle, but in Unity2019 the Packing Tag do not shows up in the Inspector, but it exists in the serialize file. AssetBundleMaster overwrite the Inspector for it, Packing Tag was added, the script is TextureImporterInspector.cs : 

Unity5

Unity2019

  

Unity2019 AssetBundleMaster overwrite Inspector

  In some cases the [Include in Build] info of SpriteAtlas may lost(for exp AssetBundle update), ResourceLoadManager added a callback to UnityEngine.U2D.SpriteAtlasManager.atlasRequested as a fallback to ensure the Sprites will be load correctly, if you got the issue that can not load Sprite, debug the ResourceLoadManager.RequestAtlas function(Unity2017 or newer).

 

 SpriteAtlas [Include in Build] setting(Unity2017 or newer).

  2. EditorConfigSettings, some of the editor settings will be set, you can take a look codes at AssetBundleBuildWindow::1676 line, EditorConfigSettings function, it did set the UnityEditor.EditorSettings.spritePackerMode for create SpriteAtlas, and change GraphicsSettings > Lightmap Modes to Custom mode, for preventing the LightMap info being stripped while build AssetBundle : 

    

  3. TerrainData, the used textures must set to isReadable(Read/Write Enabled in AssetImport Inspector), or it will pop error message after AssetBundle built.

  4. Shader Collection, prevent multi packing and multi compiled for Built-In Shaders, reduce AssetBundle size.

  

原文链接:http://www.cnblogs.com/tiancaiwrk/p/11459536.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号