3.使用Stopwatch进行分帧处理

最近在读《Unity性能优化(第三版)》,看到其中的第2.11.4章节的全局消息管理器里 MessagingSystem 编写的代码时,注意到他没有使用协程,而是使用了System.Diagnostics.Stopwatch,来进行对单帧运行过长的循环进行分帧处理的操作,觉得挺有趣就在这儿记录一下(顺便纠正书中的一处忘记用Reset清空累计计时的错误)。

耗时案例:

首先我们在写一个比较耗时的循环(这里用到了臭名昭著但又难以割舍的Find方法),然后我们运行会发现Unity要卡好久才会输出 End:

    private System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
    private int i = 0;

    void Update()
    {
        if (i == 0)
        {
            Debug.Log("Start");
        }
        while (i<20000000)
        {
            // 写一个稍微耗时的操作在循环体里
            GameObject obj = GameObject.Find("Curoa_icon"); 
            i++;
        }
        if (i== 20000000)
        {
            i++;
            Debug.Log("End");
        }
        
    }

然后大约花费了6s左右,这期间这一帧就卡住了:

使用Stopwatch的改善方法:

然后我们用Stopwatch来进行改善——假如该次Update中的循环累计时间超过了100毫秒,那么我们中断该帧,在下一帧中处理剩下的循环:

    private System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
    private int i = 0;

    void Update()
    {
        timer.Start();
        if (i == 0)
        {
            Debug.Log("Start");
        }
        while (i<20000000)
        {
            if (timer.Elapsed.Milliseconds > 100) 
            {
                // 该帧超时了我们就输出一下
                Debug.Log("timerStop " + timer.Elapsed.Milliseconds);
                Debug.Log("i = " + i);
                timer.Stop();
                timer.Reset(); // 原书这里忘记reset了,如果漏了可能会导致Elapsed没有清空累计计时;
                return;
            }
            // 写一个稍微耗时的操作在循环体里
            GameObject obj = GameObject.Find("Curoa_icon"); 
            i++;
        }
        if (i== 20000000)
        {
            i++;
            Debug.Log("End");
        }
        
    }

运行一下会发现,原本会卡住的单帧被拆分到大约80帧中完成了,每帧只进行了循环中的一部分:

最后推荐一下Davide Aversa和Chris Dickinson编写的这本书,毕竟这年头多看点儿纸质书有益于舒缓大脑Σ_(꒪ཀ꒪」∠)_:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值