Unity OutOfMemoryException List.Add()

时间:2015-05-26 08:12:30

标签: c# unity3d path-finding a-star

我正在Unity3D(版本4.6.1)中为我的FPS实现A *搜索算法。目前,我有一组敌人预制件在游戏开始时产生,并附有 Pathfinder.cs 脚本。在我的Pathfinder类中,每1秒(如果我的目标已经更改了节点),它会在 AStar.cs 中调用 FindPath(),它会找到从自身到目标的新路径。目前,玩家是目标;所以多个敌人可以找到通往同一个地方的路径。

我已经完成了所有工作,敌人找到了预期的路径。 问题是当我的播放器走动一段时间(有时几步,有时更长)时,突然游戏冻结并且任务管理器中的Unity.exe进程最多可以拍摄大约2GB +内存(大约230MB),并且如果我停止现场,不要下来。有时,Unity会在控制台中解冻此错误一秒钟解冻:

OutOfMemoryException: Out of memory
System.Array.Resize[Node] (.Node[]& array, Int32 length, Int32 newSize) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1928)
System.Array.Resize[Node] (.Node[]& array, Int32 newSize) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1912)
System.Collections.Generic.List`1[Node].set_Capacity (Int32 value) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/List.cs:622)
System.Collections.Generic.List`1[Node].GrowIfNeeded (Int32 newCount) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/List.cs:100)
System.Collections.Generic.List`1[Node].Add (.Node item) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/List.cs:91)
AStar.CalculatePath (.Node node) (at Assets/Scripts/AStar.cs:152)
AStar.FindPath (Vector3 startPos, Vector3 endPos) (at Assets/Scripts/AStar.cs:109)
Pathfinder.FindPath () (at Assets/Scripts/Pathfinder.cs:64)
Pathfinder.Update () (at Assets/Scripts/Pathfinder.cs:35)

错误指向 list.Add(node)上的 AStar.cs 脚本:

private static List<Node> CalculatePath(Node node) {
    List<Node> list = new List<Node>();
    while (node != null) {
        list.Add(node); //Error here
        node = node.parent;
    }
    list.Reverse();
    return list;
}

我最初有ArrayList,但它也出现了同样的错误。

重要:

当只有1个敌人时,此错误会发生。仅当场景中有多个敌人路径查找时才会发生错误。我认为这是因为AStar类和开放和封闭列表是静态的,所以我尝试将它们更改为在非静态上下文中使用,但错误仍然存​​在。

我已将我的AStar,Pathfinder和Node类粘贴到pastebin: http://pastebin.com/4pQU9Pwc

非常感谢任何帮助!感谢。

2 个答案:

答案 0 :(得分:3)

看起来可能存在某种循环逻辑,您将节点添加到列表中?您是否尝试在添加之前检查列表是否包含节点?

while (node != null) {
        if (!list.Contains(node)) {
            list.Add(node);
            node = node.parent;
        }
        else {
            break;
        }
    }

答案 1 :(得分:0)

感谢@Altra Viator找到问题的原因,但是结束路径仍然会产生奇怪的结果。我更改了CalculatePath方法以包含一个起始节点(敌人当前节点)并添加了一个简单的检查:

if(node == start) {
    break;
}

该方法现在看起来像这样:

private static List<Node> CalculatePath(Node node, Node start) {
    //Retrace the path back through each of the goal nodes parents (to the start node)
    List<Node> list = new List<Node>();
    while (node != null) {
        if (!list.Contains(node)) {
            list.Add(node);
            if(node == start) {
                break;
            }
            node = node.parent;
        }
        else {
            break;
        }
    }
    list.Reverse();
    return list;
}