关闭mono的GC,防止其带来的卡顿

为了解决游戏过程中明显的卡顿问题,本文详细介绍了如何通过修改Mono运行时来控制垃圾回收(GC)的过程。作者分享了在Unity游戏引擎下,针对Android和iOS平台,如何开关GC功能的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们的游戏品类特殊,对游戏对局内的画面流畅性要求极高。不允许出现可以明显察觉的卡顿。当我们解决了所有对象创建,JIT编译等带来的卡顿之后。还有一个较为棘手的卡顿来源就是GC。我们想了各种办法尽可能的减少对局内的内存分配。包括对UI的特殊处理,对网络消息的特殊处理。最后终于能够做到在一个对局之内不会产生GC。
但是,我们知道,这件事并不是一劳永逸的。随着关卡的继续开发,总有一天还会出现GC,有些内存分配是没办法彻底消除的,比如UI上变化的文字。因此我决定去搞mono本身。
首先是编译mono,这方面教程很多,比如【1】。然后就是设法开关GC,事实上mono内部有这样的功能函数,GC_enable和GC_disable,我们要做的不过是将这些符号导出。mono\mini\ldscript文件中描述了mono lib的导出符号,在其中增加GC_enable和GC_disable,重新编译,得到改造过的libmono.so。替换unity目录下的libmono(需要区分armv7和x86)
在C#中实现一个功能类,然后就可以愉快的开关GC功能了。

class GarbageCollection
{
#elif UNITY_ANDROID
    [DllImport("mono")]
    protected static extern void GC_enable();
    [DllImport("mono")]
    protected static extern void GC_disable();
#else
    protected static void GC_enable()
    {
    }
    protected static void GC_disable()
    {
    }
#endif
}

那么IOS平台呢,本来想使用跟android平台类似的方法。后来发现由于IOS上使用IL2CPP,mono被改造后集成进了libiPhone.a,同时大量符号都被导出了
包括GC_enable和GC_disable,也就是说在IOS上我们可以直接使用这两个接口,编译时不会遇到任何问题。
最后,我们的功能类就是这个样子

class GarbageCollection
{
    static bool enabled = true;
    public static bool Enable
    {
        get
        {
            return enabled;
        }
        set
        {
            if (value == enabled)
            {
                return;
            }
            if (value)
            {
                try
                {
                    GC_enable();
                }
                catch (System.Exception ex)
                {
                    Debug.Log("GC exception!");
                    Debug.Log(ex.ToString());
                }
            }
            else
            {
                try
                {
                    GC_disable();
                }
                catch (System.Exception ex)
                {
                    Debug.Log("GC exception!");
                    Debug.Log(ex.ToString());
                }
            }
            enabled = value;
        }
    }
#if UNITY_IPHONE
   
    [DllImport ("__Internal")]
    protected static extern void GC_enable();
    [DllImport ("__Internal")]
    protected static extern void GC_disable();
#elif UNITY_ANDROID
    [DllImport("mono")]
    protected static extern void GC_enable();
    [DllImport("mono")]
    protected static extern void GC_disable();
#else
    protected static void GC_enable()
    {
    }
    protected static void GC_disable()
    {
    }
#endif
}


做个简单的测试,在update里面不断的分配内存,很高兴的看到内存在飙涨。(这话怎么感觉怪怪的)





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值