Hello,
i am working on a CustomInspector with UI Toolkit. I have an Inspector GameOptionsOverride_Inspector which derives from Editor. I want to generate a list GameOptionsEnabled every time a property on the inspector changes. The code below works fine, the list is created when the property overrideKeyboardOptionsListProperty changes. The Problem is Unity throws 2 errors every time that the TrackPropertyValue function is called
Assertion failed on expression: ‘IsInSyncWithParentSerializedObject()’
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
Assertion failed on expression: ‘IsInSyncWithParentSerializedObject()’
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
My Question is, is there something that im missing after changing the array of the property ? For example calling some function other than ApplyModifiedProperties that tells unity that i changed the serialized object and that it should inform other objects accordingly?
Thanks for reading i hope someone can help me out ^^
[CustomEditor(typeof(GameOptionsListOverride))]
public class GameOptionsOverride_Inspector : Editor
{
public VisualTreeAsset GameOptionsListOverride_Inspector_UXML;
public override VisualElement CreateInspectorGUI()
{
// Create a new VisualElement to be the root of our inspector UI
VisualElement myInspector = new VisualElement();
GameOptionsListOverride_Inspector_UXML.CloneTree(myInspector);
myInspector.TrackPropertyValue(serializedObject.FindProperty("overrideKeyboardOptionsListProperty"), CheckGameOptionsListChanged);
// Return the finished inspector UI
return myInspector;
}
void CheckGameOptionsListChanged(SerializedProperty serializedProperty)
{
if (serializedProperty.objectReferenceValue is not null)
{
GameOptionsListSO so = serializedProperty.objectReferenceValue as GameOptionsListSO;
SerializedProperty GameOptionsEnabled = serializedObject.FindProperty("GameOptionsEnabled");
if (GameOptionsEnabled.isArray)
{
//GameOptionsEnabled.Next(true); // skip generic field
//GameOptionsEnabled.Next(true); // advance to array size field
//// Get the array size
//int arrayLength = GameOptionsEnabled.intValue;
//GameOptionsEnabled.Next(true); // advance to first array index
// Write values to list
List<GameOptionEnabled> values = so.items.ConvertAll(i => ConvertSOToGameOptionEnabled(i)).ToList();
int lastIndex = values.Count - 1;
GameOptionsEnabled.ClearArray();
for (int i = 0; i <= lastIndex; i++)
{
//values.Add(GameOptionsEnabled.boxedValue as GameOptionEnabled); // copy the value to the list
//if (i < lastIndex) GameOptionsEnabled.Next(false); // advance without drilling
GameOptionsEnabled.InsertArrayElementAtIndex(i);
GameOptionsEnabled.GetArrayElementAtIndex(i).boxedValue = values[i];
}
serializedObject.ApplyModifiedProperties();
serializedObject.UpdateIfRequiredOrScript();
}
}
}
GameOptionEnabled ConvertSOToGameOptionEnabled(GameOptionSO gameOptionSO)
{
return new GameOptionEnabled(gameOptionSO);
}
[CreateAssetMenu(fileName = "GameOptionsListOverride", menuName = "ScriptableObjects/RuntimeSet/GameOptionsListOverride", order = 1)]
public class GameOptionsListOverride : ScriptableObject
{
GameObject player;
public EnumSo savedGameOptionsEvent;
public GameOptionsListSO OverrideKeyboardOptionsListProperty
{
get
{
return overrideKeyboardOptionsListProperty;
}
set
{
overrideKeyboardOptionsListProperty = value;
GameOptionsEnabled = overrideKeyboardOptionsListProperty.items.ConvertAll(i => ConvertSOToGameOptionEnabled(i)).ToList();
}
}
[SerializeField]
private GameOptionsListSO overrideKeyboardOptionsListProperty;
public List<GameOptionEnabled> GameOptionsEnabled = new List<GameOptionEnabled>();
[NonSerialized]
private List<GameOption> runTimeGameOptions;
public List<GameOption> GetGameOptions()
{
if(runTimeGameOptions is null)
runTimeGameOptions = overrideKeyboardOptionsListProperty.items.ConvertAll(i => ConvertSOToGameOption(i)).ToList();
return ApplyOverrides(runTimeGameOptions);
}
public List<GameOption> ApplyOverrides(List<GameOption> options)
{
foreach(var ge in GameOptionsEnabled)
{
var option = options.Find(o => o.name == ge.name);
option.enabled = ge.enabled;
}
return options;
}
//void OnValidate()
//{
// if(overrideKeyboardOptionsListPropertyOld != overrideKeyboardOptionsListProperty && overrideKeyboardOptionsListProperty is not null)
// {
// GameOptionsEnabled = overrideKeyboardOptionsListProperty.items.ConvertAll(i => ConvertSOToGameOptionEnabled(i)).ToList();
// Debug.Log("Changed Override OldValue: " + overrideKeyboardOptionsListPropertyOld + "NewValue:" + overrideKeyboardOptionsListProperty);
// }
// overrideKeyboardOptionsListPropertyOld = overrideKeyboardOptionsListProperty;
//}
GameOption ConvertSOToGameOption(ScriptableObject gameOptionSO)
{
//uses pattern matching
switch(gameOptionSO)
{
case KeyboardOptionSO t1:
return new KeyboardOption(gameOptionSO as KeyboardOptionSO);
case GameSpecificOptionSO t3:
return new GameSpecificOption(gameOptionSO as GameSpecificOptionSO);
case MouseOptionSO t4:
return new MouseOption(gameOptionSO as MouseOptionSO);
default:
return new GameOption(gameOptionSO as GameOptionSO);
}
}
GameOptionEnabled ConvertSOToGameOptionEnabled(GameOptionSO gameOptionSO)
{
return new GameOptionEnabled(gameOptionSO);
}
public void InitGameOptions(GameObject player)
{
this.player = player;
foreach (var option in GetGameOptions())
{
option.Initialize(player);
}
}
public void ApplyKeyboardOptions(GameObject player)
{
this.player = player;
foreach (GameOption k in GetGameOptions())
{
k.ApplyOption();
}
if (savedGameOptionsEvent)
Manager.EmitBroadcastEvent(savedGameOptionsEvent, new TargetEvent()
{
origin = this
});
}
public void DisableOptions()
{
foreach (GameOption g in GetGameOptions())
{
g.UndoOption(player);
}
}
}