GUILayout: Mismatched LayoutGroup.Repaint

Hi,

I have created a custom Editor Script. For some resason it causes the message “GUILayout: Mismatched LayoutGroup.Repaint” to be sprayed into the console.

My code is as follows:

using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Collections;

[CustomEditor(typeof(LootTable))]
public class LootTableEditor : Editor
{
    void Awake()
    {
        m_lootTable = target as LootTable;
    }

    public override void OnInspectorGUI()
    {
        EditorUtility.SetDirty(m_lootTable);

        serializedObject.Update();

        SortItems();

        float totalWeight = 0;
        foreach (LootTable.ItemData item in m_lootTable.m_items)
        {
            totalWeight += item.m_weight;
        }

        int itemNr = 0;
        foreach(LootTable.ItemData item in m_lootTable.m_items)
        {
            string itemName = (item.m_item == null) ? "" : item.m_item.name.Replace("_", " ").ToUpper();
            string itemNrString = (item.m_item != null && ++itemNr > 9) ? itemNr.ToString() : "0" + itemNr.ToString();
            double dropChance = Math.Round((item.m_weight / totalWeight) * 100, 1);
            string itemLabel = (item.m_item == null) ? ("[UNASSIGNED ITEM]") : ("#" + itemNrString + " - " + itemName + " (" + dropChance.ToString() + "%)");
            item.m_visible = EditorGUILayout.Foldout(item.m_visible, itemLabel);
         
            if (item.m_visible)
            {
                EditorGUILayout.BeginHorizontal();
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button("Remove Item", GUILayout.Width(100)))
                    {
                        int index = Array.IndexOf(m_lootTable.m_items, item);
                        m_lootTable.m_items = m_lootTable.m_items.Where((val, idx) => idx != index).ToArray();
                        break;
                    }
                EditorGUILayout.EndHorizontal();

                GUILayout.Space(5);
                GUILayout.Box("", new GUILayoutOption[] { GUILayout.ExpandWidth(true), GUILayout.Height(1) });
                GUILayout.Space(5);

                EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("Item");
                    item.m_item = EditorGUILayout.ObjectField(item.m_item, typeof(GameObject), true) as GameObject;
                EditorGUILayout.EndHorizontal();
             
                EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("Amount");
                    item.m_amount = (int)EditorGUILayout.Slider(item.m_amount, 0, 999);
                EditorGUILayout.EndHorizontal();

                item.m_weight = EditorGUILayout.FloatField("Weight", item.m_weight);
             
                EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("MP Only");
                    item.m_mp_only = GUILayout.Toggle(item.m_mp_only, "");
                EditorGUILayout.EndHorizontal();
            }
        }

        if (GUILayout.Button("Add Item"))
        {
            Array.Resize<LootTable.ItemData>(ref m_lootTable.m_items, m_lootTable.m_items.Length + 1);
            m_lootTable.m_items[m_lootTable.m_items.Length - 1] = new LootTable.ItemData();
        }

        if (GUILayout.Button("Clear"))
        {
            if(m_lootTable.m_items.Length > 0)
            {
                Array.Clear(m_lootTable.m_items, 0, m_lootTable.m_items.Length - 1);
                Array.Resize<LootTable.ItemData>(ref m_lootTable.m_items, 0);
            }
        }
    }

    void SortItems()
    {
        Array.Sort(m_lootTable.m_items, delegate(LootTable.ItemData item1, LootTable.ItemData item2) {
            if (item1.m_item == null)
                return item2.m_item == null ? 0 : 1;
            if (item2.m_item == null)
                return -1;
            return item1.m_item.name.CompareTo(item2.m_item.name);
        });
    }

    LootTable m_lootTable;
}

The error only appears if there are two items with the same name in the list and it can be fixed by not calling SortItems() which makes no sense to me.

Any suggestions?

Thanks in advance!

/Robin

Which line exactly throws this ? can you post the stack trace ?

ArgumentException: GUILayout: Mismatched LayoutGroup.Repaint
UnityEngine.GUILayoutUtility.BeginLayoutGroup (UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options, System.Type LayoutType) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/GUILayoutUtility.gen.cs:210)
UnityEditor.EditorGUILayout.BeginHorizontal (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/buildslave/unity/build/Editor/Mono/EditorGUI.cs:6414)
UnityEditor.EditorGUILayout.BeginHorizontal (UnityEngine.GUILayoutOption[] options) (at C:/buildslave/unity/build/Editor/Mono/EditorGUI.cs:6393)
LootTableEditor.OnInspectorGUI () (at Assets/Editor/LootTableEditor.cs:40)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor editor, Int32 editorIndex, Boolean forceDirty, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect, Boolean eyeDropperDirty) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1150)
UnityEditor.DockArea:OnGUI()

Seems to be EditorGUILayout.BeginHorizontal(); following if(item.m_visible), but that makes no more sense to me :slight_smile:

Also the error only occurs if I “open” the foldouts for one of the items that have the same name. If they are closed it works correctly.

All GUILayout classes (also EditorGUILayout) work in 2-phases:

In the first phase (layout), all GUI controls are laid-out (their positions are calculated) and Unity makes all the correct calculations of what the GUI is going to look like.

In a second phase (called “paint” or “repaint”, i can’t remember right now), all GUI controls are drawn to the screen.

If, for some reason, there are mismatches between those 2 phases (e.g: in the layout phase you “draw” 5 buttons, but in the repaint phase you try to draw more) you will get these kind of errors.

Does that make sense? I’ll have to dig a bit deeper to see what happens in your case (since your code is not super-short).

Does the problem still happen, or did you get it fixed?

1 Like

Thanks for your reply. What I don’t understand is how a simple sort of the array would cause something like this (especially when it ONLY occurs when two of the items have the same name). I’ve been unable to make the code work with the sorting so I’ve commented that out for now.

Edit:

Finally solved it by changing the sort function into this:

void SortItems()
{
     m_lootTable.m_items = m_lootTable.m_items.Where(x => x != null)
                                              .OrderBy(x => (x.m_item == null) ? "" : x.m_item.name)
                                              .ToArray();
}

I’ve got no idea why sorting using Linq works but the “regular” way does not however…