Using IDrawGizmos without a MonoBehaviour (ScriptableObjects, statics)

  • ALINE version: 1.7.8
  • Unity version: Unity 6.3
  • Render pipeline: Standard

TLDR

Passing an IDrawGizmos to the DrawingManager does not ever fire the gizmos if the object is a ScriptableObject or a POCO.

Why

Hi, after reading some threads here in the forum and elsewhere I was trying to do something more advanced with my ALINE project. Basically, I am aware that you can pass in a custom IDrawGizmos to the DrawingManager and it will register it as a source of gizmo drawing. I was very excited about doing this, but spent a decent amount of time trying to figure out why nothing was working.

I was porting over some old code where I was using the DrawGizmos attribute to draw my gizmos. It’s super handy because it means I can separate my gizmo drawing from the assembly that contains my runtime. Otherwise, if I have somebody use my really simple data container (let’s say it’s a spawn point or a way point), they have to take a dependency on ALINE in order to properly load the type if it inherits from MonoBehaviourGizmos.

I like my dependency chains clean so I was hoping there was a way to use the DrawGizmosAttribute like I’ve always done to have this clean separation only to find myself hitting the exception many have bemoaned (you can’t use the Draw.* in this context one).

Example

So after discovering that the DrawingManager can just take in any old IDrawGizmos, I made one myself:

[InitializeOnLoad]
internal static class MyStaticGizmoClass
{
	private static readonly MyCustomDrawer _drawer = new MyCustomDrawer();

	static MyStaticGizmoClass()
	{
		DrawingManager.Init();
		DrawingManager.Register(_drawer);
	}
	
	private sealed class MyCustomDrawer : IDrawGizmos
	{
		public void DrawGizmos()
		{
			Debug.Log("This will never be called because I am not a MonoBehaviour :(");
		}
	}
}

The Reason

The Gizmo Drawer actually gets properly registered, it goes into a group with a drawer, but when RemoveDestroyedGizmoDrawers runs, it has a direct cast to MonoBehaviour. As I am not a MonoBehaviour, that just gets skipped out, and the rest of the code just assumes all of them are MonoBehaviours.

Alternatives? What do I do?

All I want is two things:

  1. To Draw A Gizmo for an Object for whom I don’t want its asmdef take a dependency on ALINE (Drawing editor-time gizmos feels separate from data storage).
  2. To do this without adding a MonoBehaviour to the scene. I get that I could do this with a bunch of trickery – make a monoBehavior and set its hide flags accordingly forcing it to actually just be the hook that draws objects, but that’s incredibly disgusting. I just wanted a static-time IDrawGizmos, like the docs seemed to promise, but instead I found I was actually tied to MonoBehaviour, IDrawGizmos instead of being tied to just the callback.

Ideally I would prefer even more an alternative to the oft-ignored but very powerful DrawGizmosAttribute but ALINE seems very unhappy if I try using that attribute.

public class GizmoFreeBehaviour : MonoBehaviour {}

internal static class MyStaticClass
{
	[DrawGizmo(GizmoType.Selected | GizmoType.InSelectionHierarchy)]
	public static void ADrawingMethod(GizmoFreeBehaviour behaviour, GizmoType type)
	{
		// Ideally I would Use Aline here
		Gizmos.DrawWireCube(behaviour.transform.position, Vector3.one);
	}
}

What are the best courses of action here?