Unity 2D如何获取子弹与敌人精确碰撞点且不产生物理推力
解决方案
方案1:保留OnCollisionEnter2D,通过碰撞层矩阵屏蔽物理交互
这是改动最小、适配性最高的方案:
- 给子弹、敌人分别设置独立的Unity Layer(比如命名为Bullet、Enemy)
- 打开
Edit > Project Settings > Physics 2D面板,找到Layer Collision Matrix配置项 - 取消勾选Bullet层和Enemy层对应的交互复选框,两者就不会产生物理碰撞推力,但碰撞检测事件依然会正常触发
- 原有OnCollisionEnter2D代码无需修改,
collision.contacts[0].point仍可返回精确碰撞点
方案2:保留触发器属性,手动计算碰撞接触点
如果不想调整碰撞层配置,可以直接在OnTriggerEnter2D逻辑中计算两个碰撞体的最近接触点:
//Bullet.cs void OnTriggerEnter2D(PolygonCollider2D enemyCollider) { var enemy = enemyCollider.GetComponent<Enemy>(); if (enemy != null && enemy.isAlive) { if (enemy.impactSprite != null) { Collider2D bulletCollider = GetComponent<Collider2D>(); // 计算两个碰撞体之间的最近点,即实际碰撞接触位置 Vector2 contactPoint = Physics2D.Distance(bulletCollider, enemyCollider).closestPoint; Instantiate(enemy.impactSprite, contactPoint, transform.rotation); } enemy.TakeDamage(damage); Destroy(gameObject); return; } }
该方案不需要修改碰撞体的触发器属性,完全无物理交互,仅增加极微的计算开销,适配所有子弹形状。
方案3:固定偏移修正(仅适合规则子弹)
如果你的子弹是固定朝向飞行的规则形状,可以直接修正特效生成的位置偏移:
//Bullet.cs void OnTriggerEnter2D(PolygonCollider2D hitInfo) { var enemy = hitInfo.GetComponent<Enemy>(); if (enemy != null && enemy.isAlive) { if (enemy.impactSprite != null) { // 按子弹飞行方向偏移半个子弹宽度,25像素转世界单位的计算公式:像素值 / 项目Pixels Per Unit(默认100) float offset = 25f / 100f; Vector3 spawnPos = transform.position + transform.right * offset; Instantiate(enemy.impactSprite, spawnPos, transform.rotation); } enemy.TakeDamage(damage); Destroy(gameObject); return; } }
该方案零额外开销,仅适合固定朝向的规则子弹,不支持旋转、不规则形状的子弹。
内容的提问来源于stack exchange,提问作者Santi
相关产品推荐
相关产品推荐

