c# - 如何从另一个集合中生成游戏实体集合而不产生垃圾?

标签 c# garbage-collection xna

我最近经常使用 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/

相关文章:

c# - C#简单数据绑定(bind)小攻略

go - 错误还是功能? Golang中 'range'和 'channel'相关的垃圾回收

garbage-collection - 我可以在性能监视器中使用哪个计数器来查看有多少内存正在等待 GC?

c# - XNA 4.0 打印到 Visual Studio 2012 控制台

c# - 将屏幕纹理存储在 HLSL 纹理变量 (XNA) 中

C# 程序在速度较慢的 PC 上运行速度更快,反之亦然

c# - 如何获取不属于我的项目的上一页的 URL?

c# - ContainsKey 为字符串返回 false

java - JVM元空间在调整大小时是否总是触发GC

c# - XNA 碰撞检测与游戏速度