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

Unity实现同类型对象碰撞体互相忽略碰撞的方法

解决方案

先把你现在的设置问题说清楚:别给敌人碰撞体开Is Trigger = true。
这个属性勾上之后,碰撞体就变成纯触发器了,完全不会产生物理阻挡、推挤效果,和任何物体碰上去都只会触发OnTriggerEnter/Stay/Exit回调,根本挡不住,这就是你所有敌人跑着跑着全叠一块的根本原因。

要实现选择性忽略某类碰撞、剩下的碰撞保持正常物理效果,两种方案随便选,优先用第一种,性能最好。

方案1:用Layer层统一配置碰撞规则(首推,零运行时开销)

这是Unity原生做的批量碰撞过滤,不用写多余代码,规则固定的话用这个最省事:

  1. 打开Edit -> Project Settings -> Tags and Layers,新建一个专门给敌人用的层,比如叫Enemy
  2. 把所有敌方对象的Layer都改成刚建的Enemy
  3. 打开Edit -> Project Settings -> Physics 2D,找到最下面的Layer Collision Matrix(层碰撞矩阵):
    • 如果你要的是敌人之间不堆叠、能互相挡住,但是可以穿过所有不是敌人的物体(墙、道具、甚至玩家):找到Enemy对应的行和列,把Enemy和其他所有非Enemy层的勾选全取消,只留Enemy和Enemy的勾就行。这样敌人只会和同层的其他敌人产生碰撞阻挡,碰到其他层的东西直接穿过去,不会被卡。
    • 如果你确实要敌人之间能互相穿、不产生碰撞,但是碰到非敌人的物体会正常被挡住:只需要把Enemy层和Enemy层对应的勾取消,其他层的勾保留就好。

方案2:用Physics2D.IgnoreCollision()动态设置

如果你的敌人是运行时动态生成的,或者碰撞规则需要实时变,就用这个API,用法没你想的复杂:

  • 方法签名:Physics2D.IgnoreCollision(Collider2D a, Collider2D b, bool ignore = true)
  • 逻辑很简单:第三个参数传true,就告诉物理系统a和b这两个碰撞体之间不要算碰撞,碰到了直接穿,既不会有物理推挤,也不会触发碰撞相关回调;传false就恢复正常碰撞。
  • 给个现成的参考代码,挂在敌人预制体上就行,下面的例子是生成敌人时自动忽略所有敌人之间的碰撞,如果你要反过来忽略和非敌人的碰撞,改个判断条件就可以:
using UnityEngine;
using System.Collections.Generic;

public class Enemy : MonoBehaviour
{
    // 全局存所有活着的敌人的碰撞体
    private static readonly List<Collider2D> _allEnemyCols = new List<Collider2D>();
    private Collider2D _myCol;

    private void Awake()
    {
        _myCol = GetComponent<Collider2D>();
        // 和已经存在的所有敌人都设置忽略碰撞
        foreach (var otherCol in _allEnemyCols)
        {
            Physics2D.IgnoreCollision(_myCol, otherCol, true);
        }
        _allEnemyCols.Add(_myCol);
    }

    private void OnDestroy()
    {
        // 敌人死了就从列表里删掉
        _allEnemyCols.Remove(_myCol);
    }
}

提个醒:这个API只改两个传入碰撞体之间的碰撞规则,不会改碰撞体本身的Is Trigger状态,也不会影响这两个碰撞体和其他对象的碰撞逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:48:16