我遵循了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
方法中,它也已正确设置。
答案 0 :(得分:0)
在您的 HealthBarController.cs 脚本的AddHealthBar
方法中,您将角色的Health
类分配给Prefab healthBar
,而不是新创建的Health
实例newHealthBar
。
只需将healthBar.SetHealth(health);
替换为newHealthBar.SetHealth(health);
(第30行)。