这是一个我一直在努力回答的非常具体的问题。我有一个简单的脚本,可以在运行时唤醒/销毁期间创建/销毁组件:
// Simple script that creates and destroys an AudioSource component in runtime.
public class SimpleScript : MonoBehaviour {
// Runtime AudioSource component to be used.
private AudioSource source = null;
void Awake() {
source = gameObject.AddComponent<AudioSource>();
source.hideFlags = HideFlags.HideAndDontSave;
}
void OnDestroy() {
Destroy(source);
}
void Update() {
// Do stuff with |source| . . .
}
}
它与构建导出和所有东西都完美无缺,但是,我最近注意到一个非常具体的情况,Unity有点奇怪。在Unity Editor(播放模式)中,如果我删除此脚本(或脚本附加到的游戏对象),然后撤消操作,则会导致两个AudioSource附加到复活的游戏对象。进一步来说;我的脚本先前使用删除操作+使用新Awake调用创建的操作销毁了一个。正如预期的那样,反复执行此操作会创建越来越多的泄露的组件。
使用不同的HideFlags禁用(?)序列化似乎没有任何好处,也没有尝试DestroyImmediate等来破坏组件。我的理解是Unity将手动创建的组件视为GameObject组件之一,因此注册destroy并撤消它以及撤消脚本删除。
有关如何绕过/避免Unity的这种奇怪行为的任何建议吗?
干杯!
答案 0 :(得分:1)
你自己回答了你的问题,@ anokta!
Awake()
方法创建一个AudioSource--即每次创建拥有的游戏对象时都会创建它。
现在,当您手动从层次结构视图中删除对象(例如,单击&gt;删除等),然后撤消它时,您正在调用一个纯粹的编辑器机制,即重新创建最后一次删除。这将基本上重新创建存在的对象(添加了AudioSource
的游戏对象)。而且因为现在这是一个已创建的新对象,它将自动立即再次执行其Awake()
方法。
我确定你已经知道这一点,并且可能正在寻找解决方法。在运行时手动删除编辑器中的对象是一个敏感的区域,并且可以使用它创建无穷无尽的怪异行为。
如果您真的想要限制它,那么在调用AddComponent<AudioSource>();
后立即在其他位置(在全局管理器中)设置标志怎么样?即。
void Awake() {
if (globalManager.AsCreated != true)
{
source = gameObject.AddComponent<AudioSource>();
source.hideFlags = HideFlags.HideAndDontSave;
globalManager.AsCreated = true;
}
}
其中globalManager
是...某种全球经理。这样,您可以在运行时删除对象(我仍然断言可能会导致无穷无尽的奇怪行为)并仍然可以撤消您想要的结果。
我希望有所帮助!