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

Unity3D-禁用的游戏对象脚本丢失状态,unity3d,gameobject,Unity3d,Gameobject,我在游戏对象上有一个脚本组件(此处简化),在创建时使用testObject.setActive(false)将其禁用 禁用之前,GetTestValue的返回值为0。重新启用对象后,返回值为5 联合文件说: 使游戏对象处于非活动状态将禁用每个组件。。。任何附加到游戏对象的脚本将不再具有名为 然而,组件的行为向我表明,脚本所做的行为并不是真正的“禁用”,而是被破坏了。如果只有Update()停止了调用,那么如何解释状态丢失 这里潜在的问题是:在不破坏脚本的情况下临时禁用脚本的预期方法是什么?实际上

我在游戏对象上有一个脚本组件(此处简化),在创建时使用
testObject.setActive(false)
将其禁用

禁用之前,GetTestValue的返回值为0。重新启用对象后,返回值为5

联合文件说:

使游戏对象处于非活动状态将禁用每个组件。。。任何附加到游戏对象的脚本将不再具有名为

然而,组件的行为向我表明,脚本所做的行为并不是真正的“禁用”,而是被破坏了。如果只有
Update()
停止了调用,那么如何解释状态丢失


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

实际上发生的是,
Start()
函数在对象的生存期内只调用一次。因此,在开始时调用它并将值设置为0。但当您禁用它并重新激活它时,它不会被调用

这并没有改变这样一个事实,即即使在停用和重新激活脚本之后,您的值仍然应该是相同的(正如我们在注释部分中所指出的)

实现此功能的一种方法是使用
OnEnable()
,每次脚本设置为活动时都会调用该函数:

当对象处于启用和活动状态时,将调用此函数

因此,在您的脚本中,您将:

private void OnEnable()
{
    testValue = 0;
}
如果您知道此对象将被多次激活和停用,并且每次发生这种情况时,您绝对需要执行某些操作


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

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


在脚本上保留永远不会停用的重要信息,以便始终确保值始终正确。这样,您就不必总是重新生成正确的值,每次都检查它是否是您得到的正确值。

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

这并没有改变这样一个事实,即即使在停用和重新激活脚本之后,您的值仍然应该是相同的(正如我们在注释部分中所指出的)

实现此功能的一种方法是使用
OnEnable()
,每次脚本设置为活动时都会调用该函数:

当对象处于启用和活动状态时,将调用此函数

因此,在您的脚本中,您将:

private void OnEnable()
{
    testValue = 0;
}
如果您知道此对象将被多次激活和停用,并且每次发生这种情况时,您绝对需要执行某些操作


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

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


在脚本上保留永远不会停用的重要信息,以便始终确保值始终正确。这样一来,你就不必每次都重新生成正确的值,并检查它是否真的是你得到的好值。

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

结果表明,问题在于竞争条件。TestObject在Start()完成之前被停用,这导致无法正确初始化该对象。通过将初始化代码移动到Awake(),对象将在停用前正确设置其状态。

必须有比您所说的更多的内容。如果设置为false,则引擎不会调用所有Unity方法(Update、LateUpdate、Collision等),但仍然可以从其他位置调用public方法并影响脚本的状态。例如,您仍然可以从另一个脚本调用GetTestValue,即使它处于非活动状态。设置on和off不会影响变量的内容,也不会破坏实例。因此,要么你正在其他地方销毁并创建一个新对象,要么你正在查看两个不同的对象,要么你正在其他地方重置值。@Everts:你说的“更多”是对的。我应该明确指出,失活是在实例化之后立即发生的。肯定有比你说的更多的事情。如果设置为false,则引擎不会调用所有Unity方法(Update、LateUpdate、Collision等),但仍然可以从其他位置调用public方法并影响脚本的状态。例如,您仍然可以从另一个脚本调用GetTestValue,即使它处于非活动状态。设置on和off不会影响变量的内容,也不会破坏实例。因此,要么你正在其他地方销毁并创建一个新对象,要么你正在查看两个不同的对象,要么你正在其他地方重置值。@Everts:你说的“更多”是对的。我应该明确指出,停用在实例化之后立即发生。在对象的生命周期中只调用一次-很明显,在停用过程中不能销毁对象,因为正如您所说,Start()只调用一次。这并不能解释为什么对象会丢失它的内部状态。@如果它没有丢失它的值,你只是用那行代码来覆盖它。
public int testValue=5不可能是这种情况。将5赋值给testValue是在对象构造函数中完成的——这是编译器根据初始值设定项语法自动生成的。构造函数,比如Sta