Visual C#方法调用占用太多内存?

3
我正在使用XNA 4.0框架编写游戏。我编写了一组方法,将2D鼠标坐标转换为3D世界中的直线,然后检查该直线是否与平面相交,并且如果交点在该平面上的面内,则检查其边界。

这个数学计算是正确的,但由于某种原因,当我每帧进行500多次这些计算时,程序就会停止运行。我可以看到内存使用量从15MB增加到约130MB,然后垃圾回收决定清理一些东西。我知道问题出在这段代码中,因为当我注释掉它时,其他所有内容都可以正常运行。

下面是我的代码,请提供任何见解,谢谢!

循环:

            GraphicObject me = new GraphicObject();
            Intersection intersect;
            double? dist = null;

            foreach (GraphicObject obj in GraphicObjects)
            {
                intersect = obj.intersectMe(line);
                if (intersect.Distance != null)
                {
                    if (intersect.Distance < dist || dist == null)
                    {
                        dist = intersect.Distance;
                        me = obj;
                    }
                    else
                    {
                        obj.Highlight(false);
                    }
                }
                else
                {
                    obj.Highlight(false);
                }
            }

            if (dist != null)
            {
                me.Highlight(true);
            }

intersectMe:

    public override Intersection intersectMe(Ray _line)
    {
        GraphicHelper.Intersects(_line, rect.Vertices[0].Normal, rect.Vertices[0].Position, intersect);

        if (intersect.Distance != null)
        {
            if (!rect.PointOnMe(intersect.X - position.X, intersect.Y - position.Y, intersect.Z - position.Z))
            {
                intersect.Distance = null;
            }
        }

        return intersect;
    }

GraphicsHelper.Intersects:

    // _l = line, _n = normal to plane, _p = point on the plane
    public static void Intersects(Ray _l, Vector3 _n, Vector3 _p, Intersection _i)
    {
        _i.Distance = null;

        float num = (_n.X * (_p.X - _l.Position.X) + _n.Y * (_p.Y - _l.Position.Y) + _n.Z * (_p.Z - _l.Position.Z));

        float denom = (_n.X * _l.Direction.X + _n.Y * _l.Direction.Y + _n.Z * _l.Direction.Z);

        if (denom != 0 && num != 0)
        {
            float t = num / denom;

            if (t > 0)
            {
                _i.X = _l.Position.X + _l.Direction.X * t;
                _i.Y = _l.Position.Y + _l.Direction.Y * t;
                _i.Z = _l.Position.Z + _l.Direction.Z * t;

                _i.Distance = _i.X * _i.X + _i.Y * _i.Y + _i.Z * _i.Z;
            }
        }
    }

PointOnMe:

    public bool PointOnMe(float _x, float _y, float _z)
    {
        float ex = _x - Vertices[3].Position.X;
        float ey = _y - Vertices[3].Position.Y;
        float ez = _z - Vertices[3].Position.Z;

        float ae = a.X * ex + a.Y * ey + a.Z * ez;
        float be = b.X * ex + b.Y * ey + b.Z * ez;

        ex = _x - Vertices[1].Position.X;
        ey = _y - Vertices[1].Position.Y;
        ez = _z - Vertices[1].Position.Z;

        float ce = c.X * ex + c.Y * ex + c.Z * ez;
        float de = d.X * ex + d.Y * ey + d.Z * ez;

        if (ae > 0 && be > 0 && ce > 0 && de > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

1
在第一个代码片段中:什么是“GraphicObject”?为什么在所有代码路径中都要创建它?为什么在其中一些代码路径中会丢弃实例而不使用它? - Theodoros Chatzigiannakis
GraphicObject是我继承的一个基类,它包含了一些虚方法。实际上,我只是将其作为我的鼠标悬停在其上的对象的参考。这样我就可以“突出显示”它。我调用new来实例化它,因为可能没有任何对象在我的鼠标指针下面。 - Talmien
我添加了代码片段,其中实际使用了“me”。 - Talmien
你又在一个代码路径中丢弃了实例(通过替换它)。相比其他路径,这个代码路径被频繁执行吗? - Theodoros Chatzigiannakis
我的C#知识很糟糕。我想要做的是使用“me”作为指向在3D世界中最接近鼠标位置的对象的指针。根据我的世界设置,我应该只替换一次或者根本不替换。我刚刚测试了一下,在me = obj断点处确认它没有发生。 - Talmien
1
除了使用真正的分析器之外,您可能需要自己进行一些分析。首先测量最内层循环:假设执行一百万次需要多长时间,然后向外移动... - TaW
1个回答

1
感谢大家抽出时间查看我的问题。实际上,错误在于我如何处理obj.Highlight()。TaW的建议让我设置了分析器,帮助我找到了问题所在。
    public override void Highlight(bool toggle)
    {
        if(toggle)
        {
            rect.Texture = new Texture2D(GraphicsManager.Graphics.GraphicsDevice, 1, 1);
            rect.Texture.SetData<Color>(new Color[] { Color.Yellow });
        }
        else
        {
            rect.Texture = new Texture2D(GraphicsManager.Graphics.GraphicsDevice, 1, 1);
            rect.Texture.SetData<Color>(new Color[] { squareColor });
        }
    }

每一帧所有对象都会生成新的纹理。这种做法非常糟糕。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接