示例#1
0
    private void Check_ReuseCoroutinue()
    {
        Profiler.BeginSample("Check_ReuseCoroutinue");

        Profiler.BeginSample("1");
        if (_testingCor1 == null)
        {
            _testingCor1 = StartCoroutine(TestingCor1());
        }
        Profiler.EndSample();

        Profiler.BeginSample("2");
        if (_testingCor2 == null)
        {
            _testingCor2 = TestingCor2();
        }
        if (_testingCor2 != null)
        {
            if (_testingCor2.MoveNext())
            {
                int v = (int)_testingCor2.Current;
            }
            else
            {
                //_testingCor2.Reset(); // C# 语法糖生产的没有 Reset 实现,这里会报错
            }
        }
        Profiler.EndSample();

        Profiler.BeginSample("3");
        if (_testingCor3 == null)
        {
            _testingCor3 = new UnityCoroutineInst_NoBoxingOperates();
        }
        if (_testingCor3 != null)
        {
            if (_testingCor3.MoveNext())
            {
                int v = _testingCor3.Current;
            }
            else
            {
                _testingCor3.Reset(); // 我们自己实现的 Cortoutine 就可以随心所欲的 Reset,因为自己实现了接口,这样就不用重新 new 一个协程管理对象,也就没有 GC 了
            }
        }
        Profiler.EndSample();

        Profiler.EndSample();

        // Profile 结果
        //  1、2 方式都因为 C# 语法糖内部实际 new 了一个类似 UnityCoroutineInst_NoBoxingOperates 的类来分状态处理,所以每次获取一个 Enumerator 时,都会有 GC
        //  3 方式虽然我们也实现了对应的 IEnumerator,但是我们自己可实现对 Reset 接口的处理,所以不用重新 new,因此只有第一次 new 有 GC
        // 因此,没事不要频繁的 StartCortoutine ,因为有 GC
        // 尽可能使用 Update 函数来处理
    }
示例#2
0
    private void Check_Enumerator()
    {
        Profiler.BeginSample("Check_Enumerator");

        Profiler.BeginSample("1");
        if (enumerator_first_run)
        {
            enumerator = GetEnumerator();
        }
        if (enumerator != null)
        {
            if (enumerator.MoveNext())
            {
                int v = enumerator.Current;
            }
            else
            {
                enumerator = null;
            }
        }
        Profiler.EndSample();

        Profiler.BeginSample("2");
        if (enumerator_first_run)
        {
            StartCoroutine(GetEnumerator());
        }
        Profiler.EndSample();

        Profiler.BeginSample("3");
        if (enumerator_first_run)
        {
            cor_inst_have_boxing = new UnityCoroutineInst_HaveBoxOperates();
        }
        if (cor_inst_have_boxing != null)
        {
            if (cor_inst_have_boxing.MoveNext())
            {
                int v = enumerator.Current;
            }
            else
            {
                cor_inst_have_boxing = null;
            }
        }
        Profiler.EndSample();

        Profiler.BeginSample("4");
        if (enumerator_first_run)
        {
            cor_inst_no_boxing = new UnityCoroutineInst_NoBoxingOperates();
        }
        if (cor_inst_no_boxing != null)
        {
            if (cor_inst_no_boxing.MoveNext())
            {
                int v = enumerator.Current;
            }
            else
            {
                cor_inst_no_boxing.Dispose();
                cor_inst_no_boxing = null;
            }
        }
        Profiler.EndSample();

        Profiler.EndSample();

        enumerator_first_run = false;

        // Profile 结果
        // IEnumerator + yield 本质上就是 C# 编译器的语法糖,会生产一个状态机,对不同逻辑的 yield 设置到不一样的 swtich(state) 的 case 分支上执行对应的逻辑
        // 所以在获取 IEnumerator 实例的瞬间就 new 了一个对象来构造状态信息,这回导致 GC 的
        // 所以控制好获取 IEnumerator 的次数,和帧频调用率
    }