C# Unity Tilemaps,用于突出显示瓷砖/单元的单个瓷砖碰撞检测,奇怪的行为
我已经在这个问题上工作了几天,试图创建一个正方形的瓷砖网格,使用Unity Tilemaps似乎是最有效的方法,而且它已经内置了很多 我想突出球员周围的瓷砖,这样他就可以看到什么是合法的举动。 我在底图(地面/草地)的顶部使用了第二个Tilemap 第二个Tilemap,highlightsMap由不可见的瓷砖组成,当出现C# Unity Tilemaps,用于突出显示瓷砖/单元的单个瓷砖碰撞检测,奇怪的行为,c#,unity3d,grid,collision,tile,C#,Unity3d,Grid,Collision,Tile,我已经在这个问题上工作了几天,试图创建一个正方形的瓷砖网格,使用Unity Tilemaps似乎是最有效的方法,而且它已经内置了很多 我想突出球员周围的瓷砖,这样他就可以看到什么是合法的举动。 我在底图(地面/草地)的顶部使用了第二个Tilemap 第二个Tilemap,highlightsMap由不可见的瓷砖组成,当出现Physical.SphereOverlap或Physics2D.CircleAll 为了检测每个平铺,我在一个空对象上添加了一个长方体碰撞器,并在平铺贴图网格的顶部创建了这些
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,你将需要3DCollider
s。。如果您想要Physics2D.overlapscircle
您将需要2Dcollizer2D
s(在2D中,Z轴基本上不存在)。。。你的屏幕截图看起来很像你想要在3D中工作是的,它们100%都在正确的位置,当我在位置(2,4,0)突出显示该磁贴,然后在层次结构中查看我的空磁贴阵列时,位置(2,4,0)处的空磁贴正好位于突出显示的磁贴(2,4,0)的顶部,因此它完全是应该的,但我认为添加这些3d对撞机是一个混乱,难道没有内置的方法来检查附近的瓷砖吗?我刚刚得到了播放器所在的磁贴,并从中加/减以突出显示中心磁贴周围的磁贴,但这也是一个混乱,不允许扩展,这就是为什么我想使用球体/圆。谢谢Hugo,但不幸的是,这没有得到相邻的磁贴。同样的问题仍然存在,获得中间的牌很容易,但是如果你通过手动减去和添加来获得相邻的牌,特别是如果你想让玩家有30个左右的合法移动,那么推断得到相邻的牌是一个混乱。我真的需要它来处理球体/圆的碰撞,这样半径就可以很容易地为不同的类更改。我以前是这样做的,但正如我所说的,它根本不可伸缩,也许你可以做一个for循环来循环,但每个tile都会有很多代码,这会非常混乱。使用colliders的这种方式对于可伸缩性和更少的代码来说要好得多,因为一旦它起作用,您所需要做的就是更改半径!不管怎样,我发现了问题所在!非常感谢你一直帮助我德胡戈你是老板!