- Home /
Find instance of EditorWindow without creating new one?
Hey everybody!
I need to Repaint a specific custom EditorWindow, triggered by changes in a custom inspector. For this I need to find any existing instance of this window.
EditorWindow.FindObjectOfType() does not give me any results at all here...
My current workaround is to create a static pseudo singleton reference to the last EditorWindow, but this is lost once Unity is restarted and not a very elegant way.
Answer by Bunny83 · Feb 22, 2013 at 09:20 AM
GetWindow actually does what you want. It ensures that only one instance is open. When you call GetWindow and the window is already created it reuses the existing window. So just use GetWindow() whenever you need to open the window.
If you want a singleton-like property, just do:
public static MyEditorWindow Instance
{
get { return GetWindow< MyEditorWindow >(); }
}
If you really just want to find all instances that are open use Resources.FindObjectsOfTypeAll. As mentioned in the docs, be careful since this function can return also internal stuff like the SceneView camera, ...
edit
I've finally made a base class for MonoBehaviour singletons a couple of days ago. I just made another one for EditorWindow ;)
// Runtime Extension class
public class MonoBehaviourSingleton< TSelfType > : MonoBehaviour where TSelfType : MonoBehaviour
{
private static TSelfType m_Instance = null;
public static TSelfType Instance
{
get
{
if (m_Instance == null)
{
m_Instance = (TSelfType)FindObjectOfType(typeof(TSelfType));
if (m_Instance == null)
m_Instance = (new GameObject(typeof(TSelfType).Name)).AddComponent<TSelfType>();
DontDestroyOnLoad(m_Instance.gameObject);
}
return m_Instance;
}
}
}
//Editor Extension class
public class EditorWindowSingleton< TSelfType > : EditorWindow where TSelfType : EditorWindow
{
private static TSelfType m_Instance = null;
public static TSelfType FindFirstInstance()
{
var windows = (TSelfType[])Resources.FindObjectsOfTypeAll(typeof(TSelfType));
if (windows.Length == 0)
return null;
return windows[0];
}
public static TSelfType Instance
{
get
{
if (m_Instance == null)
{
m_Instance = FindFirstInstance();
if (m_Instance == null)
m_Instance = GetWindow<TSelfType>();
}
return m_Instance;
}
}
}
Just derive your class from the singleton base class and your ready to go. You have to pass the type itself as generic parameter. Something like that:
public class MyEditorWindow : EditorWindowSingleton< MyEditorWindow >
{
//[...]
}
Thanks a lot! Resources.FindObjectsOfTypeAll() did the trick...
Great little script to pop in projects if you're wanting singleton editor windows. Thanks for sharing.
Sorry to revive an old post, but just my small two cents. In order for this to work when using Build and Run, make sure to surround EditorWindowSingleton class between
#if UNITY_EDITOR
//your EditorWindowSingleton class here
#endif
Otherwise you will get compilation errors about the namespace name 'UnityEditor' not being found. And it does make sense, since the editor library is not included when you export and run the game.
"Sorry to revive an old post"
Don't $$anonymous$$d it. It's always good to see a fellow sufferer, err, developer.
Answer by numberkruncher · Feb 21, 2013 at 06:48 PM
using UnityEngine;
using UnityEditor;
public class MyEditorWindow : EditorWindow {
#region Window Management
private static MyEditorWindow _instance;
// And use the property like @Bunny83 suggested
public static MyEditorWindow Instance {
get { return GetWindow<MyEditorWindow>(); }
}
public static void RepaintWindow() {
if (_instance != null)
_instance.Repaint();
}
#endregion
void OnEnable() {
_instance = this;
}
}
Warning, I haven't tested the above code, but you should get the idea :-)
Thank! But that's basically what I ment with "create a static pseudo singleton reference to the last EditorWindow". It works fine, but when reloading the script or restarting Unity while keeping the EditorWindow open, will break this reference.
Another option is to initialize the static instance variable using the OnEnable
message. I will update the above...
Good solution. Works for me. Don't forget to set _instance
back to null
in OnDisable()
though.