unity中AssetBundle打包及使⽤总结(WebGL)
资源打包,教程很多。但,适合⾃⼰项⽬的打包⼜有⼏个?None
打包注意点:
(1)资源尽量分⽂件夹放置,便于打包资源的管理
(2)打包相对独⽴资源
(3)打包时,尽量只打包素材,且⼤⼩控制在10M左右,避免影响下载速度
(4)打⼊包的实例化物体,在其他脚本被引⽤的时候,通过查⽅式(名称会多个“(clone)”)。且实例化⼀定要⽐引⽤要早,避免出现访问空对象的问题。尽量实例化在Awake中,引⽤在Start中。
(5)共⽤资源、私有资源配合打包
共有资源打包,可⽤初始化代码统⼀管理。⽐如房间、⼈、⼱等。但是需要进⼊程序即开始异步下载,以免影响各常见的使⽤。
私有资源在进⼊对应场景时再下载,避免资源浪费;在场景卸载时,⼀定卸载私有资源。
(6)如果有 AssetBoudle的使⽤,保证在发布时,不勾选“Strip Engine Code*”,但是⽆⽤代码⼀定清理⼲净。
WebGl平台的资源打包:
⼀、标记资源(AssetBoudle名称,如xx.ab )
⼆、创建以下代码,放⼊“Asset—Editor”路径中
[MenuItem("AssetsBoundle/Build AssetBoudles")]
static void BuildAllAssetBoundles()
{
string strDir = "AssetBoundles";
if(Directory.Exists(strDir)==false)
{
Directory.CreateDirectory(strDir);
}
BuildPipeline.BuildAssetBundles(strDir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);
}
核⼼是BuildAssetBundles(strDir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);
采⽤Chunk的编译⽅法,是为了WebGl的下载、编译快速。平台要选择WebGL。
三、已打包的内容放置到服务器。
有可能服务器需要设置下(1) ⽂件格式的类型(2)跨域访问 (3)访问权限
四、运⾏程序时,启动协程,下载、加载对应资源
public List<string> bundleToLoadList = new List<string>(); //要下载、加载的所有资源路径
public List<AssetBundle> bundlesLoadedList = new List<AssetBundle>(); //已下载的资源列表
Dictionary<string, Object> allObjs=new Dictionary<string,Object>(); //所有预设体字典
List<Object> objsList = new List<Object>(); //所有预设体
public string strABUrl=@"192.168.1.110:80/boundles/"; //下载地址
void Start () {
StartCoroutine(load());
}
IEnumerator load()
{
foreach(string strBundle in bundleToLoadList)
{
string strurl = strABUrl + strBundle;
Debug.Log(strurl+" Time:"+Time.time);
//⽤using的⽅式,为了让web⾃⾏释放
using (WWW bundleW = new WWW(strurl))
{
yield return bundleW; //下载过程
if (bundleW.isDone && == null)
{
Debug.Log(bundleW.assetBundle.name + " downloaded success!" + " Time:" + Time.time);
AssetBundle assetBd = bundleW.assetBundle;
AssetBundle assetBd = bundleW.assetBundle;
bundlesLoadedList.Add(assetBd);
Debug.Log("bundle name:" + assetBd.name);
Object[] objs = assetBd.LoadAllAssets(); //加载过程
Debug.Log("loaded success!" + " Time:" + Time.time);
foreach (Object obj in objs)
{
if (!allObjs.ContainsKey(obj.name))
{
if (obj.GetType() == typeof(GameObject))
allObjs.Add(obj.name, obj);
}
else
Debug.Log("aready exist asset :" + obj.name + " type:" + obj.GetType() + " with type:" + allObjs[obj.name].GetType());
objsList.Add(obj);
}
}
else
Debug.Log("down load failed!--" + strBundle);
}
}
}
//强制卸载所有资源
public void ForceUnLoadAll()
{
if (bundlesLoadedList.Count == 0)
return;
for (int i = 0; i < bundlesLoadedList.Count;i++ )
{
if(bundlesLoadedList[i]!=null)
{
bundlesLoadedList[i].Unload(true);
bundlesLoadedList[i] = null;
}
}
for (int i = 0; i < objsList.Count; i++)
{unity 教程
objsList[i] = null;
}
objsList.Clear();
foreach (KeyValuePair<string, Object> obj in allObjs)
{
allObjs[obj.Key] = null;
}
allObjs.Clear();
}
五、在需要实例化的地⽅,进⾏实例化
public List<string> gameobjectsToInstantiate = new List<string>(); //需要的加载预设体的名称列表
BundleLoadMgr bundleLoadMgr = null; //资源加载器对象(上⾯代码的类)
void Awake () {
bundleLoadMgr = GameObject.Find("BundleLoadMgr").GetComponent<BundleLoadMgr>();
StartCoroutine(InstanceInstantiate());
// InstanceInOneLine();
}
IEnumerator InstanceInstantiate()
{
if (bundleLoadMgr != null)
{
foreach (string strObj in gameobjectsToInstantiate)
{
Object obj = null;
确保加载上后,再开始初始化所有物体
while(obj==null)
{
obj= bundleLoadMgr.GetGameobjectAssetByName(strObj);
yield return obj;
}
yield return Instantiate(obj);
}
}
}
协程实例化的⽅式,可能会造成其他脚本调⽤到本预设体时为空的问题。也可以在主线程实例化这些预设体,但是如果之前未下载完成的话,可能会卡住线程。两种⽅法各有利弊。尽量让预设体有⾃⼰的独⽴性,最起码预设体外的尽量少引⽤该预设体。
最后记着销毁⽆⽤的资源。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论