【问题标题】:What is the fastest way to get GameObject reference?获取 GameObject 参考的最快方法是什么?
【发布时间】:2017-10-25 11:25:19
【问题描述】:

假设我的脚本定义如下。

public GameObject _GameObject;

private void Start()
{
[![enter image description here][1]][1]
    _GameObject = gameObject;
}


这会执行得更快吗?

public void SetActive(bool value)
{
  [1]: https://i.stack.imgur.com/S60FB.jpg
    gameObject.SetActive(value);
}

还是这个?

public void SetActive(bool value)
{
    _GameObject.SetActive(value);
}

【问题讨论】:

    标签: c# unity3d gameobject


    【解决方案1】:

    在 Unity 4.x 及更低版本中,缓存方法会明显更快。在那些版本中,MonoBehaviour.transform 和 MonoBehaviour.gameObject 实际上不是字段;相反,“在引擎盖下”它们的行为就像带有附加访问器的属性。

    因此访问 gameObject 属性将通过访问器对 Component.get_gameobject() 进行方法调用。当然,与简单的内存访问相比,方法调用自然会产生更多开销。 (Transform 更糟糕;显然访问器实际上调用了 GetComponent 方法来返回值!)

    这就是为什么您经常会看到资深 Unity 开发人员缓存这些值的原因。

    据我所知,Unity 5 已简化此流程以获得更好的性能;使用内置属性仍然会产生非常少量的开销,但据报道它是微不足道的。

    来源:https://blogs.unity3d.com/2014/06/23/unity5-api-changes-automatic-script-updating/

    【讨论】:

      【解决方案2】:

      我假设缓存变量比使用 Component 类中的 gameObject 变量更快,并且一个简单的测试证明了这一点。那是因为缓存它会给你引用而不是使用gameObject,它使用get 访问器来返回引用。不确定获取引用是否需要本机函数调用,但这是可能的。使用get 访问器比直接引用访问要慢。

      假设您有 100 万个脚本调用 gameObject.activeSelf 或通过缓存版本 _GameObject.activeSelf

      测试结果:

      游戏对象:54ms

      缓存的_GameObject:30ms

      软件/硬件测试于:

      • Unity 5.6.0f3
      • Windows 10 专业版
      • MacBookPro11,4
      • 16 GB 内存

      重要吗?

      在普通应用程序中,可能不是。在游戏中,是的。从游戏中删除 24ms 是一个很好的改进,具体取决于游戏的类型。

      测试脚本:

      public GameObject _GameObject;
      
      void Start()
      {
          Application.runInBackground = true;
      
          int iterations = 1000000;
      
          //TEST 1
          Stopwatch stopwatch1 = Stopwatch.StartNew();
          for (int i = 0; i < iterations; i++)
          {
              bool active = gameObject.activeSelf;
          }
          stopwatch1.Stop();
      
          //TEST 2
          Stopwatch stopwatch2 = Stopwatch.StartNew();
          for (int i = 0; i < iterations; i++)
          {
              bool active = _GameObject.activeSelf;
          }
          stopwatch2.Stop();
          //SHOW RESULT
          WriteLog(String.Format("gameObject: {0}", stopwatch1.ElapsedMilliseconds));
          WriteLog(String.Format("Cached _GameObject: {0}", stopwatch2.ElapsedMilliseconds));
      }
      
      void WriteLog(string log)
      {
          UnityEngine.Debug.Log(log);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多