Unity3D - 禁用游戏对象脚本丢失状态

Unity3D - Disabled GameObject scripts losing state

我在 GameObject(此处简化)上有一个脚本组件,它在创建时被禁用,使用 testObject.setActive(false)

using UnityEngine;

public TestObject : MonoBehaviour {
    public int testValue = 5;

    void Start() {
        testValue = 0;
    }

    public int GetTestValue() {
        return testValue;
    }
}

禁用前,GetTestValue 的 return 为 0。重新启用对象后,return 为 5。

Unity 文档说:

Making a GameObject inactive will disable every component ... Any scripts that you have attached to the GameObject will no longer have Update() called ...

然而,组件的行为向我暗示脚本生成的 MonoBehaviour 并不是真正的 'disabled',而是被破坏了。如果只是 Update() 停止被调用,那如何解释状态丢失?

这里的根本问题是:在不破坏脚本的情况下临时禁用脚本的预期方法是什么?

实际上 Start() 函数 在一个对象的生命周期中只被调用一次 。所以一开始它被调用并将值设置为0。但是当你禁用它并重新激活它时,它不会被调用。

这并没有改变这样一个事实,即即使在停用和重新激活脚本之后,您的值仍然应该相同(正如我们在评论部分中发现的那样)。

完成这项工作的一种方法是使用 OnEnable(),每次脚本设置为活动时都会调用它。 More info on OnEnable:

This function is called when the object becomes enabled and active.

因此在您的脚本中您将拥有:

private void OnEnable()
{
    testValue = 0;
}

如果您知道此对象将被激活和停用多次,并且每次发生这种情况时您绝对需要做一些事情。


这引出了我的第二点和我的建议:

不要在将被停用和重新激活的脚本上保留重要值。

将重要信息保存在一个永远不会被停用的脚本上,这样您就可以始终确保该值始终是正确的。这样一来,您就不必总是重新生成正确的值并每次都检查它是否真的是您获得的好值。

事实证明,这个问题是竞争条件。 TestObject 在 Start() 完成之前被停用,这导致对象无法正确初始化。通过将初始化代码移至 Awake(),对象在停用前正确设置其状态。

我有相反的情况..我试图在 Awake() 中设置一个动画参数并立即停用。参数值没有改变。但是如果我把它放在 Start() 中,值就会被设置。