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);

字符串优化

  1. 字符串拼接,C#拼接非常量时会使用String.conact,会生成新的字符串,不会检查字符串池,so避免频繁的字符串拼接
  2. 值类型的ToString,如果战斗飘字的情况下封装unsafe比较好

内存碎片

Update中GC Alloc

如果一个程序每帧分配一千字节 (1KB) 的临时内存,并且它以每秒 60 帧的速度运行,那么它必须每秒分配 60 千字节的临时内存。在一分钟内,这增加了 3.6 兆字节的内存可供垃圾收集器使用。
每秒调用一次垃圾收集器会对性能产生负面影响。如果垃圾收集器每分钟只运行一次,它必须清理分布在数千个单独分配中的 3.6 兆字节,这可能会导致大量垃圾收集时间。

  1. 不要在Update中new C#集合
  2. Physics.RaycastAll改成RaycastNonAlloc ,RayCast大小根据项目需要初始化大小即可。
posted @ 2022-08-30 21:33  zmorestar  阅读(198)  评论(0)    收藏  举报