统一更新图像 UI
Updating image UI with unity
我试图制作一个程序来更新玩家每回合拥有的心数(满心、半心和空心)。当我这样做时,我将该预制件的游戏对象实例化为一个变量,然后统一将其分配给我的 UI 面板。但是(我不确定但我认为)之前更新中使用的变量在下一个循环中被破坏后仍然被引用给我错误:
MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
这是更新循环:
void Update()
{
if (HP <= 0)
{
anim.SetBool("Death", true);
Destroy(GameObject.Find("Hearts"));
Destroy(GameObject.Find("Inventory"));
text.alignment = TextAnchor.LowerCenter;
text.text = "\n YOU DIED";
text.fontSize = 150;
text.color = new Color(255, 0, 0);
} else {
foreach (Transform child in GameObject.Find("Hearts").transform)
{
Destroy(child.gameObject);
}
for (var i = 0; i<(int)HP; i++)
{
GameObject Heart = Instantiate(heart, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
Heart.transform.SetParent(GameObject.Find("Hearts").transform);
}
if (HP - (float)((int)HP) == 0.5F) {
GameObject HalfHeart = Instantiate(halfheart, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
HalfHeart.transform.SetParent(GameObject.Find("Hearts").transform);
}
for (var i =0; i<Mathf.Floor(MaxHP-HP); i++)
{
GameObject EmptyHeart = Instantiate(emptyheart, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
EmptyHeart.transform.SetParent(GameObject.Find("Hearts").transform);
}
}
有没有办法在不创建变量的情况下实例化预制件?或者有办法使变量引用成为临时变量,这样它只持续一次更新?
预先感谢您的帮助!
问题在于,一旦生命值低于零,后续每次更新都会进入第一个if语句,并尝试一遍又一遍地删除"Hearts"和"Inventory"对象。您可以通过添加一个名为 isDead
的 bool 并将语句更改为 if (HP <= 0 && !isDead)
然后在块内设置 isDead = true
来解决此问题。这将防止它输入两次。
坦白说,你解决问题的方式完全是倒退的。正如其他人指出的那样,每帧删除和实例化对象效率非常低,而且 Transform.Find 也很慢。您实际上根本不需要销毁任何东西——只要 HP 发生变化,您就可以只拥有一份红心列表和 enable/disable 适当的数量。您可以在列表的末尾有一个半心,并在适当的时候 enable/disable 它 - 如果您使用的是 HorizontalLayoutGroup,它仍然会正确对齐。您可能想要这样做,以便您只能使用 属性 或函数(类似于 ModifyHealth(float amount)
)更改 HP,并将更新红心显示的逻辑放在那里。
我试图制作一个程序来更新玩家每回合拥有的心数(满心、半心和空心)。当我这样做时,我将该预制件的游戏对象实例化为一个变量,然后统一将其分配给我的 UI 面板。但是(我不确定但我认为)之前更新中使用的变量在下一个循环中被破坏后仍然被引用给我错误:
MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
这是更新循环:
void Update()
{
if (HP <= 0)
{
anim.SetBool("Death", true);
Destroy(GameObject.Find("Hearts"));
Destroy(GameObject.Find("Inventory"));
text.alignment = TextAnchor.LowerCenter;
text.text = "\n YOU DIED";
text.fontSize = 150;
text.color = new Color(255, 0, 0);
} else {
foreach (Transform child in GameObject.Find("Hearts").transform)
{
Destroy(child.gameObject);
}
for (var i = 0; i<(int)HP; i++)
{
GameObject Heart = Instantiate(heart, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
Heart.transform.SetParent(GameObject.Find("Hearts").transform);
}
if (HP - (float)((int)HP) == 0.5F) {
GameObject HalfHeart = Instantiate(halfheart, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
HalfHeart.transform.SetParent(GameObject.Find("Hearts").transform);
}
for (var i =0; i<Mathf.Floor(MaxHP-HP); i++)
{
GameObject EmptyHeart = Instantiate(emptyheart, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
EmptyHeart.transform.SetParent(GameObject.Find("Hearts").transform);
}
}
有没有办法在不创建变量的情况下实例化预制件?或者有办法使变量引用成为临时变量,这样它只持续一次更新? 预先感谢您的帮助!
问题在于,一旦生命值低于零,后续每次更新都会进入第一个if语句,并尝试一遍又一遍地删除"Hearts"和"Inventory"对象。您可以通过添加一个名为 isDead
的 bool 并将语句更改为 if (HP <= 0 && !isDead)
然后在块内设置 isDead = true
来解决此问题。这将防止它输入两次。
坦白说,你解决问题的方式完全是倒退的。正如其他人指出的那样,每帧删除和实例化对象效率非常低,而且 Transform.Find 也很慢。您实际上根本不需要销毁任何东西——只要 HP 发生变化,您就可以只拥有一份红心列表和 enable/disable 适当的数量。您可以在列表的末尾有一个半心,并在适当的时候 enable/disable 它 - 如果您使用的是 HorizontalLayoutGroup,它仍然会正确对齐。您可能想要这样做,以便您只能使用 属性 或函数(类似于 ModifyHealth(float amount)
)更改 HP,并将更新红心显示的逻辑放在那里。