在Unity Editor中使用AddComponent脚本撤消GameObject的删除(播放模式)

时间:2016-01-26 15:37:00

标签: c# unity3d editor undo-redo

这是一个我一直在努力回答的非常具体的问题。我有一个简单的脚本,可以在运行时唤醒/销毁期间创建/销毁组件:

// 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的这种奇怪行为的任何建议吗?

干杯!

1 个答案:

答案 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是...某种全球经理。这样,您可以在运行时删除对象(我仍然断言可能会导致无穷无尽的奇怪行为)并仍然可以撤消您想要的结果。 我希望有所帮助!