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

Unity跨脚本获取Enemy非公开currentHealth变量修复二阶段攻击伤害bug

问题修复方案

核心问题原因

  • Enemy脚本中的currentHealth为私有变量,外部脚本无法直接访问
  • OrionUpgradedCombat中获取的enemyScript是Start方法内的局部变量,Update、协程方法中无法调用
  • 无论当前Boss血量阶段,都会直接启动第二击的协程,就算动画不播放,碰撞检测逻辑仍然会执行,导致无动画也出伤害
  • Update中反复对secondAttackDamage做减法操作,会导致伤害值异常变为负数,不符合需求

修复步骤

1. 修改Enemy脚本,暴露血量的只读访问权限

给私有变量currentHealth添加公共只读属性,既保证外部不能随意修改血量,又能让战斗脚本读取当前血量值:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public Component enemyCombat;
    public Component aiScript;
    public Animator animator;
    public int maxHealth = 100;
    // 新增:公共只读属性,外部可以读取当前血量
    public int CurrentHealth => currentHealth;
    int currentHealth;

    // Start is called before the first frame update
    void Start()
    {
        currentHealth = maxHealth;
    }

    public void TakeDamage(int damage)
    {
        currentHealth -= damage;
        animator.SetTrigger("Hurt");

        if (currentHealth <= 50)
        {
            animator.SetBool("IsAngry", true);
        }

        if(currentHealth <= 0)
        {
            Die();
        }
    }

    void Die()
    {
        Debug.Log("Enemy Died");
        animator.SetBool("IsDead", true);
        Destroy(aiScript);
        Destroy(enemyCombat);
        GetComponent<Collider2D>().enabled = false;
        this.enabled = false;      
    }
}

2. 修改OrionUpgradedCombat脚本,调整第二击触发逻辑

把enemyScript改为全局成员,血量高于50时直接不启动第二击协程,从根源避免无意义的伤害判定:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OrionUpgradedCombat : MonoBehaviour
{
    public Animator animator;
    // 可直接在Inspector拖拽Enemy组件赋值,也支持动态获取
    public Enemy enemyScript;
    public Transform AttackPoint;
    public Transform secondAttackPoint;
    public float attackRange = 0.5f;
    public float secondAttackRange = 0.5f;
    public LayerMask enemyLayers;
    public int attackDamage = 8;
    public int secondAttackDamage = 15;
    public float attackRate = 2f;
    float nextAttackTime = 0f;

    void Start()
    {
        // 如果没有在Inspector赋值,自动动态获取
        if(enemyScript == null)
            enemyScript = GetComponent<Enemy>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Time.time >= nextAttackTime)
        {
            StartCoroutine(Attack());
            // 只有血量低于等于50的时候才启动第二击协程,高于50时完全不执行第二击逻辑
            if (enemyScript.CurrentHealth <= 50)
            {
                StartCoroutine(AttackTwo());
            }
            nextAttackTime = Time.time + 8f / attackRate;
        }
    }

    public IEnumerator Attack()
    {
        yield return new WaitForSeconds(2);
        animator.SetTrigger("Attack");
        Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackPoint.position, attackRange, enemyLayers);
        foreach (Collider2D enemy in hitEnemies)
        {
            enemy.GetComponent<PlayerHealth>().TakeDamage(attackDamage);
        }
    }

    public IEnumerator AttackTwo()
    {
        yield return new WaitForSeconds(4);
        animator.SetTrigger("AttackTwo");
        Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(secondAttackPoint.position, secondAttackRange, enemyLayers);
        foreach (Collider2D enemy in hitEnemies)
        {
            enemy.GetComponent<PlayerHealth>().TakeDamage(secondAttackDamage);
        }
    }

    void OnDrawGizmosSelected()
    {
        if (AttackPoint == null)
            return;
        Gizmos.DrawWireSphere(AttackPoint.position, attackRange);
        // 新增第二攻击点的范围绘制,方便调试
        if (secondAttackPoint != null)
            Gizmos.DrawWireSphere(secondAttackPoint.position, secondAttackRange);
    }
}

注意事项

  • 优先在Inspector面板把Enemy组件拖拽到OrionUpgradedCombat的enemyScript字段上,避免动态获取出错
  • 该方案直接从触发逻辑层面屏蔽了一阶段的第二击,不需要反复修改伤害值,性能更高也不会出现异常伤害问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:27:02