我最近经常使用 XNA,并且也阅读了很多有关游戏中垃圾收集的内容。我认为通过使用池化和避免对 foreach 的依赖,我在减少垃圾量方面已经做了合理的工作。
现在,我将基本游戏实体存储在 KeyedCollection 中,它允许我迭代所有实体(如列表)并通过键引用实体(如字典)。
我希望能够查询我的集合并返回另一个集合,而不会在每次查询时产生垃圾。我在下面提供了一个概念示例,因为我认为我更擅长对它们进行编码,我正在解释......
/// <summary>
/// Defines a sample entity.
/// </summary>
public class SampleEntity
{
public uint Id;
public Vector2 Position;
}
/// <summary>
/// Defines a collection of sample entities.
/// </summary>
public class EntityCollection : KeyedCollection<uint, SampleEntity>
{
/// <summary>
/// Return the key for the supplied item.
/// </summary>
protected override uint GetKeyForItem(SampleEntity item)
{
return item.Id;
}
}
/// <summary>
/// Defines the sample game class.
/// </summary>
public class GameSample
{
/// <summary>
/// Create a new instance of the GameSample class.
/// </summary>
public GameSample()
{
Entities = new EntityCollection();
}
/// <summary>
/// Get the collection of game entities.
/// </summary>
public EntityCollection Entities { get; private set; }
/// <summary>
/// Return the collection of entities within a radius of the supplied point.
/// </summary>
public List<SampleEntity> Query(Vector2 center, float radius)
{
List<SampleEntity> results = new List<SampleEntity>() // BAD, BAD, BAD!!!!!
//
// add the entities to the results collection
//
return results;
}
}
这个(过于简化的)示例会产生大量垃圾,因为它每次调用都会创建一个新的 List 对象。我还尝试过创建全局结果列表并清除每个调用,但这看起来很难看。
/// <summary>
/// Return the collection of entities within a radius of the specified point.
/// </summary>
public List<SampleEntity> Query(Vector2 center, float radius)
{
_globalResults.Clear();
//
// add the entities to the global results collection
//
return _globalResults;
}
我是不是错过了什么?我不知道是否有更优雅的解决方案。
最佳答案
我认为在这种情况下最好的解决方案是让你的函数看起来像这样:
public void Query(Vector2 center, float radius, List<SampleEntity> result)
{
result.Clear();
result.Add(/*...*/);
// ...
}
并让调用者负责管理该列表。
另外:制作游戏时,不要害怕编写简单的代码。如果全局结果列表有效 - 那么这就是一个很好的解决方案。
如果您不需要存储列表,那么从性能角度来看,Skurmedel's answer 可能更好。
不过,如果是我,我会做非常简单的事情,直接迭代实体。相同的效果,也许更快一点,最重要的是:更少的代码。
在编写复杂的空间分区数据结构之后再编写复杂的枚举查询函数,只有在您真正需要它提供的性能之后才会编写它。
关于c# - 如何从另一个集合中生成游戏实体集合而不产生垃圾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3531234/