开启Read/Write Enabled一般是用于运行时修改Mesh的顶点数据,开启这个选项会导致Mesh的内存占用翻倍。因此如果项目中不需要在运行时修改这些Mesh数据的话,建议把这个选项关闭。除了需要脚本中访问的网格,作为网格碰撞器中的网格,脚本中用StaticBatchingUtility.Combine静态合批的网格,以及粒子系统发射的网格之外,其它模型建议不要勾选此项 ,否则会在内存也保留一份网格实例占用内存。
开启纹理导入设置中 Read/Write Enabled,纹理在传到GPU之后,CPU端的数据也会一直保留在内存中。因为在移动端显存共享内存,会导致内存占用加倍。因此需要注意是否有需要在CPU端访问的纹理,比如:需要通过脚本获取纹理像素的情况下,就要开启纹理导入设置中的 Read/Write Enabled。
Unity默认的Animation Type是Generic,对包含动画数据的FBX文件是适用这个选项的。但是如果FBX文件中没有包含动画数据,而只是普通静态Mesh的话,设置为Generic会导致引擎自动为这个Mesh的GameObject添加一个Animator组件,导致不必要的消耗。因此对于不包含动画数据的模型文件,建议把这个选项设置为None。
对3D物体,关闭Mipmap会导致远处的纹理有闪烁感,而且渲染性能较低,因此建议开启3D物体上纹理的Mipmap。开启Mipmap的缺点是会导致纹理的内存占用更大。对2D物体,Mipmap并不会导致闪烁和性能问题,所以建议关闭2D以及UI纹理上的Mipmap选项。
建议开启Optimize GameObject,这个选项可以把SceneManager中用于skinning的节点都去除,节省了场景节点树更新以及查询的CPU消耗,对于需要做挂点的节点可以添加到例外列表中。
不需要使用Unity内置音频模块的时候,建议Editor中通过勾选Edit->Project Settings->Audio->Disable Unity Audio来完全禁用FMOD模块,避免不必要的CPU消耗。
建议改为用InstanceID来判断即Object. GetInstanceID,运行期间保证唯一。 因为Object的判等还有额外的耗时操作,而Int类型的判等就非常快速了。同理,使用Object作为key的数据结构也建议改用InstanceID做key。
IL2CPP就sealed的类或函数会有优化,变虚函数调用为直接函数调用。详见《IL2CPP OPTIMIZATIONS: DEVIRTUALIZATION》。
if(myDictionary.Contains(oneKey))
{
MyValue myValue = myDictionary[oneKey];
// todo
}
但其可减少冗余的哈希次数,优化为:
MyValue myValue;
if(myDictionary.TryGetValue(oneKey, out myValue))
{
// todo
}
低更新频率,如设定移动阈值,更新频率等
场景切换时避开峰值
问题:当前一个场景还未释放的时候,切换到新的场景。这时候由于两个内存叠加很容易达到内存峰值。
解决方案:在屏幕中间遮盖一个Loading场景。在旧的释放完,并且新的初始化结束后,隐藏Loading场景,使之有效的避开内存大量叠加超过峰值。
使用struct或enum做key的dictionary,在使用TryGetValue()或者键值访问时,会分配内存。 以下方法可以避免这种情况:
1) 自定义的struct作key,struct需要实现 IEquatable接口
2) enum 作key麻烦一些 申明一个Comparer的struct
public struct BuffStatusComparer : IEqualityComparer
{
public bool Equals(BuffStatus x, BuffStatus y)
{
return x == y;
}
public int GetHashCode(BuffStatus obj)
{
// you need to do some thinking here,
return (int)obj;
}
}
47、初始化字典,枚举类型必须添加比较函数
HitShipBuffDict = new Dictionary<BuffStatus,List