Currently the Unity’s EditorGUILayout.BeginScrollView() is terrible in Performance for Lists and Arrays to display a huge amount of Contents into a Scrollview, even though the Scrollview only sees a certain amount of Contents only, so i decided to make it only Render/Display the current Contents that are only visible, it works fine if you move the ScrollView’s Slider up and down, but if you hold the Up/Down buttons of the ScrollView, it will throw errors and warnings and some contents disappear for 1 frame and re-appear like normal, for that i made a small example script that you can test and see for your self:
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TestCode : MonoBehaviour
{
public List<int> myList = new List<int>();
public Vector2 myScrollView = Vector2.zero;
}
[CustomEditor(typeof(TestCode))]
public class TestCodeEditor : Editor
{
private TestCode testCode {get {return (TestCode)target;}}
public override void OnInspectorGUI ()
{
serializedObject.Update();
MyVoid();
if(GUI.changed)
{
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(testCode);
}
}
private void MyVoid ()
{
int startIndex = 0;
if(testCode.myList.Count >= 5)
{
testCode.myScrollView = EditorGUILayout.BeginScrollView(testCode.myScrollView,GUILayout.Height(117));
startIndex = (int)testCode.myScrollView.y / 30;
}
if(testCode.myList.Count > 0)for(int a = 0; a < testCode.myList.Count; a++)
{
//Checks if the current index isn't in the view
if(a < startIndex || a > startIndex + 4)GUILayout.Space(30);
//Checks if the current index is in the view
if(a >= startIndex && a <= startIndex + 4)
{
EditorGUILayout.BeginHorizontal("Box");
{
//The Index Of The Property
GUILayout.Box(a.ToString("000"));
//The Integer Property
EditorGUILayout.PropertyField(serializedObject.FindProperty("myList").GetArrayElementAtIndex(a),GUIContent.none,true);
//These Buttons Will Swap/Remove Items From The List
GUI.enabled = a != 0;
if(GUILayout.Button("▲",GUILayout.Width(20),GUILayout.Height(20)))
{
int current = testCode.myList[a];
int previous = testCode.myList[a - 1];
testCode.myList[a] = previous;
testCode.myList[a - 1] = current;
break;
}
if(GUI.enabled != (a != testCode.myList.Count - 1))
GUI.enabled = a != testCode.myList.Count - 1;
if(GUILayout.Button("▼",GUILayout.Width(20),GUILayout.Height(20)))
{
int current = testCode.myList[a];
int next = testCode.myList[a + 1];
testCode.myList[a] = next;
testCode.myList[a + 1] = current;
break;
}
if(!GUI.enabled)GUI.enabled = true;
if(GUILayout.Button("-",GUILayout.Width(20),GUILayout.Height(20)))
{
testCode.myList.RemoveAt(a);
break;
}
}
EditorGUILayout.EndHorizontal();
}
}
if(testCode.myList.Count >= 5)EditorGUILayout.EndScrollView();
EditorGUILayout.BeginHorizontal();
if(GUILayout.Button("Add 10"))
{
int count = testCode.myList.Count;
while(testCode.myList.Count < count + 10)
testCode.myList.Add(0);
}
if(GUILayout.Button("Add 100"))
{
int count = testCode.myList.Count;
while(testCode.myList.Count < count + 100)
testCode.myList.Add(0);
}
EditorGUILayout.EndHorizontal();
}
}
The console throws these messages:
ArgumentException: GUILayout: Mismatched LayoutGroup.Repaint
Unexpected top level layout group! Missing GUILayout.EndScrollView/EndVertical/EndHorizontal?
GUI Error: You are pushing more GUIClips than you are popping. Make sure they are balanced)
I know what the middle warning message talks about, but the Console itself is wrong, not me or my code!
However if you replace the StartIndex with a number from the script, none of these happen, but the ScrollView will display a range of Contents only, i replaced it with “1” like:
//Checks if the current index isn't in the view
if(a < 1 || a > 1 + 4)GUILayout.Space(30);
//Checks if the current index is in the view
if(a >= 1 && a <= 1 + 4)
So is there a solution to fix that?
Thanks.
[EDIT] The error points at the line that Begins Horizontal with the “Box” GUIStyle, removing everything but keeping the EditorGUILayout.PropertyField() it will work fine, so there is something wrong with the EditorGUILayout.BeginHorizontal("Box); line.