A *在多个网格上寻路

时间:2013-04-18 17:03:21

标签: c# unity3d path-finding

我正在尝试围绕一个立方体实现A *寻路,立方体由6个网格组成,为​​了保持简单,我有4种方法GetXPlus,GetXMinus,GetYPlus,GetYMinus。每个方法检查下一个tile是否在当前网格空间内,如果它不是切换到适当的网格。

我遇到的问题是,当试图从当前网格向另一个方向翻转的网格中获取图块时,返回的图块位于另一侧。有没有一种方法或方法可以避免为每个原始网格和方向编写独特的逻辑?

为了帮助清楚地表达我的问题,在这里,我来自(紫色)网格,并使用GetXPlus方法:

enter image description here

我当前实现的一个snippit(每个网格是64乘64):

public Tile GetXPlus( int currentX, int currentY )
{
    var newX = currentX + 1;
    var tile = GetTile( newX , currentY );

    if( newX > 64 ) //Get adjacent XPlus Grid 
    { 
        currentGrid = SetCurrentGrid( XPlusGridIndex );
        tile = GetTile( newX - 64, currentY );
    }

    return tile;
}

背景

此实施源于对此处建议的其他问题的出色答案:https://gamedev.stackexchange.com/questions/53866/pathfinding-on-a-uneven-planetary-surface

2 个答案:

答案 0 :(得分:1)

我建议你比前面的答案更进一步。创建一个表示所有切片的多维数据集,并缓存每个切片的邻居。由于瓷砖之间的关系是固定的,它将为您节省大量时间。

后记您可以使用double[,,]int[,,,]来跟踪已处理的图块,并根据这些图块添加邻居Queue<Tile>

如果需要,您也可以实施GetDirection(Tile tile)。该功能只需要在方向字典中搜索。

公共类Cube     {         私人瓷砖[,,]瓷砖;

    public Cube(int size)
    {
        tiles = new Tile[size, size, 6];

        // initialize.
        for (var side = 0; side < 6; side++)
        {
            for (var x = 0; x < size; x++)
            {
                for (var y = 0; y < size; y++)
                {
                    tiles[x, y, side] = new Tile(x, y, side);
                }
            }
        }

        // set directions & neighbors
        for (var side = 0; side < 6; side++)
        {
            for (var x = 0; x < size; x++)
            {
                for (var y = 0; y < size; y++)
                {
                    // todo: implement.
                }
            }
        }
    }

    public Tile this[int x, int y, int side]
    {
        get
        {
            return tiles[x, y, side];
        }
    }
}

public class Tile
{
    private Dictionary<DirectionType, Tile> directions = new Dictionary<DirectionType, Tile>();

    private Tile[] neighbors = new Tile[4];

    public Tile(int x, int y, int side)
    {
        this.X = x;
        this.Y = y;
        this.Side = side;
    }

    public int X { get; private set; }
    public int Y { get; private set; }
    public int Side { get; private set; }

    public Tile this[DirectionType dir]
    {
        get
        {
            return directions[dir];
        }
    }



    public Tile[] Neighbors { get { return neighbors; } }
}

public enum DirectionType
{
    // delta: +1, 0
    e,
    // delta: 0, +1
    n,
    // delta: -1, 0
    w,
    // delta: 0, -1
    s,
    // delta: 0, 0
    X
}

答案 1 :(得分:0)

您可以使用从“X坐标”,“Y坐标”和“平铺”组成的一个三维坐标空间到另一个坐标空间的函数映射。

给定订单:

enum TileBorder
{
    Left   = 0,
    Top    = 1,
    Right  = 2,
    Bottom = 3
}

您可以将这些转换存储在Tile类的数组中:

class Tile
{
    public Tile[] Neighbors { get; set; }
    public Func<int, int, int>[] XTransitions { get; set; }
    public Func<int, int, int>[] YTransitions { get; set; }

    public void GetXPlus(int x, int y, out int newX, out int newY, out Tile newTile)
    {
        x++;
        if (x <= 64)
        {
            newX = x;
            newY = y;
            newTile = this;
        }
        else
        {
            newX = XTransitions[(int)TileBorder.Right](x, y);
            newY = YTransitions[(int)TileBorder.Right](x, y);
            newTile = Neighbors[(int)TileBorder.Right];
        }
    }
    // ...
}

然后在设置结构时只需要注意一点。例如,假设您的坐标从1到64(包括1和64)运行,则可以设置绿色图块。

Tile pink   = new Tile();
Tile green  = new Tile();
Tile orange = new Tile();
Tile purple = new Tile();
Tile blue   = new Tile();

green.Neighbors = new Tile[] 
{ 
    /* left */   orange, 
    /* top */    pink,
    /* right */  blue,
    /* bottom */ purple 
};

green.XTransitions = new Func<int, int, int>[] 
{
    /* left */   (x, y) => 1, 
    /* top */    (x, y) => x,
    /* right */  (x, y) => 64,
    /* bottom */ (x, y) => x 
};

green.YTransitions = new Func<int, int, int>[] 
{
    /* left */   (x, y) => 65 - y, 
    /* top */    (x, y) => 64,
    /* right */  (x, y) => 65 - y,
    /* bottom */ (x, y) => 1
};

请注意,切片转换功能只是一个查找,但为了完全灵活,您还可以使用类型的功能:
对于x坐标,Func<int, int, Tile, int>
y {坐标Func<int, int, Tile, int>,和 瓷砖Func<int, int, Tile, Tile>