在 Unity 中实现 2D hex-based/isometric 网格系统的最佳方式(对于复杂的图块)?

Best way to implement a 2D hex-based/isometric grid system in Unity (for complex tiles)?

我正在尝试为 2D 游戏创建网格系统。不完全确定我是否会使用六边形网格或等轴测图,但这在这里无关紧要。基本上,我正在尝试创建一款塔防游戏,您可以在其中部署单位而不是塔,并且可以像玩战术游戏一样移动它们。问题是瓷砖本身会很复杂——会有不同类型的地形。有些单位只能部署在X,不能通过Y,那种事。我还需要能够随意向这些图块添加一些逻辑 - 谁知道呢,也许我想要一个特殊的图块来为其上方的单位提供额外的攻击范围,诸如此类。游戏还必须 "feel" 像网格一样 - 让事物捕捉到图块的中心,并在悬停时和 moving/attacking.

时突出显示图块

好的,这让我找到了一条非常明显的路线:我可以为我需要的不同类型的图块创建预制件,将所有属性和逻辑添加为脚本组件并创建一个网格 class 来实例化每个世界上的瓷砖。这很好用,因为这样我就可以完全控制一切——我可以对这些图块做任何我想做的事,而且我还可以在实例化它们时为它们的位置创建一个二维矩阵。例如,这样我就可以调用 tile[3, 6],这听起来对寻路、突出显示等来说意义重大。我还可以 link 将其顶部的任何游戏对象连接到图块本身,因此我可以调用 tile[6, 2].ObjectOnTop.~WhateverInfoINeedFromIt 之类的东西,这对于整体逻辑来说也非常方便。

但缺点也很可怕——我什至如何设计和部署不同级别的设计?我能想到的唯一方法是想出一种方法来手工完成这一切,以某种方式将该信息导出到 json 文件,并让网格 class 实例化所有内容 select 将根据 json 信息在何处实例化哪个磁贴。我不仅不知道如何实际实现它,而且我还认为对于本应自然的东西来说,这将是一项荒谬的工作量。我也不确定每个图块的游戏对象在性能方面是否是个好主意。最大的问题?如果它是一个简单的正方形瓷砖网格,那么创建这样的网格很容易 - 但当我们开始谈论六边形和等距网格时......老实说,这并不容易。复杂的形状使得处理这种东西变得非常困难。例如,我如何将鼠标位置转换为等效的图块?正方形非常容易……其他的就没那么简单了。网格仅在游戏运行时才真正部署也有点糟糕(顺便说一句,这通常被认为是我应该避免的坏事吗?)。

但别担心,因为我找到了解决方案:tilemaps!当然!它解决了我遇到的所有问题,对吗?据说是的,但它也消除了我拥有预制件的所有力量。现在我不能对瓷砖有任何逻辑......他们不能存储任何属性......所以我注定要失败,我猜。我读过一些关于克服这个问题的方法(预制笔刷,Tile 固有的自定义 classes,为每种瓷砖类型制作一个瓷砖地图),但老实说它们非常小众而且感觉不对。

太奇怪了,像这样的通用网格系统本来应该是那么简单和普遍。但是我几乎找不到任何信息。就好像我错过了这个非常明显的工具,似乎没有人提到它,因为它太明显了。所以我在这里,努力开始一个项目,因为我什至无法弄清楚如何实现游戏的基本结构。我在网上看到的所有东西都让我想到了瓷砖地图——但据我所知,它们只适用于非常基本的东西。我想我不会为这种游戏工作。我现在不知道该怎么做 - 必须有一种最佳方法来解决所有问题,这种方法可能适用于从事此类游戏的所有开发人员。老实说,有很多。

所以,请给我一些启发。提前致谢!

(有人发布了一个极其相似的问题:

可以通过不同的方式将鼠标位置转换为图块位置,最简单的方法是对鼠标进行光线投射并查看它是否碰到图块

可能最容易制作 class 'Tile' 的二维图块数组,即使它的十六进制将其分解为二维数组并偏移,在代码中动态设置图块

对于寻路,这样的 djikstra 算法非常有用

https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

我有完全相同的问题。我发现的最好的是:https://m.youtube.com/playlist?list=PLzDRvYVwl53uhO8yhqxcyjDImRjO9W722

这是 CodeMonkey 的播放列表,他在其中通过脚本创建网格,还添加了泛型,这使您可以拥有所需的逻辑并添加可视化图块。唯一的问题是当我想要正方形而你想要不同的形状时。我不知道该怎么做,也许你可以调整网格(更可能是它用来显示视觉效果的 tilemap)或者你应该放开不同的形状,我不知道。

希望我至少帮了一点忙。我看到了这个post,很遗憾没有人回复你。希望你能实现你想要的,并且会成功。祝你好运,主要是玩得开心:)

可能会有帮助

grid = new gridSpace[roomWidth + 3, (roomWidth / 2) + 2];
int xStep = 4; # 2:1 isometry type
    for (int x = 0; x < roomWidth - 1; x += xStep) #xStep depends by type of isometry
    {
        int minX = x;
        int maxX = x + 2;

        int localX = x;
        for (int y = roomWidth / 2; y > -1; y--)
        {
            grid[localX, y] = gridSpace.empty;
            if (localX == minX)
            {
                localX = maxX;
            }
            else
            {
                localX = minX;
            }

        }
    }