ECS Gizmos Best Practice?

Hi all,

I’ve been using a cobbled-together system for Gizmos and have been wondering if this is the way to or if it could be improved.

The system which draws the gizmos when the editor is running (in the server world, but that’s not important):
ServerGizmoDrawSystem.cs

#if UNITY_EDITOR
public class ServerGizmoDrawSystem : SystemBase
{
    protected override void OnStartRunning()
    {
        // Connect system to handler.
        GizmoManager.OnDrawGizmos(drawGizmos);
    }

    private void drawGizmos()
    {

        Entities.
            WithName("GizmoDrawSystem_Dead").
            WithAll<Dead>().
            ForEach(
                    (in LocalToWorld ltw) => { Gizmos.DrawIcon(ltw.Position + new float3(0, 3, 0), "Dead"); }
                   ).
            Run();

        Entities.
            WithName("GizmoDrawSystem_Fire").
            ForEach(
                    (in LocalToWorld ltw, in Fire fire) =>
                    {
                        Gizmos.DrawSphere(ltw.Position, math.log(fire.fuel / 300 + 1));
                    }
                   ).
            Run();
     
        // More ForEach queries as needed ...
    }

    protected override void OnUpdate()
    {
        // Intentionally empty.
    }
}
#endif

And here is the GizmoManager where I hook into the GizmoSystemHandler:
GizmoManager.cs

#if UNITY_EDITOR
public static class GizmoManager
{
    public static void OnDrawGizmos(Action action)
    {
        Handler.DrawGizmos += action;
    }

    private static GizmoSystemHandler Handler => _handler != null ? _handler : (_handler = createHandler());
    private static GizmoSystemHandler _handler;

    private static GizmoSystemHandler createHandler()
    {
        var go = new GameObject("Gizmo Handler") { hideFlags = HideFlags.DontSave };

        return go.AddComponent<GizmoSystemHandler>();
    }

}
#endif

And the GizmoSystemHandler which reacts to OnDrawGizmos… calls:
GizmoSystemHandler.cs

#if (UNITY_EDITOR)
public class GizmoSystemHandler : MonoBehaviour
{
    public Action DrawGizmos;
    public Action DrawGizmosSelected;

    private void OnDrawGizmos()
    {
        if (EditorApplication.isPlaying)
        {
            DrawGizmos?.Invoke();
        }
    }

    private void OnDrawGizmosSelected()
    {
        if (EditorApplication.isPlaying)
        {
            DrawGizmosSelected?.Invoke();
        }
    }
}
#endif

Is this (roughly) the way to go or can it be improved? What are you using for gizmos at play time?

2 Likes

I haven’t done anything drastically different. All my systems inherit from a subclass of SystemBase with a couple of extra functions that can optionally be implemented such as DrawGizmos or OnGUI. These all get called from a monobehaviour.

It works and it’s simple.