Short description: I wanna write a script and when I’m clicking onto a GameObject in the scene or the Hierarchy that has this script attatched it should instantly trigger this object’s Polygon Collider to go into edit mode without me pressing that button: --
Now I already built up the script’s structure so that it is [ExecuteInEditMode] but the Update portion only compiles for the Unity Editor and only runs when I’m not in playmode, the only thing I need to complete this nice little tool to help me design my game is a reference to this “Edit Collider” button.
Can I actually access the edit mode of a Polygon Collider 2D via some kind of script method or variable (like getComponent.toggleEditMode() or .setEditMode for example)?
And I know this is a very uncommon desire but let me explain myself first:
I’m using a collection of scripts from ViicEsquivel and pakfront that are taking the shape of a Polygon Collider 2D and convert it into a 2D Mesh, basically making the collider visible and renderable at runtime (the scripts can be found here How to fill polygon collider with a solid color? - Questions & Answers - Unity Discussions). This is so convenient that I decided to make nearly the entire static part (a.k.a. walls) of the world geometry for my 2D space game just by shaping Polygon Collider verticies and applying those scripts.
But needing to press the Edit Collider button everytime I want to shape a wall will most likely slow down my workflow by a lot which is why I want to write a script to do it for me. I just can’t find a way to pull this one off myself /:
I figured out how to do this with reflection against Unity 2018.2.21. Here’s some snippets from the code I used on my editor window tool. No guarantees it will work on different versions of Unity though.
I have taken the liberty to make it into a static class for easier use. I’ve also added some workarounds for cases in which UnityEditor might crash (still does sometimes, so use with care!). Hope others will find it useful.
#if UNITY_EDITOR
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace yourCoolNamespace
{
/// <summary>
/// Enables to start and stop editing a PolygonCollider2D via script.
/// Based on "infosekr"s code, see: https://discussions.unity.com/t/712436
///
/// Usage:
/// EditPolygonCollider2D.Start( aGameObjectWithAColliderOnIt );
/// EditPolygonCollider2D.Stop( aGameObjectWithAColliderOnIt );
///
/// Settings:
/// EditPolygonCollider2D.DisableColliderWhileEditing (bool, default true).
/// This was necessary because Unity tends to crash if edit is started via this
/// script but not ended via script. To avoid this we simpy disable editing on
/// the collider while we edit via script.
/// </summary>
[InitializeOnLoad]
public static class EditPolygonCollider2D
{
public static bool DisableColliderWhileEditing = true;
static object polygonUtility = null;
static MethodInfo polygonUtilityStartEditing = null;
static MethodInfo polygonUtilityStopEditing = null;
static MethodInfo polygonUtilityOnSceneGUI = null;
static bool onListenerActive = false;
static GameObject currentlyEditedObject;
static HideFlags currentlyEditedObjectHideFlags;
static EditPolygonCollider2D()
{
cacheTypeInfosIfNecessary();
}
static void cacheTypeInfosIfNecessary()
{
if (polygonUtility == null)
{
System.Type type = Assembly.Load("UnityEditor").GetType("UnityEditor.PolygonEditorUtility");
var ctors = type.GetConstructors();
polygonUtility = ctors[0].Invoke(new object[] { });
polygonUtilityStartEditing = type.GetMethod("StartEditing");
polygonUtilityStopEditing = type.GetMethod("StopEditing");
polygonUtilityOnSceneGUI = type.GetMethod("OnSceneGUI");
}
}
static void setListeners( bool active )
{
if (active)
{
if (onListenerActive == false)
{
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui += OnSceneGUI;
#else
SceneView.onSceneGUIDelegate += OnSceneGUI;
#endif
Selection.selectionChanged += OnSelectionChanged;
}
}
else
{
if (onListenerActive == true)
{
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui -= OnSceneGUI;
#else
SceneView.onSceneGUIDelegate -= OnSceneGUI;
#endif
Selection.selectionChanged -= OnSelectionChanged;
}
}
onListenerActive = active;
}
private static void OnSelectionChanged()
{
if(currentlyEditedObject != null && Selection.activeGameObject != currentlyEditedObject)
{
Stop(currentlyEditedObject.transform);
}
}
public static void Start(Component obj)
{
Start(obj.transform);
}
public static void Start(GameObject obj)
{
Start(obj.transform);
}
public static void Start(Transform trans)
{
Tools.current = Tool.None;
currentlyEditedObject = trans.gameObject;
cacheTypeInfosIfNecessary();
PolygonCollider2D collider = trans.GetComponent<PolygonCollider2D>();
if (collider != null)
{
polygonUtilityStartEditing.Invoke(polygonUtility, new object[] { collider });
setListeners(true);
}
if(DisableColliderWhileEditing)
{
currentlyEditedObjectHideFlags = collider.hideFlags;
collider.hideFlags = HideFlags.NotEditable;
}
}
public static void Stop(Component obj)
{
Stop(obj.transform);
}
public static void Stop(GameObject obj)
{
Stop(obj.transform);
}
public static void Stop(Transform trans)
{
currentlyEditedObject = null;
cacheTypeInfosIfNecessary();
PolygonCollider2D collider = trans.GetComponent<PolygonCollider2D>();
if (collider != null)
{
polygonUtilityStopEditing.Invoke(polygonUtility, new object[] {});
setListeners(false);
}
if (DisableColliderWhileEditing)
{
collider.hideFlags = currentlyEditedObjectHideFlags;
}
}
public static void OnSceneGUI(SceneView sceneView)
{
if (polygonUtilityOnSceneGUI != null)
{
polygonUtilityOnSceneGUI.Invoke(polygonUtility, new object[] { });
}
}
}
}
#endif