Unity 2D中如何获取玩家前方、脚下及周围的Tile瓦片?
Unity 2D Tilemap 瓦片获取与高亮方案
需求梳理
- 按下U键时可获取两类瓦片:玩家周围指定范围内的所有瓦片(包含玩家脚下瓦片)、玩家正前方1格的单个瓦片
- 玩家取出可放置道具时,Tilemap上可高亮显示道具即将放置的位置
- 高亮位置需适配玩家的实时旋转朝向,替代当前固定高亮玩家上方瓦片的实现
核心实现思路
1. 坐标转换统一处理
不要手动对玩家世界坐标做四舍五入计算网格位置,直接使用Unity Grid组件自带的WorldToCell(Vector3 worldPos)方法,将玩家世界坐标直接转换为Tilemap对应的网格坐标,适配不同网格大小、偏移配置的项目,精度更高且兼容性更好。
2. 周围瓦片批量获取
按下U键时触发遍历逻辑:
- 先定义需要获取的周围范围,例如3x3范围就取x轴偏移从-1到1,y轴偏移从-1到1
- 循环计算每个偏移对应的网格坐标
playerCellPos + new Vector3Int(xOffset, yOffset, 0) - 调用
Tilemap.GetTile(Vector3Int cellPos)获取对应位置的瓦片,存入集合即可得到玩家周围所有瓦片 - 要单独取脚下瓦片,直接取偏移为(0,0)的坐标对应的瓦片即可
3. 朝向适配的正前方瓦片获取
- 在玩家控制脚本中新增字段存储当前朝向向量,例如面向上下左右分别对应
Vector2Int.up/down/left/right,玩家切换朝向时同步更新该字段 - 正前方1格的网格坐标 = 玩家所在网格坐标 + 朝向向量转换的Vector3Int
- 不管是获取正前方瓦片还是高亮放置位,都直接使用该坐标即可自动适配朝向
4. 放置位高亮优化
- 单独封装高亮更新方法,触发条件为:玩家移动、玩家切换朝向、玩家切换到/取消可放置道具状态,不需要每帧都执行位置判断,降低性能消耗
- 每次更新高亮前先清空上一次高亮位置的瓦片,再给当前目标位置赋值高亮瓦片即可
5. 边界校验补充
所有瓦片获取、高亮操作执行前,先判断目标网格坐标是否在Tilemap的有效坐标范围内,避免出现越界、空引用报错。
现有代码可调整方向
- 原有坐标计算逻辑替换为
grid.WorldToCell(player.transform.position)获取准确网格坐标 - 新增U键监听逻辑
if(Input.GetKeyDown(KeyCode.U)),触发时执行瓦片获取逻辑 - 新增玩家朝向字段,与玩家控制脚本的朝向状态同步,用于计算正前方坐标
- 高亮逻辑增加判断条件,仅当玩家持有可放置道具时才执行,无道具时自动清除高亮
现有实现代码
using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEngine; using UnityEngine.Tilemaps; public class PlayerGrid : MonoBehaviour { private Grid grid; [SerializeField] private Tilemap interactiveMap = null; [SerializeField] private Tilemap pathMap = null; [SerializeField] private Tile hoverTile = null; [SerializeField] private Tile pathTile = null; public GameObject player; private Vector3Int previousMousePos = new Vector3Int(); // Start is called before the first frame update void Start() { grid = gameObject.GetComponent<Grid>(); } // Update is called once per frame void Update() { var px = Mathf.RoundToInt(player.transform.position.x); var py = Mathf.RoundToInt(player.transform.position.y); var tilePos = new Vector3Int(px, py, 0); if (!tilePos.Equals(previousMousePos)) { interactiveMap.SetTile(previousMousePos, null); // Remove old hoverTile interactiveMap.SetTile(tilePos, hoverTile); previousMousePos = tilePos; } // Left mouse click -> add path tile if (Input.GetMouseButton(0)) { pathMap.SetTile(tilePos, pathTile); } // Right mouse click -> remove path tile if (Input.GetMouseButton(1)) { pathMap.SetTile(tilePos, null); } } }
内容的提问来源于stack exchange,提问作者Dustin
相关产品推荐
相关产品推荐

