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

2D游戏生命值系统实现:如何仅在踩踏敌人时对其造成伤害

Unity 2D 踩敌仅敌方受伤害的修复方案

问题根因

你当前的问题核心有两个:

  1. 玩家和敌人挂载了完全相同的碰撞伤害脚本,碰撞触发时两个物体的OnCollisionEnter2D会同时执行,双方都会调用对方的血量组件扣血,自然两边都掉血
  2. 法线判断逻辑存在缺陷:ContactPoint2D.normal是指向当前挂载脚本的物体的方向,你之前的写法没有区分敌我逻辑,且水平碰撞只判断了x正方向的法线,所以只有单侧碰撞生效

实现方法

建议将敌我碰撞逻辑拆分,不要共用同一套脚本,分别处理伤害判定:

1. 敌人挂载的碰撞脚本逻辑

仅当玩家撞到敌人头顶时,触发敌人掉血:

private void OnCollisionEnter2D(Collision2D coll)
{
    // 仅处理和玩家的碰撞
    if (coll.gameObject.CompareTag("Player")) 
    {
        Health enemyHealth = GetComponent<Health>();
        foreach (ContactPoint2D point2D in coll.contacts)
        {
            // 法线y≥0.5f说明碰撞来自敌人上方,即玩家踩头
            if (point2D.normal.y >= 0.5f)
            {
                enemyHealth.takeDamage(damage);
                // 可选:给玩家添加向上弹跳的力,增强手感
                Rigidbody2D playerRb = coll.gameObject.GetComponent<Rigidbody2D>();
                playerRb.velocity = new Vector2(playerRb.velocity.x, 6f);
            }
        }
    }
}

2. 玩家挂载的碰撞脚本逻辑

仅当玩家侧面/下方撞到敌人时,才触发玩家掉血,踩头时玩家不受伤害:

private void OnCollisionEnter2D(Collision2D coll)
{
    // 仅处理和敌人的碰撞
    if (coll.gameObject.CompareTag("Enemy")) 
    {
        Health playerHealth = GetComponent<Health>();
        foreach (ContactPoint2D point2D in coll.contacts)
        {
            // 法线y<0.5且水平分量更大,说明是侧面/下方碰撞
            if (point2D.normal.y < 0.5f && Mathf.Abs(point2D.normal.x) > Mathf.Abs(point2D.normal.y))
            {
                playerHealth.takeDamage(damage);
            }
        }
    }
}

可选优化方案

如果担心斜向碰撞法线判定不稳定,可以给敌人头顶单独加一个小的BoxCollider2D,勾选Is Trigger,专门用来检测玩家踩头,触发逻辑更稳定,不会出现边界判定错误。

问题示意图:
碰撞触发示意图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:06:03