C# Unity Tilemaps,用于突出显示瓷砖/单元的单个瓷砖碰撞检测,奇怪的行为

C# Unity Tilemaps,用于突出显示瓷砖/单元的单个瓷砖碰撞检测,奇怪的行为,c#,unity3d,grid,collision,tile,C#,Unity3d,Grid,Collision,Tile,我已经在这个问题上工作了几天,试图创建一个正方形的瓷砖网格,使用Unity Tilemaps似乎是最有效的方法,而且它已经内置了很多 我想突出球员周围的瓷砖,这样他就可以看到什么是合法的举动。 我在底图(地面/草地)的顶部使用了第二个Tilemap 第二个Tilemap,highlightsMap由不可见的瓷砖组成,当出现Physical.SphereOverlap或Physics2D.CircleAll 为了检测每个平铺,我在一个空对象上添加了一个长方体碰撞器,并在平铺贴图网格的顶部创建了这些

我已经在这个问题上工作了几天,试图创建一个正方形的瓷砖网格,使用Unity Tilemaps似乎是最有效的方法,而且它已经内置了很多

我想突出球员周围的瓷砖,这样他就可以看到什么是合法的举动。 我在底图(地面/草地)的顶部使用了第二个Tilemap

第二个Tilemap,highlightsMap由不可见的瓷砖组成,当出现
Physical.SphereOverlap
Physics2D.CircleAll

为了检测每个平铺,我在一个空对象上添加了一个长方体碰撞器,并在平铺贴图网格的顶部创建了这些碰撞器的网格,以便:

位置(2,4,0)的框式对撞机
正好位于位置(2,4,0)的
平铺顶部

这应该是处理此问题最直接的方法,因为您可以使用
Tilemap.SetTile(Vector3Int Pos,Tile Tile)

然而,这个问题很奇怪。碰撞器具有正确的位置值,以便能够通过该位置数据精确地引用其下方的平铺。如上所述,我已经仔细检查了这一点,碰撞器清空与它们下面的瓷砖的位置完全相同,不需要转换

问题在于,互动程序没有像预期的那样在玩家周围高亮显示,相反,玩家旁边的一些互动程序高亮显示,而其他互动程序没有高亮显示。我使用的Physical.OverlapSphere仅适用于3D碰撞器,这就是为什么我将它们作为其他网格添加到所有内容之上

遗憾的是,使用Physics2D.CircleAll无法检测到平铺本身(精灵或栅格)上的任何2D碰撞器,因此不确定是否打算这样工作

冲突网格脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class scr_ColliderGrid : MonoBehaviour
{
    public GameObject eCollider;
public Tile invisibleTile;
public Tile highlightTile;
public Tilemap highlightMap;
public int xSize, ySize;

private Vector3Int[] gridArray;                 // Tilemaps use Vector3Int BUT only use (X, Y, 0)   !!!!!!!
private int xC = 0, yC = 0, i = 0;

private Tile[] tiles;

private Vector3Int previous;

private void Start()
{
    gridArray = new Vector3Int[xSize * ySize];
    tiles = new Tile[xSize * ySize];

    GenerateCollisionGrid();
}

private void GenerateCollisionGrid()
{
    for (xC = 0; xC < xSize; xC++)
    {
        for (yC = 0; yC < ySize; yC++)
        {
            Vector3Int newPos = new Vector3Int(xC, yC, 0);       // 2, 4, 0
            Vector3Int newColPos = new Vector3Int(xC, yC, 0);    // 2, 4, 0     //This used to be different values, but now they are exactly the same.
            if (invisibleTile != null)
            {
                Tile tile = Instantiate(invisibleTile, newPos, Quaternion.identity, transform);
                tiles[i] = tile;

                GameObject col = Instantiate(eCollider, newColPos, Quaternion.identity, transform);
            }
            gridArray[i] = newPos;
            i++;
        }
    }

    highlightMap.SetTiles(gridArray, tiles);
    highlightMap.SetTile(new Vector3Int(2,4,0), highlightTile);   // 2,4,0  //Test to see if positions are the same. (collider and tiles)
}
如果您在Unity中打开一个新的3D项目,并使用Tilemap(在我的代码示例中称为highlightMap)设置一个网格,您应该能够使用这两个脚本准确地重新创建它

一切都是二维的,这意味着
x+是正确的
y+是向前的
z+是向上的
(tilemaps未使用)

我拥有的空对撞机预制件是一个位置为0,0,0的空围棋。它有另一个空的GO子对象,该子对象具有长方体碰撞器组件,该子对象的变换值为0.5,0.5,0.5,因此碰撞器位于每个平铺顶部的中心

这是在0步之后,所以只需按Play:

这是在1向前移动(y+1)之后:

你完全可以不用使用对撞机,也可以使用

Tilemap yourTileMap;

// see https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap-layoutGrid.html
var grid = yourTileMap.layoutGrid;
// The "Grid" implements "GridLayout"
// see https://docs.unity3d.com/ScriptReference/Grid.html
var currentCellPos = grid.WorldToCell(transform.position);
var currentCell = yourTileMap.GetTile(currentCellPos);
var currentCellPos = grid.WorldToCell(transform.position);
var currentCell = yourTileMap.GetTile(currentCellPos);

var leftCellPos = grid.WorldToCell(transform.position - transform.right * someRange);
var leftCell = yourTileMap.GetTile(leftCellPos);

var rightCellPos = grid.WorldToCell(transform.position + transform.right * someRange);
var rightCell = yourTileMap.GetTile(rightCellPos);

var frontCellPos = grid.WorldToCell(transform.position + transform.forward * someRange);
var frontCell = yourTileMap.GetTile(frontCellPos);

var backCellPos = grid.WorldToCell(transform.position - transform.forward * someRange);
var backCell = yourTileMap.GetTile(backCellPos);
然后,如果你需要得到多个瓷砖,我可能会采取“懒惰/愚蠢”的方式,只做一些类似于

Tilemap yourTileMap;

// see https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap-layoutGrid.html
var grid = yourTileMap.layoutGrid;
// The "Grid" implements "GridLayout"
// see https://docs.unity3d.com/ScriptReference/Grid.html
var currentCellPos = grid.WorldToCell(transform.position);
var currentCell = yourTileMap.GetTile(currentCellPos);
var currentCellPos = grid.WorldToCell(transform.position);
var currentCell = yourTileMap.GetTile(currentCellPos);

var leftCellPos = grid.WorldToCell(transform.position - transform.right * someRange);
var leftCell = yourTileMap.GetTile(leftCellPos);

var rightCellPos = grid.WorldToCell(transform.position + transform.right * someRange);
var rightCell = yourTileMap.GetTile(rightCellPos);

var frontCellPos = grid.WorldToCell(transform.position + transform.forward * someRange);
var frontCell = yourTileMap.GetTile(frontCellPos);

var backCellPos = grid.WorldToCell(transform.position - transform.forward * someRange);
var backCell = yourTileMap.GetTile(backCellPos);
我不知道为什么,但显然我没有将瓷砖本身实例化为一个瓷砖数组,所以每次我在网格上“放置”它们时,实际上是在放置一个空数组。
现在它修好了!只是需要找到一个很好的方式来删除所有后,移动和即时通讯设置

小心:确认
Tilemap.SetTile(矢量3int位置,Tile Tile)
参数
Pos
指的是网格位置。。这可能与碰撞器的实际世界矢量3位置(transform.position)不同。。。您是否检查了它们是否实际位于正确的位置?是的,请确保使用一个物理引擎;)Physics和Physics2D是两个完全独立的引擎,它们之间没有任何联系!如果你选择Physics.OverlapSphere,你将需要3D
Collider
s。。如果您想要
Physics2D.overlapscircle
您将需要2D
collizer2D
s(在2D中,Z轴基本上不存在)。。。你的屏幕截图看起来很像你想要在3D中工作是的,它们100%都在正确的位置,当我在位置(2,4,0)突出显示该磁贴,然后在层次结构中查看我的空磁贴阵列时,位置(2,4,0)处的空磁贴正好位于突出显示的磁贴(2,4,0)的顶部,因此它完全是应该的,但我认为添加这些3d对撞机是一个混乱,难道没有内置的方法来检查附近的瓷砖吗?我刚刚得到了播放器所在的磁贴,并从中加/减以突出显示中心磁贴周围的磁贴,但这也是一个混乱,不允许扩展,这就是为什么我想使用球体/圆。谢谢Hugo,但不幸的是,这没有得到相邻的磁贴。同样的问题仍然存在,获得中间的牌很容易,但是如果你通过手动减去和添加来获得相邻的牌,特别是如果你想让玩家有30个左右的合法移动,那么推断得到相邻的牌是一个混乱。我真的需要它来处理球体/圆的碰撞,这样半径就可以很容易地为不同的类更改。我以前是这样做的,但正如我所说的,它根本不可伸缩,也许你可以做一个for循环来循环,但每个tile都会有很多代码,这会非常混乱。使用colliders的这种方式对于可伸缩性和更少的代码来说要好得多,因为一旦它起作用,您所需要做的就是更改半径!不管怎样,我发现了问题所在!非常感谢你一直帮助我德胡戈你是老板!