资源管理
Q1:字体作为多个资源的依赖包,会在游戏中被加载多次。我们现在有个问题,AssetBundle A资源依赖于这个字体,加载A的时候加载了一份字体,然后B资源也依赖这字体,而后加载B的时候我们没有去重复加载字体,这时候发现B资源上出现了字体丢失的现象。
请问加载资源的时候,Unity会自动去识别内存里是否有它的资源依赖包吗?如果有的话,为什么B加载的时候找不到已经存在内存中的字体?这里需要手动去做些什么处理吗?
同时我发现依赖包资源如果进行了bundle.m_AssetBundle.Unload(false)以后,其他依赖于这个包的资源就引用不到了。我们流程上对于每个读进来的AssetBundle,都会加载完后马上进行Unload(false),请问如果是依赖包的话,是不是不能对其进行这步操作?
Unity引擎是会自动根据依赖关系去搜寻依赖的资源的,但需要注意的是,依赖的AssetBundle文件必须存在。也就是说,依赖关系包如果后续还会使用的话,是不应该被Unload的,否则后续AssetBundle加载上来后,被依赖的资源是无法找到的。对于Unity 5.3之前的版本,出于内存的考虑,开发团队可以通过CreateFromFile或LoadFromCacheorDownload来加载AssetBundle,既可以保留AssetBundle之间的依赖关系,同时又不会产生Webstream。
开发团队可以参考你应该了解的AssetBundle管理机制,进一步了解相关API。
性能优化
Q2: 我在用Profiler真机查看iPhone App时,发现第一次打开某些UI时,Font.CacheFontForText占用时间超过2s,这块主要是由什么影响的?若iPhone5在这个接口消耗2s多,是不是问题很大?这个消耗和已经生成的RenderTexture的大小有关吗?
Font.CacheFontForText主要是指生成动态字体Font Texture的开销, 一次性打开UI界面中的文字越多,其开销越大。如果该项占用时间超过2s,那么确实是挺大的,这个消耗也与已经生成的Font Texture有关系。简单来说,它主要是看目前Font Texture中是否有地方可以容下接下来的文字,如果容不下才会进行一步扩大Font Texture,从而造成了性能开销。
资源管理
Q3:SkinnedMeshRenderer.BakeMesh这个函数一般是什么时候调用呢?在Instantiate后调用么?
SkinnedMeshRenderer.BakeMesh 的作用在于:将一个蒙皮动画的某个时间点上的动作,Bake成一个不带蒙皮的Mesh,从而可以通过自定义的采样间隔,将一段动画转成一组Mesh序列帧。而后在播放动画时只需选择最近的采样点(即一个Mesh)进行赋值即可,从而省去了骨骼更新与蒙皮计算的时间。
该方法的优点是用内存换计算时间,在场景中大量出现同一个带动画的模型时,效果会非常明显。该方法的缺点是内存的占用极大地受到模型顶点数、动画总时长及采样间隔的限制。因此,该方法只适用于顶点数较少,且动画总时长较短的模型。同时,Bake的时间较长,因此需要在加载场景时完成。
比较经典的适用场景为MOBA游戏中的小兵。
性能优化
Q4:我用Profiler.BeginSample统计到的数据与直接看Memory下的不一样,前者比后者的数据更大,这是为何? 用Profiler的API获取到的这一帧的内存消耗是85.6MB,而堆内存中显示的是62.9MB,这怎么理解?
Profiler.BeginSample
Profiler中数据
这种情况确实也是经常会遇到的。一帧中分配如此高的内存是会触发GC.Collect的,而Mono中显示的数值则是GC之后的Mono内存数值。
资源管理
Q5:将Shader独立打包,如果我在启动游戏的时候加载一次,那么之后切换场景是不是就不用每次都加载了?
确切地说,要达到后续Shader都不出现加载开销,需要满足以下两个条件:
(1)包含Shader的AssetBundle文件常驻内存;
(2)Shader已经全Load加载好;只要满足这两个条件,后续加载好的GameObject,但凡依赖于这些Shader的,都会直接拿来进行使用,而不会再有加载和解析开销。
原文出处:侑虎科技
转载请与作者联系,同时请务必标明文章原始出处和原文链接及本声明。