C# 在EditorWindow OnGUI方法内平衡调用会导致问题

C# 在EditorWindow OnGUI方法内平衡调用会导致问题,c#,user-interface,unity3d,balance,C#,User Interface,Unity3d,Balance,我正在制作一个系统来平衡EditorWindow的OnGUI方法内部的调用。 我正在做以下工作: public void Update() { 重新油漆(); } 在我的OnGUI方法中,我称之为平衡器。我有一个回调列表(list)。 所以这个想法很简单,一些callvaxc 对于具有完整GUI的回调,我将跳过一些重绘帧,并为其他回调调用每个重绘帧(例如,选框标签或显示GIF) 由于某种原因,此错误会发生“在执行重新绘制时获取控件0在只有0个控件的组中的位置” private int m_re

我正在制作一个系统来平衡EditorWindow的OnGUI方法内部的调用。 我正在做以下工作:

public void Update()
{
重新油漆();
}
在我的OnGUI方法中,我称之为平衡器。我有一个回调列表(list)。 所以这个想法很简单,一些callvaxc 对于具有完整GUI的回调,我将跳过一些重绘帧,并为其他回调调用每个重绘帧(例如,选框标签或显示GIF)

由于某种原因,此错误会发生“在执行重新绘制时获取控件0在只有0个控件的组中的位置”

private int m_repaincounter;
公众抽签()
{
事件e=当前事件;
尝试
{
foreach(m_动作中的var动作)
{
尝试
{
//测试1
//MainAction是从Action继承的类(类MainAction:Action)
如果(操作是主操作)
{
bool isDesignedType=e.rawType==EventType.Repaint | | e.rawType==EventType.Layout;
if(isDesignedType)
++m_重新绘制计数器;
如果(!(m_重新绘制计数器==20&&isDesignedType))
持续
其他的
m_重新绘制计数器=0;
}
//测试2
action.Value();
}
捕获(例外情况除外)
{
LogException(ex);
}
}
}
接住
{
//由于重新编译,集合将被修改,因此我们需要避免异常
}
}
但是如果我评论一下“测试1”,一切都很好

在类的
ctor
上,我们需要指定对GUI方法的回调,例如:

公共平衡器(Action drawAction)
{
m_actions=新列表();
m_actions.Add(drawAction);
}
因此,我们可以轻松地(在
编辑器窗口中
)执行以下操作:

专用均衡器m_均衡器;
public void OnEnable()
{
m_平衡器=新平衡器(牵引);
}
公众抽签()
{
//按照if语句的规定,每20次重新绘制一次该块
GUILayout.BeginHorizontal(“盒子”);
{
按钮(“我是第一个按钮”);
按钮(“我在右边”);
//每次重新喷漆时都会调用此选框
m_balancer.AddAction(()=>CustomClass.DisplayMarquee(“示例”);
}
GUILayout.EndHorizontal();
}
//在我们拥有的平衡器类中
//我们使用System.Linq.Expressions来标识已经添加的操作
私有HashSet m_alreadyAddedActions=新HashSet();
公共void AddAction(表达式回调)
{
如果(!m_alreadyAddedActions.Add(callback.ToString()))
回来
m_actions.Add(callback.Compile());
}
我想不出来。我在网上找不到任何信息。有人能帮我吗?

好的,那么,
OnGui
(IMGui)很难使用。如果不将其用于编辑器脚本,请改用新的4.6 UI(UGui)。 那么现在。这个问题

至少调用了OnGui。其中一个是计算布局,另一个是实际绘制东西(“重新绘制”)

如果在这两个调用之间事物的数量、大小或任何其他内容发生变化,那么Unity将出现错误,即“在执行重新绘制时,获取控件0在只有0个控件的组中的位置。”

也就是说:您不能在之后和之前的任何时候更改IMGui系统中的UI状态


仅,仅,
Event.current==EventType.Repaint期间更改状态(从而更改正在绘制的对象)。仅,仅,更改下一帧的状态(或者,在
Event.current==EventType.Layout
期间进行更改,前提是此相同的新状态将在重新绘制期间产生相同的代码路径)。在任何情况下,都不要在重新绘制过程中进行上一次布局中没有的更改。

我以前读过这篇文章。我知道这是为什么造成的……问题比更改“事物的数量、大小或任何其他内容”更糟糕,因为我没有这样做……如果我对“测试1”进行评论,问题就很清楚了块,所以只调用了“action.Value();”,一切正常…所以我不知道这里到底发生了什么。
continue;
导致
action.Value()
未被调用。这取决于
m_repaintCounter
isDesignedType
。假设计数器为0,我们为布局调用一次。
isDesignedType
为true,它递增
m_repaintCounter
。当
m_repaintCounter!=20
时,调用
continue
。这将成对重复(可能性是布局,偶数是重新绘制)。因此当
m_repaitcounter
增加到19(布局)时,调用
continue
。当
m_repaitcounter
增加到20(以下重新绘制)时,不调用
continue
。当
action.Value()
在第20次迭代中被调用,它调用了一个函数
Draw()
,该函数调用
GuiLayout
向GUI添加一些内容。这些内容在上一次布局(第19次迭代)中不存在:现在出现了一个问题。您的状态取决于在布局和重新绘制之间更改的值。现在我明白了