
一般在场景切换时,因为要加载大量的资源,初始化大量的脚本,如果在主线程加载,会出现卡顿现象。而异步加载把加载过程放在子线程,这样就不会卡住在主线上的渲染,所以卡顿就会好很多。我们想要在游戏中动态的加载我们的资源,可以使用AssetBundle的方式或者是ResourcesLoad的方式。
那么如何使用AssetBundle呢
我们首先需要对我们的编辑器做一些小小的处理
1在Unity中增加一个打bundle的 *** 作按钮
在项目的Assets同级目录下创建一个Editor的文件,然后在新建一个脚本文件
引用官方的话
//Create a folder (right click in the Assets folder and go to Create>Folder), and name it “Editor” if it doesn’t already exist
//Place this script in the Editor folder
要把这个脚本放到Editor文件里才能正确运行 否则会报错 提示命名空间不正确。
这样我们的打包按钮就加好了,只要点击 *** 作就会走这个静态方法(BulidAssetBundle)进行打包。
其中打包主要是调用了BulidPipelineBuildAssetBundles这个方法。
BulidPipelineBuildAssetBundles主要使用三个参数来完成打包:
第一个是打包后的包体存放路径。
第二个是打包规则。
第三个是目标 *** 作系统。
第二个参数打包规则可以分为很多
//官方解释地址
[ >最近也在纠缠这些东西
Unity在这方面比较黑箱 有时候很困惑
比较特殊的就是这个Destroy
Destroy一个Asset的实例是可以的,但是如果Destroy一个Asset就会把这个Asset文件被摧毁。
对于Prefab,这种差异很好区分,应该Destroy那个Instantiate出来的Object
但是对于一些特殊的Asset,这个差异就不那么好理解了。
比如贴图,一般很少显式的去Instantiate创建实例,而是这样:
arenderermainTexture = AssetBundle1Load("贴图1")
brenderermainTexture = AssetBundle1Load("贴图1")
这种方法 其实是个引用 ,如果你Destroy这个AssetBundle1 那贴图1就没了 如果你Destroy这个a或者b的mainTexture,也是一样结果。
如果你
Texture tex = Instantiate( AssetBundle1Load("贴图1")) as Texture;
这个tex是可以被Destroy的 要实例一个贴图 导入的地方要标志为readable。
如果你循环:
arenderermainTexture = AssetBundle1Load("贴图2")
brenderermainTexture = AssetBundle1Load("贴图2")
不停加载新贴图,之前创建的贴图就成了无引用的游离Assets,会导致内存不断增加。解决办法 要么你自己记录每一次加载的对象,在不用的时候用ResourcesUnloadAsset(object)释放,简单的办法用一个ResourcesUnLoadUnusedAssets就能把这些没有指向的游离Asset全部释放掉,但是很慢。
如果概念不太清楚的,Destroy要慎用 除了Prefab
简单的说 Load的东西释放应该用UnLoad,Instantiate的东西才用Destroy,一一对应起来理论上就没有泄露。如果找不到当时那个Load的对象了就简单的ResourcesUnLoadUnusedAssets。Destroy一个asset等于删掉那个资源,奇怪官方论坛居然很多人建议Destroy texture,洋人也不都是干货。
downloadassetBundleUnload(true)这句一般就会Unload这个AssetBundle并且把关联的实例对象都清除。有这句理论上你不用Destroy。
另外内存回收不是即时的 我试过跟踪,发现Unity和Mono的GC工作并不是很效率,和标准net的GC有较大差距。之前曾经碰到过,连续Load Unload闪退的情况,后来发现GC没有及时生效,内存还是会突破限制,于是就在每个Unload后跟了一个GCCollect()
另外现在>手机很卡的话是由于手机的储存空间不足造成的
可以使用腾讯手机管家来进行下空间清理,这个软件的清理力度比较大
通过对手机上的垃圾和缓存进行全面的扫描,扫描之后可以进行一键清理
还能卸载一些不常用的软件并进行卸载残留的清理进一步释放手机空间最近被一个问题纠缠了好久,终于找到解决办法,这里做个记录。
我们做的一款游戏在编辑器里跑的好好的,一打包的手机上就各种崩溃;
而且是不确定什么时候出现,用logcat查看了系统日志,就看到是异常地址访问的log,没有什么有价值的信息。
重复试了好多次之后,发现每次进一个测试关卡的时候必闪退,于是一路上加日志,希望能知道是哪一句导致程序崩溃。
加到最后,场景加载完了,一切都正常。可以推断加载场景过程没问题,应该是在某一个组件脚本的update里面出问题的。
这下线索又断了,因为挂update的组件太多,而且不知道有哪些组件运行;这里就想到一个想法,我们以后的代码应该都由程序自己去调用update,
不要直接用u3d的update,这样我们可以很容易的知道哪些代码在运行,而且是可以保证调用次序的。
接着想了个办法,就是进场景后,逐个把有update的函数禁用,发现某个组件禁用后就不闪退了,于是问题定位到这个组件的update函数。
通过逐条的增加日志,最终定位到一个空引用访问上,导致程序在安卓机上闪退!怀疑是安卓sdk在运行时的jit直接变成了机器指令,导致可能的空异常。
这个问题让我很惊讶,原来以为会抛出空引用异常,没想到很c#的空指针访问一样会导致进程崩溃。于是组织大家把所有可能为空的地方排查可一遍。
另外在编辑器里没问题,是因为编辑器里加载资源是同步加载的,所以加载完直接使用加载后的对象是没问题的;
但是在手机上要从assertbundle中加载,使用了异步过程,会导致后续的访问可能存在访问空异常;
于是把编辑器里的加载也改成异步加载,编辑器中就能跟手机上一样的加载过程,尽量暴露手机上运行可能出现的问题
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)