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

Unity C#问题:战士攻击Boss血量不更新,如何跨脚本修改数值?

问题分析:战士攻击Boss后血量不更新的原因

我尝试通过Warrior(战士)脚本修改Boss的血量,但数值完全没有更新。目前战士碰撞Boss时能触发检测且无报错,但Boss的血量数值未发生变化。另外,Warrior可以生成多个实例,相关代码如下:

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

public class WarriorHealthSystem : MonoBehaviour
{
    // private int warriorHealth = 100;  - dont need it atm
    private int warriorAttack = 20;
    // public int warriorDefense = 10;   - dont need it atm
    private int warriorCooldown = 5;
    private int timeSinceLastAttack;

    public GameObject bossHealth;
    

    // Start is called before the first frame update
    void Start()
    {
        bossHealth = GameObject.FindGameObjectWithTag("Boss");
    }

    // Update is called once per frame
    void Update()
    {

    }

    private void OnCollisionStay2D(Collision2D collision)
    {
        HealthSystemScript healthSystemScript = bossHealth.GetComponent<HealthSystemScript>();
        //Check if warrior is touching Boss object
        if (collision.gameObject.tag == "Boss" && Time.time > warriorCooldown)
        {
            // Abort if we already attacked recently.
            if (Time.time - timeSinceLastAttack < warriorCooldown) return;
            { 
                //if collided object has "Boss" Tag then:
                if (collision.gameObject.CompareTag("Boss"))
                {
                    WarriorAttack(warriorAttack, healthSystemScript.currentHealth);
                    Debug.Log("took 20dmg!");



                    // Remember that we recently attacked.
                    timeSinceLastAttack = (int)Time.time;


                }
            }
        }
    }
    private void WarriorAttack(int damage, int bossHealth)
    {
        bossHealth -= damage;
    }
}

核心原因及修复方案:

  • 值传递导致无效修改
    C#里int是值类型,把healthSystemScript.currentHealth传给WarriorAttack的bossHealth参数时,传的是一份数值副本,方法里修改副本根本不会影响原组件里的currentHealth。
    错误写法:

    WarriorAttack(warriorAttack, healthSystemScript.currentHealth);
    private void WarriorAttack(int damage, int bossHealth)
    {
        bossHealth -= damage; // 改的是副本,原血量没变化
    }
    

    直接修改原变量或者传递组件实例:

    // 方案1:直接在碰撞逻辑里修改
    healthSystemScript.currentHealth -= warriorAttack;
    
    // 方案2:修改WarriorAttack方法接收组件实例
    private void WarriorAttack(int damage, HealthSystemScript bossHealthSystem)
    {
        bossHealthSystem.currentHealth -= damage;
    }
    // 调用时传组件实例
    WarriorAttack(warriorAttack, healthSystemScript);
    
  • 冷却判断逻辑错误
    最外层条件里加了Time.time > warriorCooldown,游戏刚开始Time.time从0开始,小于5,直接导致攻击逻辑根本进不去。这个条件完全多余,后面已经有Time.time - timeSinceLastAttack < warriorCooldown的冷却判断,直接删掉即可。
    修正后的条件:

    if (collision.gameObject.CompareTag("Boss"))
    
  • 冗余的标签判断
    最外层已经判断了碰撞对象是Boss,里面又重复写了collision.gameObject.CompareTag("Boss"),完全没必要,直接删掉这段冗余代码。

  • 多战士实例的潜在注意点
    每个战士都通过GameObject.FindGameObjectWithTag("Boss")查找Boss,这个逻辑本身没问题,但如果Boss被销毁重建,可能会出现找不到的情况。可以考虑把Boss的HealthSystemScript做成单例,或者在场景里提前赋值引用,避免重复查找。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:37:07