URP or HDRP is used as active pipeline. No issue with BIRP.
Material is selected from assets in isolation, not on game-object. Doesn’t happen in Properties window. Custom ShaderGUI doesn’t affect this.
How to reproduce:
Select any Material in Assets
Change any property
Save project
Inspector stops responding to clicks
??? Now you have to re-select material
As I constantly press Ctrl + S, you may imagine how unbearable it becomes.
Some other very strange behavior:
If you undo changes and save again, it starts working again (and ofc breaks on next save).
If you do all these steps when changing material on game-object, and then select this material in assets - the issue will be gone only for that particular material. (???) Issue will be back after Editor restart.
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using System.Reflection;
public class MaterialInspectorSaveFix : AssetModificationProcessor // is there a better callback method for OnSave?
{
struct InspectorWindowData
{
public EditorWindow window;
public Dictionary<int, float> editorsHeight;
static MethodInfo OnSelectionChangedMethod;
public VisualElement QueryEditorsList()
{
return window.rootVisualElement.Query(className: "unity-inspector-editors-list").First();
}
public void InvokeOnSelectionChanged()
{
if (OnSelectionChangedMethod == null)
OnSelectionChangedMethod = window.GetType().GetMethod("OnSelectionChanged", BindingFlags.NonPublic | BindingFlags.Instance);
OnSelectionChangedMethod.Invoke(window, null);
}
}
static MethodInfo LayoutSetMethod;
static void SetLayoutProperty(VisualElement element, Rect rect)
{
if (LayoutSetMethod == null)
LayoutSetMethod = typeof(VisualElement).GetProperty("layout", BindingFlags.Public | BindingFlags.Instance).GetSetMethod(true);
LayoutSetMethod.Invoke(element, new object[] { rect });
}
static string[] OnWillSaveAssets (string[] paths)
{
var selection = Selection.objects;
bool hasAnyMaterialSelected = false;
foreach (var obj in selection)
{
if (obj is Material)
{
hasAnyMaterialSelected = true;
break;
}
}
if (!hasAnyMaterialSelected)
return paths;
var allWindows = Resources.FindObjectsOfTypeAll(typeof(EditorWindow));
var inspectorWindows = new List<InspectorWindowData>(1);
foreach (EditorWindow window in allWindows)
{
var type = window.GetType();
if (type.FullName == "UnityEditor.InspectorWindow")
{
var data = new InspectorWindowData() { window = window, editorsHeight = new Dictionary<int, float>() };
foreach (var editor in data.QueryEditorsList().Children())
{
data.editorsHeight.Add(editor.GetHashCode(), editor.layout.height);
}
inspectorWindows.Add(data);
}
}
// We DO NOT want to mess with Selection, as it'll register garbage Undo.
//Selection.objects = null;
//foreach (var inspector in inspectorWindows)
// inspector.InvokeOnSelectionChanged();
//Selection.objects = selection;
foreach (var inspector in inspectorWindows)
{
inspector.InvokeOnSelectionChanged();
foreach (var editor in inspector.QueryEditorsList().Children())
{
var layout = editor.layout;
if (inspector.editorsHeight.TryGetValue(editor.GetHashCode(), out var height))
{
// dunno where EditorElement sets the layout, so we'll do it manually
layout.height = height;
SetLayoutProperty(editor, layout);
}
}
}
return paths;
}
}
#endif
Let me know if it works on your version or if there any issues with it!
While writing this fix, I’ve found the cause of this issue.
If you look in UITK Debugger, the Material EditorElement is not re-initialized properly - height is 65, thus you can only click on it’s header. It’s not the case with Properties window, only the Inspector.
Before save:
After save:
There’s also another small issue - preview pane (at the bottom) doesn’t remember on save that it was completely hidden, only when height is above zero, so it keeps resetting itself when trying to hide it.