Is there any way to toggle specific gizmos from script? The context is I am working on an editor plugin where it would be useful to quick toggle a specific Gizmo on and off without the user having to access the built-in dropdown menu for Gizmos. Thanks.
Maybe this will help, seems to work, but still it would be nice to get a solution without reflection: https://answers.unity.com/questions/851470/how-to-hide-gizmos-by-script.html
Thanks calpolican, I'll give this a try. On first glance it seems like it just handles enabling/disabling all gizmos - I specifically want to toggle a single gizmo, but maybe I can modify it for my own purposes. Thanks again.
Ok, I haven't really worked with gizmos, and I'm not sure if this would work, but... I guess you're using the OnDrawGizmos() function for your cusotm gizmo, right? couldn't you just put a bool there before the Gizmo.DrawSphere() or whatever you have to draw the gizmo? Anyway, best of luck, and if you find an answer, please post it. Code (CSharp): public class gizmoTest : MonoBehaviour { public float explosionRadius = 5.0f; void OnDrawGizmos() { if (on){ //You put a bool here // Display the explosion radius Gizmos.color = new Color(1, 1, 0, 0.75F); Gizmos.DrawSphere(transform.position, explosionRadius); } } }
Thanks for the reply, unfortunately this wouldn't achieve the desired outcome. This would only effectively toggle the gizmos for a component if gizmos were already globablly enabled and the specific component gizmo was also enabled. Ideally, one would be able to just directly call 'OnDrawGizmos', however this throws a runtime exception since Gizmo methods can only be called inside the 'magic' OnDrawGizmos method, which must be invoked by the Unity Editor and only gets called when gizmos are globablly enabled. It's not a complete show stopper - one of my custom inspectors relies heavily upon a specific Gizmo being enabled, so for the purposes of improving user friendliness, it would be nice to have a shortcut button that selectively enables one specific Gizmo (if it isn't already enabled). Thanks for the help nonetheless. I'll probably come back to this problem at a later date.
I strongly advise against using if directives in OnDrawGizmos. I've worked on projects that had lots of gizmos, and even with them disabled thousands of objects needed to have it called, just to check the if condition. This is causing a snowball effect on editor performance the bigger the scene gets. Best idea would be to create an utility class that handles the gizmo toggling for your custom inspectors through the reflection.
Hey! have you found a solution ? i am looking a way to enable/disable CharacterJoint component gizmos without searching through gizmos panel or character rig. Fricking thing enables itself every time i restart the editor.
Nope, I ended up just relying upon the user remembering to enable gizmos, which is less than ideal...
I've reported this as a bug. It's ridiculous that Unity still hasn't created an API call for this "feature". (It's not a feature: it's a bug. UnityEditor will globally stop executing your OnDrawGizmos methods - which is *still not documented even in 2020* - and there's no API to detect that or fix it. You just waste hours or days debugging "why isn't this running on user X's machine?" only to discover it's that badly designed Gizmos button blocking all the method calls )
Here are two methods you can use to either switch a specific type gizmo in project or switch all of them. Tested on Unity 2019.3. Based on this answer: https://answers.unity.com/questions...-view.html?childToView=1651053#answer-1651053 Code (CSharp): public static void SwitchAllGizmos(bool value) { var annotation = Type.GetType("UnityEditor.Annotation, UnityEditor"); var classId = annotation.GetField("classID"); var scriptClass = annotation.GetField("scriptClass"); var annotationUtility = Type.GetType("UnityEditor.AnnotationUtility, UnityEditor"); var getAnnotations = annotationUtility.GetMethod("GetAnnotations", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var setGizmoEnabled = annotationUtility.GetMethod("SetGizmoEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var setIconEnabled = annotationUtility.GetMethod("SetIconEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var annotations = (Array)getAnnotations.Invoke(null, null); foreach (var a in annotations) { var classIdValue = (int)classId.GetValue(a); var scriptClassValue = (string)scriptClass.GetValue(a); setGizmoEnabled.Invoke(null, new object[] { classIdValue, scriptClassValue, value ? 1 : 0, false }); setIconEnabled.Invoke(null, new object[] { classIdValue, scriptClassValue, value ? 1 : 0 }); } } public static void SwitchGizmo<T>(bool value) { var typeName = typeof(T).Name; var annotation = Type.GetType("UnityEditor.Annotation, UnityEditor"); var classId = annotation.GetField("classID"); var scriptClass = annotation.GetField("scriptClass"); var annotationUtility = Type.GetType("UnityEditor.AnnotationUtility, UnityEditor"); var getAnnotations = annotationUtility.GetMethod("GetAnnotations", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var setGizmoEnabled = annotationUtility.GetMethod("SetGizmoEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var setIconEnabled = annotationUtility.GetMethod("SetIconEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var annotations = (Array)getAnnotations.Invoke(null, null); foreach (var a in annotations) { var scriptClassValue = (string)scriptClass.GetValue(a); if (scriptClassValue.Equals(typeName) == false) continue; var classIdValue = (int)classId.GetValue(a); setGizmoEnabled.Invoke(null, new object[] { classIdValue, scriptClassValue, value ? 1 : 0, false }); setIconEnabled.Invoke(null, new object[] { classIdValue, scriptClassValue, value ? 1 : 0 }); break; } }
Isn't that the same as the answer from 2 years ago, which (as already noted) doesn't work except in limited circumstances (and fails in most of the important ones)?
Maybe thats helpful? Code (CSharp): public static void SetSceneViewGizmos(bool gizmosOn) { #if UNITY_EDITOR UnityEditor.SceneView sv = UnityEditor.EditorWindow.GetWindow<UnityEditor.SceneView>(); sv.drawGizmos = gizmosOn; #endif } public static bool GetSceneViewGizmosEnabled() { #if UNITY_EDITOR UnityEditor.SceneView sv = UnityEditor.EditorWindow.GetWindow<UnityEditor.SceneView>(); return sv.drawGizmos; #else return false; #endif } I use it in some scripts to enable gizmos, then wait for gizmos to draw (and do other stuff )and disable it after they were drawn, inside the OnDrawGizmo Method, calling the same method. Also theres an Update delegate you can subscribe in the static EditorApplication class, and the "SceneView.duringSceneGui" can also be helpful, you can draw handles during this routine and it does not depend on the Gizmos Toggle. (and handles have way more functionality - you can click on them, drag them, draw text, dottet lines, meshes, define Z-Testing for them and so on)
Interesting approach. How do you know when to 'turn it off' when you have more than one class that's running OnDrawGizmos? OR ... is it enough that ANY of them turn it off (even the first one to execute) because the change doesn't take effect until next Editor-frame?
Useful tip - thanks! This works - but getting the window causes focus change by default. I found the solution to that (in 2019 LTS at least) is to specify no focus (the false param), Code (CSharp): SceneView sv = EditorWindow.GetWindow<SceneView>(null, false);
Jost compiled answers from above into one handy utility script. You need to place this script inside Editor folder as any other editor-only script. It also has a shortcut for toggling scene gizmos. By default it's Alt+G. You can change this through the code or using "Edit/Shortcuts..." menu. It works for me in Unity 2020.3.19f1 Code (CSharp): using UnityEditor; public static class SceneViewGizmosUtility { [MenuItem("Tools/Toogle Scene View Gizmos &g")] public static void ToggleSceneViewGizmos() { var currentValue = GetSceneViewGizmosEnabled(); SetSceneViewGizmos(!currentValue); } public static void SetSceneViewGizmos(bool gizmosOn) { #if UNITY_EDITOR UnityEditor.SceneView sv = UnityEditor.EditorWindow.GetWindow<UnityEditor.SceneView>(null, false); sv.drawGizmos = gizmosOn; #endif } public static bool GetSceneViewGizmosEnabled() { #if UNITY_EDITOR UnityEditor.SceneView sv = UnityEditor.EditorWindow.GetWindow<UnityEditor.SceneView>(null, false); return sv.drawGizmos; #else return false; #endif } }
Great! You posted another thing that definitely doesn't work (confirmed by Unity QA: they have no intention of fixing this), adding nothing to the thread. If you have an actual solution to the actual problem, post away. "I copy/pasted the existing code that doesn't work" isn't helpful.
It looks like the call to UnityEditor.EditorWindow.GetWindow<UnityEditor.SceneView>(); rellay bogs down the editor, so may only want to call once and store the result
And if the user chooses to reset their layout or close a scene view and open a new one, they're out of luck, I guess. While @a436t4ataf 's tone is a bit rough, I am inclined to agree. Hacking the Scene View's deep and undocumented internals is fraught with brittle design flaws and risks of breakage. Gizmos and Handles are drawn at very specific points in time in the editor's processing loop, so that they aren't overdrawn by the other objects in the scene. They have decided not to expose a UnityEditor API to do the toggle. They haven't even exposed the shortcut, so you can't do a generic EditorApplication.ExecuteMenuItem("ToggleGizmos"); and I suspect that's just the way they prefer it.
It is public API, I'm not doing any reflection. And instead of GetWindow<> you could use SceneView.lastActiveSceneView.