Unity性能优化-内存
托管堆内存
闭包
C#中的方法引用是引用类型,因此它们是在堆上分配的。 这意味着如果将方法引用作为参数传递,则很容易创建临时分配。无论传递的方法是匿名方法还是预定义方法,都会发生这种分配。
public void LoadAsset(string name, Action callback)
{
}
闭包产生条件:将方法作为参数传递时,当传递的的方法引用需要访问其方法体之外的变量的状态时,会形成闭包。 必须将方法体之外的变量传递给闭包,以便闭包的代码可以使用它。
例如:
void Closer()
{
var i = 1;
LoadAsset("", () =>
{
if (i > 1)
{
}
});
}
为了确保将正确的值传递给闭包,C# 会生成一个匿名类,该类可以保留闭包所需的外部作用域变量。 当闭包传递给callback方法时,会实例化此类,并使用所需的外部变量的值初始化该类实例。
执行闭包需要实例化其生成的类的副本,并且所有类都是 C# 中的引用类型。 因此,执行闭包需要在托管堆上分配一个对象。
协程
yield return new,提出成员变量。
日志
日志要做严格限制,使用条件属性在发布正式包的时候关闭取消DEBUGMODE宏定义,这样的话所有使用自定义日志的位置都会被剔除。直接上代码
[System.Diagnostics.Conditional("DEBUGMODE")]
public static void Log(object obj)
{
if (!AppSetting.DEBUG_ENABLE)
{
return;
}
Debug.Log(obj);
}
使用举例,像这种打印的字符串都会被剔除掉。避免Log字符串拼接装箱等情况。确保不需要的打印日志不会被打进包内。
Logger.Log("player guid:" + 11111);
字符串优化
- 字符串拼接,C#拼接非常量时会使用String.conact,会生成新的字符串,不会检查字符串池,so避免频繁的字符串拼接
- 值类型的ToString,如果战斗飘字的情况下封装unsafe比较好
内存碎片
Update中GC Alloc
如果一个程序每帧分配一千字节 (1KB) 的临时内存,并且它以每秒 60 帧的速度运行,那么它必须每秒分配 60 千字节的临时内存。在一分钟内,这增加了 3.6 兆字节的内存可供垃圾收集器使用。
每秒调用一次垃圾收集器会对性能产生负面影响。如果垃圾收集器每分钟只运行一次,它必须清理分布在数千个单独分配中的 3.6 兆字节,这可能会导致大量垃圾收集时间。
- 不要在Update中new C#集合
Physics.RaycastAll改成RaycastNonAlloc,RayCast大小根据项目需要初始化大小即可。

浙公网安备 33010602011771号