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

如何实现多个Warrior实例同时攻击单个敌人并正确统计伤害?

如何实现多个Warrior实例同时攻击单个敌人并正确统计伤害?

兄弟,我看了你的代码,问题其实很明显——你把攻击冷却的逻辑放到了敌人脚本里,这就导致不管多少个Warrior过来攻击,只要有一个触发了伤害,敌人就会进入冷却状态,其他Warrior的攻击都被挡住了。

咱们来拆解下问题:你的OnCollisionStay2D里用了敌人自己的_TimeSinceLastAttack和冷却判断,相当于给敌人加了一个“全局冷却”,所有攻击者共享这个冷却,自然没办法同时触发多个伤害。

解决方案:把攻击逻辑移到Warrior那边去!

每个Warrior应该自己管理攻击间隔,而不是让敌人来控制。敌人只需要专注一件事:接收伤害并更新血量。这样多个Warrior就能各自独立攻击,互不干扰。

第一步:给Warrior写专属的攻击脚本

新建一个WarriorAttackScript挂在每个Warrior对象上,让每个战士自己判断什么时候能攻击:

using UnityEngine;

public class WarriorAttackScript : MonoBehaviour
{
    [SerializeField] private int attackPower = 20; // 每个战士的攻击力
    [SerializeField] private float attackCooldown = 5f; // 每个战士的攻击间隔
    private float _timeSinceLastAttack = 0f;

    private void Update()
    {
        // 持续累加时间,用来判断是否到了下次攻击的时间
        _timeSinceLastAttack += Time.deltaTime;
    }

    private void OnCollisionStay2D(Collision2D collision)
    {
        // 碰到敌人,且自己的冷却时间到了
        if (collision.gameObject.CompareTag("Enemy") && _timeSinceLastAttack >= attackCooldown)
        {
            // 获取敌人的血量脚本
            HealthSystemScript enemyHealth = collision.gameObject.GetComponent<HealthSystemScript>();
            if (enemyHealth != null)
            {
                // 调用敌人的受伤方法
                enemyHealth.TakeDamage(attackPower);
                Debug.Log($"{gameObject.name} 给敌人造成了 {attackPower} 点伤害!");
                // 重置自己的冷却时间
                _timeSinceLastAttack = 0f;
            }
        }
    }
}

第二步:简化敌人的血量脚本

把敌人脚本里和攻击冷却相关的逻辑全部删掉,让它只负责血量管理:

using UnityEngine;
using UnityEngine.UI;

public class HealthSystemScript : MonoBehaviour
{
    public int maxHealth = 100;
    public int currentHealth;
    public HealthBar HealthBar;

    private void Start()
    {
        currentHealth = maxHealth;
        HealthBar.SetMaxHealth(maxHealth);
    }

    void Update()
    {
        // 原代码里的HealthBar.MaxHealth(currentHealth)应该是笔误,改成SetHealth更新当前血量显示
        HealthBar.SetHealth(currentHealth);
        
        // 测试用的F键销毁,保留也没关系
        if (Input.GetKey(KeyCode.F))
        {
            Destroy(gameObject);
        }
    }

    public void TakeDamage(int damage)
    {
        currentHealth -= damage;
        HealthBar.SetHealth(currentHealth);

        // 受伤后直接判断是否死亡,不用在Update里重复检测
        if (currentHealth <= 0)
        {
            Destroy(gameObject);
        }
    }
}

为什么这样改就解决问题了?

  • 每个Warrior独立控制自己的攻击冷却,多个战士同时碰敌人时,各自到了冷却时间就会触发伤害,敌人会依次接收每个战士的攻击。
  • 敌人的职责变得单一,只处理血量变化和血条更新,代码更清晰,也不容易出逻辑冲突。
  • 完全不需要维护什么Warrior列表,每个战士自己会处理攻击逻辑,简单高效。

额外小建议

  • 如果你担心多个战士同时触发碰撞导致短时间内多次伤害,可以给敌人加个短暂的无敌帧(比如受伤后0.1秒内不接收伤害),但一般情况下没必要,除非你的游戏有特殊需求。
  • 记得给敌人对象打上Enemy标签,不然Warrior的碰撞检测找不到目标哦!

备注:内容来源于stack exchange,提问作者Aru Alonless

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 11:59:53