トーフメモ

主にゲーム制作

【Unity】ArgumentException: Getting control 1's position in a group with only 1 controls when doing repaint が出たときの対処法

f:id:tofgame:20190428235503j:plain
Unityでエディタ拡張を作っていた時の話。
以下のようなエラーが出ました。

ArgumentException: Getting control 1's position in a group with only 1 controls when doing repaint
Aborting

このエラーは「OnGUI()の仕組み」が大きくかかわっていそうです。
OnGUI()は
Layoutイベントと、Repaintイベント(もしくはKeyDownなどのイベント)がセットになって二回連続で呼び出されています。
LayoutイベントはLayoutの情報(ラベル等の位置、サイズ)などの計算が行われていそうです。
その後にRepaintイベントで描画をします。

しかし、OnGUI()の中で条件分岐があるとき少し変なことが起きます。

bool flag;
void OnGUI(){
    if(flag){
        EditorGUILayout.LabelField("test");
    }else{
        flag=true;
    }
}

これを動作させると、最初の呼び出し(Layoutイベント)では「EditorGUILayout.LabelField("test");」が実行されないので、このLabelFieldの情報などは計算されません。
この後LayoutイベントとセットでReprintイベントが実行されます。
flagがtrueになったことで、「EditorGUILayout.LabelField("test");」が実行されます。LabelFieldの情報が更新されていないのに!
これを回避するために、以下のようにしました。

bool flag;
bool changeRoutineFlag;

void OnGUI(){
    if(changeRoutineFlag){
        if(!(Event.current.type == EventType.Layout)){
            return;
        }

        changeRoutineFlag=false;
    }

    if(flag){
        EditorGUILayout.LabelField("test");
    }else{
        flag=true;
        changeRoutineFlag=true;
    }
}

フラグ操作後Layoutイベントが呼ばれるまでRepaintイベントを回避することでエラーにならないようにします。
これでLayoutに関する情報を更新してから描画できます。

参考にしました

docs.unity3d.com
https://forum.unity.com/threads/argumentexception-getting-control-0s-position-in-a-group-with-only-0-controls-when.135021/