如何解决具有移动对象的四叉树的内存问题?

问题描述

我正在用 C# 为 2D 游戏创建一个四叉树,以加快渲染速度。一些对象(行星)正在移动,这就是为什么我创建了一个名为 removeAndUpdate方法来更新树,方法是从叶子(而不是从根)删除和重新插入特定对象,因为我已经读过在link。不幸的是,在重新插入部分一段时间后我得到了 System.OutOfMemoryException。我很确定,removeAndUpdate 方法存在一些问题。

也许值得一提的是,当一个四边形被细分时(以防万一,当四边形的存储容量已满时),内容将不会在子四边形之间分布。我这样做是为了提高一些性能。不过我觉得和上面的问题没有关系。

我猜,某处有一个无限循环,导致内存不足。如果我从根插入新对象,则没有问题。

我在异常发生的地方写了评论

这里可以看到 QuadTree 类的重要部分:

public class QuadTree
{
    BoundingBox boundary;
    int capacity;
    List<Worldobject> leafContent;
    public QuadTree parent;
    bool divided;
    public List<QuadTree> childQuadTrees;

    public QuadTree(BoundingBox _boundary,int _capacity,QuadTree _parent)
    {
        this.boundary = _boundary;
        this.capacity = _capacity;
        this.leafContent = new List<Worldobject>();
        this.childQuadTrees = new List<QuadTree>();
        this.divided = false;
        this.parent = _parent;
    }

    // Subdividing the quad,if its storing capacity is full.
    public void subdivide()
    {
        // north-East
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(new Vector3(boundary.Center.X,boundary.Min.Z),new Vector3(boundary.Max.X,boundary.Center.Z)),this.capacity,this));
        // north-West
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(new Vector3(boundary.Min.X,new Vector3(boundary.Center.X,this));
        // South-East
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(boundary.Center,boundary.Max),this));
        // South-West
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(new Vector3(boundary.Min.X,boundary.Center.Z),boundary.Max.Z)),this));

        this.divided = true;
    }

    public void insert(Worldobject wO)
    {
        // Checking,whether the quad contains the Box at all.
        if (!this.ContainorOverlap(wO.BoundingBox))
        {
            return;
        }

        // If there is space,insert the Box.
        if (this.leafContent.Count < this.capacity && this.divided == false)
        {



/*This is the instruction,where System.OutOfMemoryException occures*/
          this.leafContent.Add(wO); // <-------
          return;
        }

        // If not,subdivide the quad then insert the obj to the subquads.
        else
        {
            if (this.divided == false)
            {
                this.subdivide();
            }

            this.childQuadTrees[0].insert(wO);
            this.childQuadTrees[1].insert(wO);
            this.childQuadTrees[2].insert(wO);
            this.childQuadTrees[3].insert(wO);
        }
    }

    /* Here is the method to update the moving objects bounding volume.
    It first removes the element from the tree,updates the boundingBox,then reinsert the object from the leaves*/
    public void removeAndUpdate(Worldobject obj,Vector3 displacement)
    {
        if (!this.ContainorOverlap(obj.BoundingBox))
        {
            return;
        }

        if (this.divided)
        {
            this.childQuadTrees[0].removeAndUpdate(obj,displacement);
            this.childQuadTrees[1].removeAndUpdate(obj,displacement);
            this.childQuadTrees[2].removeAndUpdate(obj,displacement);
            this.childQuadTrees[3].removeAndUpdate(obj,displacement);
        }

  /* if the obj is found,remove it,the try to reinsert it to its parent. If its parent does not contain it,move upwards in the hierarchy and try again to insert*/
        if (leafContent.Contains(obj))
        {
            this.leafContent.Remove(obj);
            QuadTree q = this.parent;
            while (q.ContainorOverlap(obj.BoundingBox) == false)
            {
                q = q.parent;
            }
            obj.BoundingBox.Translate(displacement);
            q.insert(obj);
        }
    }

    public void query(BoundingBox range,List<Worldobject> resultList)
    {
        if (!this.ContainorOverlap(range))
        {
            return;
        }

        if (this.divided)
        {

            this.childQuadTrees[0].query(range,resultList);
            this.childQuadTrees[1].query(range,resultList);
            this.childQuadTrees[2].query(range,resultList);
            this.childQuadTrees[3].query(range,resultList);
        }

        resultList.AddList(this.leafContent);
    }
}

以下是异常中断时调试的一些信息:

enter image description here

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)