You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2D中如何获取瓦片地图内特定瓦片的位置?

解决Tilemap碰撞时拾取物在瓦片附近生成的问题

方法一:直接用碰撞接触点生成(最简单)

你当前用col.transform.position拿到的是整个Tilemap的原点,自然会在(0,0)附近生成拾取物。直接用碰撞产生的接触点作为生成基准即可,修改后的代码如下:

using UnityEngine;

public class Drops : MonoBehaviour
{
    public GameObject wooddropling;
    public GameObject stonedropling;
    // 可在Inspector面板调整的随机生成范围
    public float spawnRange = 3f;

    void OnCollisionEnter2D(Collision2D col)
    {
        // 获取首个碰撞接触点的世界坐标
        Vector2 hitPos = col.contacts[0].point;
        
        if (col.gameObject.CompareTag("trees"))
        {
            Vector3 spawnPos = new Vector3(
                hitPos.x + Random.Range(-spawnRange, spawnRange),
                hitPos.y + Random.Range(-spawnRange, spawnRange),
                0f
            );
            Instantiate(wooddropling, spawnPos, Quaternion.Euler(0, 0, Random.Range(0f, 360f)));
        }
        else if (col.gameObject.CompareTag("stones"))
        {
            Vector3 spawnPos = new Vector3(
                hitPos.x + Random.Range(-spawnRange, spawnRange),
                hitPos.y + Random.Range(-spawnRange, spawnRange),
                0f
            );
            Instantiate(stonedropling, spawnPos, Quaternion.Euler(0, 0, Random.Range(0f, 360f)));
        }
    }
}

方法二:精准获取碰撞瓦片的中心位置(适合严格限定在瓦片范围内生成的场景)

如果需要确保拾取物生成在碰撞瓦片的中心附近,可通过Tilemap的坐标转换方法实现:

using UnityEngine;
using UnityEngine.Tilemaps;

public class Drops : MonoBehaviour
{
    public GameObject wooddropling;
    public GameObject stonedropling;
    public float spawnRange = 3f;

    void OnCollisionEnter2D(Collision2D col)
    {
        Tilemap tilemap = col.gameObject.GetComponent<Tilemap>();
        if (tilemap == null) return;

        // 将碰撞接触点转换为Tilemap的单元格坐标
        Vector2 hitPos = col.contacts[0].point;
        Vector3Int cellPos = tilemap.WorldToCell(hitPos);
        // 获取该瓦片的中心世界坐标
        Vector3 tileCenter = tilemap.GetCellCenterWorld(cellPos);
        
        if (col.gameObject.CompareTag("trees"))
        {
            Vector3 spawnPos = new Vector3(
                tileCenter.x + Random.Range(-spawnRange, spawnRange),
                tileCenter.y + Random.Range(-spawnRange, spawnRange),
                0f
            );
            Instantiate(wooddropling, spawnPos, Quaternion.Euler(0, 0, Random.Range(0f, 360f)));
        }
        else if (col.gameObject.CompareTag("stones"))
        {
            Vector3 spawnPos = new Vector3(
                tileCenter.x + Random.Range(-spawnRange, spawnRange),
                tileCenter.y + Random.Range(-spawnRange, spawnRange),
                0f
            );
            Instantiate(stonedropling, spawnPos, Quaternion.Euler(0, 0, Random.Range(0f, 360f)));
        }
    }
}

额外提示

  • 优先使用CompareTag()替代直接用==比较标签,既能提升性能,也能避免拼写错误导致的Bug
  • 若碰撞存在多个接触点,可根据需求选择首个接触点或遍历所有接触点
  • 将随机范围设为公开变量,无需修改代码就能在编辑器中调整生成范围

内容的提问来源于stack exchange,提问作者Ted Hutter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:05:32