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
相关产品推荐
相关产品推荐

