【问题标题】:Most efficient way, Tags or List<GameObject>?最有效的方式,Tags 还是 List<GameObject>?
【发布时间】:2015-04-18 13:39:10
【问题描述】:

在我的游戏中,我可以使用游戏对象或标签列表进行迭代,但我更喜欢知道什么是最有效的方式。

使用标签节省更多内存还是统一需要很多资源才能通过标签进行搜索?

public List<City> _Citys = new List<City>();

foreach(GameObject go in GameObject.FindGameObjectsWithTag("City")) 

【问题讨论】:

  • 标签unity的第一句话是“不要在关于UNITY游戏引擎的问题上使用(使用:unity3d代替)!!”跨度>
  • 在 foreach 上,您每次都在对层次结构进行全面研究。将 GameObject.FindGameObjectsWithTag 的结果存储在 List 中以供以后迭代,除非结果可能会改变。

标签: c# performance unity3d


【解决方案1】:

根据 Microsoft 的 C# API 规则,Find*Count* 等动词表示活动代码,而 Length 等术语表示不需要执行代码的实际值。

现在,如果 Unity3D 人员遵守这些准则是一个争论的问题,但从方法的名称我已经可以看出它是有成本的,不应该掉以轻心。

另一方面,您的问题是关于性能,而不是正确性。两种方式本身都是正确的,但应该有更好的性能。

因此,性能重构的主要规则是:MEASURE

这取决于内存分配和垃圾回收,不测量就无法判断哪个真正更快。

所以我能给你的最好的建议是相当笼统的。每当您觉得需要提高代码性能时,您都必须实际衡量您将要改进的方面,之前和之后。

【讨论】:

  • 由于您所指的方法被调用一次,关键不是“活动”代码是否是“活动”代码,而是需要多长时间才能找到具有给定标签的所有对象。这需要多长时间取决于方法的实现,因为它可能以 O(n) 的形式实现,它可能很快,但也很容易成为 O(n)
  • 是的,这就是属性和隐藏复杂性的危险所在,这就是为什么我说测量如此重要!感谢您解释这一点。
【解决方案2】:

您最好使用 City 对象列表并执行标准 for 循环来迭代“City”对象。 List 只是简单地保存对“City”对象的引用,因此对内存的影响应该是最小的 - 您可以使用 GameObjects[] 的数组而不是 List(这是 FindGameObjectsWithTag 返回的)。

使用填充的列表/数组而不是按标签搜索对性能更好,当然您明确指向一个对象而不是使用“魔术”字符串——如果您稍后更改标签名称,则 FindGameObjectsWithTag方法将静默中断,因为它将不再找到任何对象。

Also, avoid using a foreach loop in Unity as this unfortunately creates a lot of garbage (the garbage collector in Unity isn't great so it's best to create as little garbage as possbile), instead just use a standard for loop:

用简单的“for”循环替换“foreach”循环。出于某种原因,每个“foreach”循环的每次迭代都会产生 24 字节的垃圾内存。一个简单的循环迭代 10 次留下 240 字节的内存准备被收集,这是不可接受的

编辑:正如 pid 的回答中提到的 - 测量。您可以使用内置的 Unity 分析器来检查内存使用情况:http://docs.unity3d.com/Manual/ProfilerMemory.html

【讨论】:

    【解决方案3】:

    您的代码示例是两个截然不同的东西。一种是实例化列表,一种是枚举函数调用返回的 IEnumerable。

    我假设您的意思是在这种情况下迭代声明的列表与迭代 GameObject.FindObjectsWithTag() 的返回值之间的区别;

    将 List 作为成员变量存储在您的类中,填充一次然后对其进行多次迭代比多次迭代 GameObject.FindObjectsWithTag 更有效。

    这是因为您始终保留您的列表以及对列表中对象的引用,而无需重新填充它。

    GameObject.FindObjectsWithTag 将搜索您的整个对象层次结构并编译它找到的与您的搜索条件匹配的所有对象的列表。每次调用该函数时都会执行此操作,因此即使它找到的对象数量与仍在搜索层次结构中的对象数量相同,也会产生额外的开销。

    老实说,您可以使用 GameObject.FindObjectWithTag 将结果缓存到 List 对象中,前提是返回的对象数量不会改变。 (就像说你没有实例化或销毁任何这些对象)

    【讨论】:

      猜你喜欢
      • 2011-07-02
      • 1970-01-01
      • 2015-06-25
      • 2020-06-14
      • 2011-01-28
      • 2017-10-25
      • 1970-01-01
      相关资源
      最近更新 更多