- Home /
EnablePicking/DisablePicking without undo
I making an editor and I want to manage if the objects are pickable or not. So I'm using those lines when inserting an object:
if (selectable)
SceneVisibilityManager.instance.EnablePicking(gameObject, true);
else
SceneVisibilityManager.instance.DisablePicking(gameObject, true);
I profiled my application and I found out that only those 2 lines made this : I looked at the source code there
So I don't want to record this undo operation for performance issue and because you don't have to undo this operation anyway.
Answer by _geo__ · Oct 22, 2021 at 01:53 PM
You could use reflections to access the internal VisibilityState instance and call "SetGameObjectPickingDisabled" on it.
This is the code the SceneVisibilityManager uses (where it registers the UNDOs):
public void DisablePicking(GameObject gameObject, bool includeDescendants)
{
Undo.RecordObject(SceneVisibilityState.GetInstance(), "Disable Picking GameObject");
SceneVisibilityState.SetGameObjectPickingDisabled(gameObject, true, includeDescendants);
}
public void EnablePicking(GameObject gameObject, bool includeDescendants)
{
Undo.RecordObject(SceneVisibilityState.GetInstance(), "Enable Picking GameObject");
SceneVisibilityState.SetGameObjectPickingDisabled(gameObject, false, includeDescendants);
}
I recently posted some code on the forums which does Hide/Unhide without undos. Modifying it to call SetGameObjectPickingDisabled should be trivial.
#if UNITY_EDITOR
public static class VisibilityStateInternals
{
// Thanks SceneVis hidden APIs, *sigh*
#region reflection
// reflection cache (speeds up code execution)
private static Type[] _refEditorTypes;
private static Type _refSceneVisibilityStateType;
private static System.Reflection.MethodInfo _refSceneVisibilityState_GetInstanceMethod;
private static System.Reflection.MethodInfo _refSceneVisibilityState_SetGameObjectHiddenMethod;
private static System.Reflection.PropertyInfo _refSceneVisibilityState_VisibilityActiveProperty;
private static void buildReflectionCache()
{
try
{
if (_refEditorTypes != null)
return;
_refEditorTypes = typeof(Editor).Assembly.GetTypes();
if (_refEditorTypes != null && _refEditorTypes.Length > 0)
{
_refSceneVisibilityStateType = _refEditorTypes.FirstOrDefault(t => t.Name == "SceneVisibilityState");
if (_refSceneVisibilityStateType != null)
{
_refSceneVisibilityState_GetInstanceMethod = _refSceneVisibilityStateType.GetMethod(
"GetInstance",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
_refSceneVisibilityState_SetGameObjectHiddenMethod = _refSceneVisibilityStateType.GetMethod(
"SetGameObjectHidden",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
_refSceneVisibilityState_VisibilityActiveProperty = _refSceneVisibilityStateType.GetProperty("visibilityActive");
}
}
}
catch (Exception)
{
// fail silently
}
}
/// <summary>
/// Based on the info found here:
/// https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/SceneView/SceneVisibilityState.bindings.cs#L20
/// and here:
/// https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/SceneVisibilityManager.cs
/// </summary>
/// <returns></returns>
public static UnityEngine.Object GetSceneVisibilityStateViaReflection()
{
try
{
buildReflectionCache();
return (UnityEngine.Object) _refSceneVisibilityState_GetInstanceMethod.Invoke(null, new object[] { });
}
catch (Exception)
{
// fail silently
return null;
}
}
/// <summary>
/// Based on the info found here:
/// https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/SceneView/SceneVisibilityState.bindings.cs#L20
/// </summary>
/// <param name="gameObject"></param>
/// <param name="isHidden"></param>
/// <param name="includeChildren"></param>
/// <returns>True if the reflection code has executed without exceptions.</returns>
public static bool SetGameObjectHiddenNoUndoViaReflection(GameObject gameObject, bool isHidden, bool includeChildren)
{
try
{
buildReflectionCache();
var state = GetSceneVisibilityStateViaReflection();
if (state != null)
{
_refSceneVisibilityState_SetGameObjectHiddenMethod.Invoke(state, new object[] { gameObject, isHidden, includeChildren });
}
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// Return true is visiblity is active, otherwise false<br />
/// Notice: It will return false if reflection failed.
/// </summary>
/// <returns></returns>
public static bool IsVisibilityActiveViaReflection()
{
try
{
buildReflectionCache();
var state = GetSceneVisibilityStateViaReflection();
if (state != null)
{
return (bool)_refSceneVisibilityState_VisibilityActiveProperty.GetValue(state, null);
}
return false;
}
catch (Exception)
{
return false;
}
}
#endregion
}
#endif
Your answer
Follow this Question
Related Questions
How to execute MenuItem for multiple objects once. 5 Answers
Save Components setting for reuse 1 Answer
How do you run File->Build Settings... from code? 0 Answers
How does conrolID work with ShowObjectPicker? 1 Answer
Unity UI 4.6 - Programmatically adding events - EventTrigger.delegates is null 0 Answers