方法执行后丢失参考

时间:2019-11-03 13:47:11

标签: c# unity3d

我遵循了video的有关如何自动为单位创建运行状况栏的信息。 这是我的HealthBar班。

    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;

    public class HealthBar : MonoBehaviour
    {
        #region SerializeFields

        [SerializeField] private Image foregroundImage;
        [SerializeField] private float updateSpeedInSec = 0.5f;
        [SerializeField] private float positionOffset = 1f;

        #endregion

        #region NonSerializeFields

        private Health health;

        #endregion

        public void SetHealth(Health healthToSet)
        {
            health = healthToSet;
            healthToSet.OnHealthPctChanged += HandleHealthChanged;
        }

        private void HandleHealthChanged(float pct)
        {
            StartCoroutine(ChangeToPct(pct));
        }

        private IEnumerator ChangeToPct(float pct)
        {
            float preChangedPct = foregroundImage.fillAmount;
            float elapsedTime = 0f;

            while (elapsedTime < updateSpeedInSec)
            {
                elapsedTime += Time.deltaTime;
                foregroundImage.fillAmount = Mathf.Lerp(preChangedPct, pct, elapsedTime / updateSpeedInSec);
                yield return null;
            }

            foregroundImage.fillAmount = pct;
        }

        private void LateUpdate()
        {
            var worldToScreenPoint = Camera.main
                .WorldToScreenPoint(health.transform.position + (Vector3) Vector2.up * positionOffset);
            transform.position = worldToScreenPoint;
        }

        private void OnDestroy()
        {
            health.OnHealthPctChanged -= HandleHealthChanged;
        }
    }

这是我的HealthBarController类,在画布上调用SetHealth方法。

using System.Collections.Generic;
using UnityEngine;

public class HealthBarController : MonoBehaviour
{
    #region SerializeFields

    [SerializeField] private HealthBar healthBar;

    #endregion

    #region NonSerializeFields

    private Dictionary<Health, HealthBar> healthBars = new Dictionary<Health, HealthBar>();

    #endregion

    private void Awake()
    {
        Health.OnHealthAdded += AddHealthBar;
        Health.OnHealthRemoved += RemoveHealthBar;
    }

    private void AddHealthBar(Health health)
    {
        if (healthBars.ContainsKey(health)) return;

        var newHealthBar = Instantiate(healthBar, transform);
        healthBars.Add(health, newHealthBar);
        healthBar.SetHealth(health);
    }

    private void RemoveHealthBar(Health health)
    {
        if (!healthBars.ContainsKey(health)) return;

        Destroy(healthBars[health].gameObject);
        healthBars.Remove(health);
    }
}

这是我关于玩家角色的健康课程。

using System;
using UnityEngine;

public class Health : MonoBehaviour, IDamageable
{
    #region SerializeFields

    [SerializeField] protected int maxHealth = 100;

    public static event Action<Health> OnHealthAdded = delegate {  };
    public static event Action<Health> OnHealthRemoved = delegate {  };
    public event Action<float> OnHealthPctChanged = delegate {  };

    #endregion

    #region NonSerializeFields

    protected int currentHealth;

    #endregion

    private void OnEnable()
    {
        currentHealth = maxHealth;
        OnHealthAdded(this);
    }

    public void TakeDamage(int damage)
    {
        currentHealth -= damage;
        float currentHealthPct = (float) currentHealth / maxHealth;
        OnHealthPctChanged(currentHealthPct);

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

    protected void Die()
    {
        OnHealthRemoved(this);
        Destroy(gameObject);
    }
}

我遇到的问题是LateUpdate方法中,health字段为空,即使在SetHealth方法中,它也已正确设置。

1 个答案:

答案 0 :(得分:0)

在您的 HealthBarController.cs 脚本的AddHealthBar方法中,您将角色的Health类分配给Prefab healthBar,而不是新创建的Health实例newHealthBar

只需将healthBar.SetHealth(health);替换为newHealthBar.SetHealth(health);(第30行)。