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回调,当前代码适配的是非触发型碰撞。
后续范围伤害的提前思路
等你搞定单点销毁后,范围伤害就是把单点逻辑扩展为遍历操作:
- 以碰撞点为中心,计算范围内的所有Tilemap单元格
- 遍历每个单元格,判断是否存在瓦片并销毁
给你一个简单的范围破坏伪代码参考:
// 获取范围中心的单元格位置 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_




