Delegate.Combine:如何检查多播(可组合)委托中是否已有委托?
Delegate.Combine: How to Check if multicast (combinable) delegates already has a delegate inside of it?
我正在使用 Unity 3D,但是,该信息应该与解决此问题无关,因为核心问题是 System.Delegate(我想让你知道,因为我将链接到一些 Unity 文档澄清)。
我有一个自定义 window,它具有自定义更新功能 DirectorUpdate
。我需要这个函数来 运行 每个编辑器更新,不管 user/window 在做什么。
为了在每次编辑器更新时调用它,我将我的方法与委托结合起来 EditorApplication.update:
protected void OnEnable()
{
// If I do the below, base EditorApplication.update won't be called anymore.
// EditorApplication.update = this.DirectorUpdate;
// So I need to do this:
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
... // Other stuff
}
请注意,这是在 window 的 OnEnable 中完成的。
问题是在单个 运行 期间可以多次调用 OnEnable(例如,关闭 window 然后重新打开window 在单个编辑器会话期间)导致
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
被多次调用, 意味着我的更新方法 (this.DirectorUpdate)
每次更新最终都会被调用多次,这会导致一些严重的错误。
所以,问题是我如何检查EditorApplication.update
是否已经在其中“包含”了我的方法。 (在里面,我当然是说它已经 System.Delegate.Combine(d)
给代表了。)
我知道可能还有其他解决方案,例如将 EditorApplication.update 恢复到 window 关闭之前的状态,但这并不能解决所有情况(例如, OnEnable 也会在 window 刷新等期间被调用)并且错误将持续存在。 (此外,如果另一个 window 与 EditorApplication.update 连接,而此 window 处于打开状态怎么办?)因此,最好的解决方案是检查 EditorApplication.update 是否已经调用此方法在 Delegate.Combine-ing 之前。
我不熟悉 System.Delegate.Combine(d)
的作用,但您可以考虑用 window 代替 enabling/disabling,每次都销毁并实例化它,然后将您的代码移动到 Start
或 Awake
每次 window “激活”仅调用一次。
最后但同样重要的是,在 OnDisable
中使用一个强大的布尔值,这样您就可以在您的组件被禁用时处理联合执行。像这样:
bool omgIWasDisabled;
protected void OnEnable()
{
if (!omgIWasDisabled) {
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
}
... // Other stuff
}
void OnDisable() {
omgIWasDisabled = true;
}
希望这些都能解决。
我认为你走的路很复杂;)
订阅和取消订阅事件和委托就像使用运算符 +=
and -=
like
一样简单
protected void OnEnable()
{
// You can substract your callback even though it wasn't added so far
// This makes sure it is definitely only added once (for this instance)
EditorApplication.update -= DirectorUpdate;
// This basically internally does such a Combine for you
EditorApplication.update += DirectorUpdate;
... // Other stuff
}
private void OnDisable()
{
// Remove the callback once not needed anymore
EditorApplication.update -= DirectorUpdate;
}
这样你也可以打开这个 window 的多个实例,它们都将单独接收回调。
顺便说一句,如果这实际上是关于 EditorWindow
那么 afaik 你不应该使用 OnEnabled
但你宁愿使用 Awake
Called as the new window is opened.
和OnDestroy
.
我正在使用 Unity 3D,但是,该信息应该与解决此问题无关,因为核心问题是 System.Delegate(我想让你知道,因为我将链接到一些 Unity 文档澄清)。
我有一个自定义 window,它具有自定义更新功能 DirectorUpdate
。我需要这个函数来 运行 每个编辑器更新,不管 user/window 在做什么。
为了在每次编辑器更新时调用它,我将我的方法与委托结合起来 EditorApplication.update:
protected void OnEnable()
{
// If I do the below, base EditorApplication.update won't be called anymore.
// EditorApplication.update = this.DirectorUpdate;
// So I need to do this:
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
... // Other stuff
}
请注意,这是在 window 的 OnEnable 中完成的。
问题是在单个 运行 期间可以多次调用 OnEnable(例如,关闭 window 然后重新打开window 在单个编辑器会话期间)导致
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
被多次调用, 意味着我的更新方法 (this.DirectorUpdate)
每次更新最终都会被调用多次,这会导致一些严重的错误。
所以,问题是我如何检查EditorApplication.update
是否已经在其中“包含”了我的方法。 (在里面,我当然是说它已经 System.Delegate.Combine(d)
给代表了。)
我知道可能还有其他解决方案,例如将 EditorApplication.update 恢复到 window 关闭之前的状态,但这并不能解决所有情况(例如, OnEnable 也会在 window 刷新等期间被调用)并且错误将持续存在。 (此外,如果另一个 window 与 EditorApplication.update 连接,而此 window 处于打开状态怎么办?)因此,最好的解决方案是检查 EditorApplication.update 是否已经调用此方法在 Delegate.Combine-ing 之前。
我不熟悉 System.Delegate.Combine(d)
的作用,但您可以考虑用 window 代替 enabling/disabling,每次都销毁并实例化它,然后将您的代码移动到 Start
或 Awake
每次 window “激活”仅调用一次。
最后但同样重要的是,在 OnDisable
中使用一个强大的布尔值,这样您就可以在您的组件被禁用时处理联合执行。像这样:
bool omgIWasDisabled;
protected void OnEnable()
{
if (!omgIWasDisabled) {
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
}
... // Other stuff
}
void OnDisable() {
omgIWasDisabled = true;
}
希望这些都能解决。
我认为你走的路很复杂;)
订阅和取消订阅事件和委托就像使用运算符 +=
and -=
like
protected void OnEnable()
{
// You can substract your callback even though it wasn't added so far
// This makes sure it is definitely only added once (for this instance)
EditorApplication.update -= DirectorUpdate;
// This basically internally does such a Combine for you
EditorApplication.update += DirectorUpdate;
... // Other stuff
}
private void OnDisable()
{
// Remove the callback once not needed anymore
EditorApplication.update -= DirectorUpdate;
}
这样你也可以打开这个 window 的多个实例,它们都将单独接收回调。
顺便说一句,如果这实际上是关于 EditorWindow
那么 afaik 你不应该使用 OnEnabled
但你宁愿使用 Awake
Called as the new window is opened.
和OnDestroy
.