最有效的方法,标签还是列表<GameObject>?
Most efficient way, Tags or List<GameObject>?
在我的游戏中,我可以使用游戏对象或标签列表进行迭代,但我更愿意知道什么是最有效的方法。
使用标签节省更多内存,或者 unity 需要很多资源才能按标签进行搜索?
public List<City> _Citys = new List<City>();
或
foreach(GameObject go in GameObject.FindGameObjectsWithTag("City"))
您最好使用 City 对象列表并执行标准 for 循环以遍历 'City' 对象。 List 只是简单地保存对 'City' 对象的引用,因此对内存的影响应该是最小的 - 您可以使用 GameObjects[] 数组而不是 List(这就是 FindGameObjectsWithTag returns)。
使用填充的 List/Array 而不是按标签搜索对性能来说更好,当然你明确指向一个对象而不是使用 'magic' 字符串——如果你更改标签稍后命名,然后 FindGameObjectsWithTag 方法将无提示地中断,因为它将不再找到任何对象。
Replace the “foreach” loops with simple “for” loops. For some reason, every iteration of every “foreach” loop generated 24 Bytes of garbage memory. A simple loop iterating 10 times left 240 Bytes of memory ready to be collected which was just unacceptable
编辑:如 pid 的回答中所述 - 测量。您可以使用内置的 Unity 分析器来检查内存使用情况:http://docs.unity3d.com/Manual/ProfilerMemory.html
根据 Microsoft 的 C# API 规则,Find*
或 Count*
等动词表示活动代码,而 Length
等术语表示不需要代码执行的实际值.
现在,Unity3D 人员是否遵守这些准则是一个有争议的问题,但从方法的名称我已经可以看出它是有代价的,不应该掉以轻心。
另一方面,您的问题是关于性能,而不是正确性。两种方式本身都是正确的,但应该有更好的性能。
因此,性能重构的主要规则是:MEASURE。
这取决于内存分配和垃圾收集,如果不测量就无法判断哪个更快。
所以我能给你的最好建议是非常笼统的。每当您觉得需要增强代码的性能时,您必须实际测量前后要改进的内容。
您的代码示例是两个截然不同的东西。一种是实例化列表,一种是通过函数调用枚举 IEnumerable returned。
我假设你的意思是遍历声明的列表与遍历 GameObject.FindObjectsWithTag() 中的 return 值之间的区别,在这种情况下;
将列表作为成员变量存储在您的 class 中,填充一次然后迭代多次比迭代多次 GameObject.FindObjectsWithTag 更有效。
这是因为您始终保留列表和对列表中对象的引用,而无需重新填充它。
GameObject.FindObjectsWithTag 将搜索您的整个对象层次结构并编译它找到的与您的搜索条件匹配的所有对象的列表。每次调用该函数时都会执行此操作,因此即使它找到的对象数量与仍在搜索层次结构的对象数量相同,也会产生额外的开销。
老实说,您可以使用 GameObject.FindObjectWithTag 使用 List 对象缓存您的结果,前提是 returned 对象的数量不会改变。 (就像说你没有实例化或销毁任何这些对象)
在我的游戏中,我可以使用游戏对象或标签列表进行迭代,但我更愿意知道什么是最有效的方法。
使用标签节省更多内存,或者 unity 需要很多资源才能按标签进行搜索?
public List<City> _Citys = new List<City>();
或
foreach(GameObject go in GameObject.FindGameObjectsWithTag("City"))
您最好使用 City 对象列表并执行标准 for 循环以遍历 'City' 对象。 List 只是简单地保存对 'City' 对象的引用,因此对内存的影响应该是最小的 - 您可以使用 GameObjects[] 数组而不是 List(这就是 FindGameObjectsWithTag returns)。
使用填充的 List/Array 而不是按标签搜索对性能来说更好,当然你明确指向一个对象而不是使用 'magic' 字符串——如果你更改标签稍后命名,然后 FindGameObjectsWithTag 方法将无提示地中断,因为它将不再找到任何对象。
Replace the “foreach” loops with simple “for” loops. For some reason, every iteration of every “foreach” loop generated 24 Bytes of garbage memory. A simple loop iterating 10 times left 240 Bytes of memory ready to be collected which was just unacceptable
编辑:如 pid 的回答中所述 - 测量。您可以使用内置的 Unity 分析器来检查内存使用情况:http://docs.unity3d.com/Manual/ProfilerMemory.html
根据 Microsoft 的 C# API 规则,Find*
或 Count*
等动词表示活动代码,而 Length
等术语表示不需要代码执行的实际值.
现在,Unity3D 人员是否遵守这些准则是一个有争议的问题,但从方法的名称我已经可以看出它是有代价的,不应该掉以轻心。
另一方面,您的问题是关于性能,而不是正确性。两种方式本身都是正确的,但应该有更好的性能。
因此,性能重构的主要规则是:MEASURE。
这取决于内存分配和垃圾收集,如果不测量就无法判断哪个更快。
所以我能给你的最好建议是非常笼统的。每当您觉得需要增强代码的性能时,您必须实际测量前后要改进的内容。
您的代码示例是两个截然不同的东西。一种是实例化列表,一种是通过函数调用枚举 IEnumerable returned。
我假设你的意思是遍历声明的列表与遍历 GameObject.FindObjectsWithTag() 中的 return 值之间的区别,在这种情况下;
将列表作为成员变量存储在您的 class 中,填充一次然后迭代多次比迭代多次 GameObject.FindObjectsWithTag 更有效。
这是因为您始终保留列表和对列表中对象的引用,而无需重新填充它。
GameObject.FindObjectsWithTag 将搜索您的整个对象层次结构并编译它找到的与您的搜索条件匹配的所有对象的列表。每次调用该函数时都会执行此操作,因此即使它找到的对象数量与仍在搜索层次结构的对象数量相同,也会产生额外的开销。
老实说,您可以使用 GameObject.FindObjectWithTag 使用 List 对象缓存您的结果,前提是 returned 对象的数量不会改变。 (就像说你没有实例化或销毁任何这些对象)