简体   繁体   English

Unity TileMaps:如何返回占据特定Vector3位置的图块的图层名称,标签或其他标识信息?

[英]Unity TileMaps: How do I return the Layer name, Tag, or other identifying information of a tile that occupies a particular Vector3 location?

I am making a game that takes place on a Tile Map. 我正在制作一个在图块地图上进行的游戏。 Each Tile is 32x32, and when characters on my map move, they move 32 pixels at a time. 每个图块都是32x32,并且当我的地图上的字符移动时,它们一次移动32个像素。

What I would like to do is examine a Vector3 location and have it return what type of tile it is. 我想做的是检查Vector3的位置,并让它返回它是什么类型的图块。 Like, just the layer is fine. 就像,只是一层很好。

My map has 5 layers: 1. Floor: everyone can walk on this. 我的地图有5层:1.楼层:每个人都可以在此上行走。 2. Sink Floor: For tiles that are swamp or shallow water, the Player's sprite changes to an alternate version where they are sunk up to their hips while on the tile. 2.水槽地板:对于潮湿或浅水的瓷砖,玩家的精灵会变为备用版本,当他们在瓷砖上时会沉入臀部。 3. Low Block: Things like Pits, Deep Water. 3.低挡:坑,深水之类的东西。 Most characters are blocked unless they have flying. 除非它们飞起来,否则大多数角色都会被阻止。 4. Block: Walls. 4.块:墙。 They block all characters. 它们阻止所有字符。 5. Door: Sometimes blocks, sometimes passes through, depends if the player has the right key. 5.门:有时会阻塞,有时会通过,取决于玩家是否拥有正确的钥匙。

here is my Character class, that the other characters inherit from. 这是我的Character类,其他字符都继承自该类。

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

public abstract class Character : MonoBehaviour
{
    public int health, wounds;
    public List<Sprite> frame;

    protected BoxCollider2D boxCollider;

    protected virtual void Start()
    {
        boxCollider = GetComponent<BoxCollider2D>();
    }

    protected virtual void MoveNorth()
    { //moves the character 1 tile north
        Vector3 oldLoc = this.gameObject.transform.position;
        Vector3 newLoc = new Vector3(oldLoc.x, oldLoc.y + (Game.instance.TILESIZE / 100f), oldLoc.z);        
        this.gameObject.transform.position = newLoc;
    }

    protected virtual void MoveWest()
    {//moves the character 1 tile west
        Vector3 oldLoc = this.gameObject.transform.position;
        Vector3 newLoc = new Vector3(oldLoc.x - (Game.instance.TILESIZE / 100f), oldLoc.y, oldLoc.z);        
        this.gameObject.transform.position = newLoc;
    }

    protected virtual void MoveSouth()
    {//moves the character 1 tile south
        Vector3 oldLoc = this.gameObject.transform.position;
        Vector3 newLoc = new Vector3(oldLoc.x, oldLoc.y - (Game.instance.TILESIZE / 100f), oldLoc.z);
        this.gameObject.transform.position = newLoc;
    }

    protected virtual void MoveEast()
    {//moves the character 1 tile east
        Vector3 oldLoc = this.gameObject.transform.position;
        Vector3 newLoc = new Vector3(oldLoc.x + (Game.instance.TILESIZE / 100f), oldLoc.y, oldLoc.z);
        this.gameObject.transform.position = newLoc;
    }

    protected virtual void WarpTo(int x, int y)
    {
        //Warps Sprite to specified tile.
        float trueTileSize = Game.instance.TILESIZE / 100f;
        float trueX = (x * trueTileSize + (trueTileSize / 2f));
        float trueY = (y * trueTileSize + (trueTileSize / 2f));
        this.gameObject.transform.position = new Vector3(trueX, trueY, 0f);
        Debug.Log("Tile size = " + trueTileSize + "   X: " + trueX + "   y: "+ trueY);
    }
}

The plan is to insert code that will detect what tile is at NewLoc and then determine whether or not the move can be completed. 计划是插入代码,以检测NewLoc上的图块,然后确定是否可以完成移动。 I also want to detect what tile my characters are standing on so that I can change the sprite to the "Wading" version, but I don't have code for that yet. 我也想检测我的角色正站在什么瓷砖上,以便可以将精灵更改为“ Wading”版本,但是我还没有代码。

I am aware that this is probably basic. 我知道这可能是基本的。 I have spent a lot of time searching and researching, but either I am over-thinking what I am trying to do, or I am just plain not understanding the answers I have been finding. 我已经花了很多时间进行搜索和研究,但是要么我对自己想做的事情考虑得过头,要么就是我不明白自己所找到的答案。

I think that the solution is probably related to TileMap.GetTile, but I just do not understand how to use it, and I cannot seem to find an example using it in a way that I understand. 我认为该解决方案可能与TileMap.GetTile有关,但我只是不了解如何使用它,而且似乎无法以我理解的方式找到使用它的示例。

Any help is appreciated! 任何帮助表示赞赏!

Update, after Ignacio Alorre's advice: Here is my Map: 根据Ignacio Alorre的建议进行更新:这是我的地图: 全图层全图

Here is just "SinkFloor" layer: 这只是“ SinkFloor”层: 一层地图(和播放器)

Here are the settings for that layer: 这是该层的设置: 接收器楼层统一设置

and here is my new Character abstract class, with my attempt at adding the CheckTile function: 这是我新的Character抽象类,尝试添加CheckTile函数:

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

public abstract class Character : MonoBehaviour
{
public int health, wounds;
public List<Sprite> frame;

protected BoxCollider2D boxCollider;

protected virtual void Start()
{
    boxCollider = GetComponent<BoxCollider2D>();
}

protected virtual void MoveNorth()
{ //moves the character 1 tile north
    Vector3 oldLoc = this.gameObject.transform.position;
    Vector3 newLoc = new Vector3(oldLoc.x, oldLoc.y + 
(Game.instance.TILESIZE / 100f), oldLoc.z);
    checkTile(newLoc);
    this.gameObject.transform.position = newLoc;
}

protected virtual void MoveWest()
{//moves the character 1 tile west
    Vector3 oldLoc = this.gameObject.transform.position;
    Vector3 newLoc = new Vector3(oldLoc.x - (Game.instance.TILESIZE / 
100f), oldLoc.y, oldLoc.z);        
    this.gameObject.transform.position = newLoc;
}

protected virtual void MoveSouth()
{//moves the character 1 tile south
    Vector3 oldLoc = this.gameObject.transform.position;
    Vector3 newLoc = new Vector3(oldLoc.x, oldLoc.y - 
(Game.instance.TILESIZE / 100f), oldLoc.z);
    this.gameObject.transform.position = newLoc;
}

protected virtual void MoveEast()
{//moves the character 1 tile east
    Vector3 oldLoc = this.gameObject.transform.position;
    Vector3 newLoc = new Vector3(oldLoc.x + (Game.instance.TILESIZE / 
100f), oldLoc.y, oldLoc.z);
    this.gameObject.transform.position = newLoc;
}

protected virtual void WarpTo(int x, int y)
{
    //Warps Sprite to specified tile.
    float trueTileSize = Game.instance.TILESIZE / 100f;
    float trueX = (x * trueTileSize + (trueTileSize / 2f));
    float trueY = (y * trueTileSize + (trueTileSize / 2f));
    this.gameObject.transform.position = new Vector3(trueX, trueY, 0f);
    Debug.Log("Tile size = " + trueTileSize + "   X: " + trueX + "   y: "+ 
trueY);
}

protected virtual int checkTile(Vector3 tileLoc)
{
    RaycastHit hit;
    float distance = 1f;
    Vector3 dir = new Vector3(0, -1, 0);        
    //Vector3 locAdjusted = new Vector3(tileLoc.x, tileLoc.y, tileLoc.z - 
    //0.5f);

    int layer = -1;

    if(Physics.Raycast(tileLoc, dir, out hit, distance))
    {
        layer = hit.collider.gameObject.layer;
        Debug.Log("Layer #: " + layer);
    }       

    return layer;
  }
}

What is supposed to happen at this stage is that whenever my player (who inherits this class) moves up, checkTile(newLoc); 在这个阶段应该发生的事情是,只要我的播放器(继承了此类的播放器)向上移动,checkTile(newLoc); fires and when the RayCast hits a collider, it should report that feat in the console, along with what the layer is. 触发,当RayCast撞到对撞机时,它应报告控制台中的壮举以及图层的内容。 It is not. 它不是。 I have tried adjusting the rayCast origin above the layer I am looking at, which should at least return the Character, but it does not. 我尝试过在要查看的图层上方调整rayCast原点,该图层至少应返回Character,但事实并非如此。 I am thinking I need to look into Raycasting a bit closer to see if I can figure out how to do this. 我想我需要更深入地研究Raycasting,以查看是否可以解决该问题。 Once I get it to work, it should be EXACTLY what I need. 一旦它开始工作,它应该正是我所需要的。

If you want to check the tile under your GameObject, you could have a dummy and invisible game object moving to the position the player select and call something like: 如果要检查GameObject下的磁贴,则可以将一个虚拟且不可见的游戏对象移动到玩家选择的位置并调用类似以下内容:

int checkTileType()
{
    RaycastHit hit;
    float distance = 1f;
    Vector3 dir = new Vector3(0, -1);

    int layer = -1;

    //With with you check what is under the game object
    if(Physics.Raycast(transform.position, dir, out hit, distance))
    {
        //With this you can extract the layer number
        layer = hit.collider.gameObject.layer
    }

    return layer;

}

Later you will need a switch to determine what to do with the information. 稍后,您将需要进行切换以确定如何处理该信息。

However this may be a little bit complex. 但是,这可能有点复杂。

Once I did something similar to what you are after. 有一次我做了类似您所追求的事情。 I solved in the following way: 我通过以下方式解决了:

I created a method to generate the map, which display the tiles in a random way. 我创建了一种生成地图的方法,该方法以随机方式显示图块。 In my case there were just three: path, wall and bush. 就我而言,只有三个:路径,墙壁和灌木丛。

In my case I had a fixed dimension of the map. 就我而言,我的地图尺寸固定。 I believe I was using as well 32x32 tiles, and I think the map had 10 tiles wide and 10 tiles height. 我相信我也使用32x32瓦片,并且我认为地图上有10瓦片宽和10瓦片高。 So I created in that same method a tilesVector of size 100 where I was storing the type of each tile in the map (1,2 and 3 so it was easy to read with a switch) 因此,我使用相同的方法创建了大小为100的tilesVector ,用于在地图中存储每个图块的类型(1、2和3,因此使用开关即可轻松读取)

What I did then was to keep a variable idx of the current position in the player GameObject. 然后,我要做的就是在玩家GameObject中保留当前位置的变量idx。 Then depending on the next movement of the player: 然后根据玩家的下一动作:

  • If the movement was horizontal I pointed to the next position of the vector with a idx+1 right movement, idx-1 left movement. 如果运动是水平的,则我指向向量的下一个位置,其中idx+1向右运动, idx-1向左运动。
  • If the movement was versital I pointed to the next position of the vector with a idx+10 down movement, idx-10 left movement. 如果该运动是横向运动,则我以idx+10向下运动指向矢量的下一个位置, idx-10左运动。

Note : It was necessary to check boundaries as well, to avoid null pointer exceptions and to avoid the guy moves from the last tile on the right to the first one of the left of the next row. 注意 :还必须检查边界,以避免空指针异常,并避免该家伙从右侧的最后一个图块移动到下一行的左侧的第一个图块。 You can add this validator using the % operator and checking the next tile is not idx < 0 or idx > 100 . 您可以使用%运算符添加此验证器,并检查下一个图块不是idx < 0idx > 100

And basically that idx is the index inside the tilesVector which will retrieve the type of tile the player is trying to move to. 基本上,idx是tilesVector内的tilesVector ,它将检索玩家尝试移动到的瓦片的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM