You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity Tilemap可破坏瓦片:投射物碰撞获取瓦片问题求助

解决2D投射物碰撞销毁瓦片的问题

看来你已经推进了不少工作,核心问题其实是没有正确获取投射物与瓦片的实际碰撞点,反而用了投射物自身的transform.position,这才导致你手动调y值越调越乱。咱们一步步来修正:

第一步:获取准确的碰撞接触点

OnCollisionEnter2D回调里,别直接用gameObject.transform.position——投射物的中心位置未必就是碰撞瓦片的位置。取而代之的是用collision.contacts获取实际接触点,这才是投射物真正撞到瓦片的精准坐标。

第二步:正确转换为Tilemap单元格坐标

Tilemap的WorldToCell方法会自动把世界坐标转换成对应的瓦片单元格位置,完全不需要你手动修改y值!只要传入正确的碰撞点世界坐标即可。

修正后的完整代码

// 记得先在脚本里引用Tilemap组件,可在Inspector面板拖入赋值
public Tilemap tilemap;
public float radius; // 后续范围伤害会用到

IEnumerator OnCollisionEnter2D(Collision2D collision)
{
    // 跳过与玩家的碰撞
    if (collision.gameObject.CompareTag("Player"))
    {
        yield break;
    }

    // 获取第一个碰撞接触点(多接触点场景可按需调整)
    Vector2 hitPoint = collision.contacts[0].point;

    // 将世界坐标转换为Tilemap的单元格位置
    Vector3Int tilePosition = tilemap.WorldToCell(hitPoint);

    // 检查目标位置是否存在瓦片,避免无效操作
    if (tilemap.HasTile(tilePosition))
    {
        // 销毁该位置的瓦片
        tilemap.SetTile(tilePosition, null);
        Debug.Log($"已销毁瓦片:{tilePosition}");
    }

    // 销毁投射物自身(可根据游戏逻辑调整时机)
    Destroy(gameObject);

    yield return null;
}

关键细节说明

  • 务必确保tilemap变量已正确绑定到场景中的Tilemap组件,否则代码会失效。
  • CompareTag代替直接判断tag != "Player",这是Unity官方推荐的更高效、更安全的标签判断方式。
  • 如果你的投射物勾选了Is Trigger,要改用OnTriggerEnter2D回调,当前代码适配的是非触发型碰撞。

后续范围伤害的提前思路

等你搞定单点销毁后,范围伤害就是把单点逻辑扩展为遍历操作:

  1. 以碰撞点为中心,计算范围内的所有Tilemap单元格
  2. 遍历每个单元格,判断是否存在瓦片并销毁

给你一个简单的范围破坏伪代码参考:

// 获取范围中心的单元格位置
Vector3Int centerTile = tilemap.WorldToCell(hitPoint);
// 遍历3x3范围的单元格(可根据radius调整范围大小)
for (int x = -1; x <= 1; x++)
{
    for (int y = -1; y <= 1; y++)
    {
        Vector3Int targetTile = centerTile + new Vector3Int(x, y, 0);
        if (tilemap.HasTile(targetTile))
        {
            tilemap.SetTile(targetTile, null);
        }
    }
}

先把单点销毁的核心问题解决,后续扩展范围伤害就会轻松很多!

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

火山引擎 最新活动