Entity Visualizer OnDrawGizmos

Just a quick question. Im a huge fan on data visualizing in the viewport eg. Debug.DrawLine and OnDrawGizmos to see my data. Is it ok for debugging reasons to get entities into a MonoBehaviour and draw them in OnDrawGizmos, or is there a better way? How would I get entities into an old school MonoBehaviour ? Thanks in advance

                entityManager = World.Active.EntityManager;
                entities = entityManager.GetAllEntities(Allocator.Temp);
...............................


                for (int 0 = 1; i < entities.Length; i++)
                {
                   VertexComponent v = entityManager.GetComponentData<VertexComponent>(entities[i]);
                    Vector3 p = new Vector3(v.position.x, v.position.y, v.position.z);
                    Gizmos.DrawSphere(p, 0.5f);
                }

Got a feeling im gonna take some heat on this

Create a system with function to draw gizmos or add function to the existing system, then call this function from MonoBehaviour.

System

    using Unity.Entities;
    using Unity.Transforms;
    using UnityEngine;

    public class GizmoSystem : ComponentSystem
    {
        EntityQuery query;

        protected override void OnCreateManager()
        {
            query = GetEntityQuery(ComponentType.ReadOnly<Station>(), ComponentType.ReadOnly<Translation>());
        }

        protected override void OnUpdate()
        {
        }

        public void OnDrawGizmos()
        {
            Entities.With(query).ForEach((ref Translation translation) => {
                Gizmos.DrawSphere(translation.Value, 0.5f);
            });
        }
    }

MonoBehaviour

    using Unity.Entities;
    using UnityEngine;

    public class Gizmo : MonoBehaviour
    {
        GizmoSystem system;

        private void Start()
        {
            system = World.Active.GetExistingSystem<GizmoSystem>();
        }

        private void OnDrawGizmos()
        {
            if (system != null)
            {
                system.OnDrawGizmos();
            }
        }
    }
2 Likes

Thank you very much, way cleaner and smarter that the Frankenstein visualizer I was building

There’s another way which you might find nicer, although it’s a little bit of a hack and I’ve only done very minimal testing with it, so I don’t know how well it holds up.

Unity provides a DrawGizmo attribute which can be applied to a static method in any class to draw gizmos. We can use it like so.

static class GizmoInvoker
{
    private static float doneTime;

    [DrawGizmo(GizmoType.NonSelected)]
    private static void DrawSystemGizmos(MonoBehaviour obj, GizmoType gizmoType)
    {
        if (Time.time == doneTime) return;
        doneTime = Time.time;

        foreach (var world in Unity.Entities.World.AllWorlds)
        foreach (var system in world.Systems)
            if (system is IGizmoDrawing gizmoDrawingSystem) gizmoDrawingSystem.DrawGizmos();
    }
}

interface IGizmoDrawing
{
    void DrawGizmos();
}

This should find all active systems which have the IGizmoDrawing interface and call the method on each. The reason it’s a bit of a hack is that the attribute method is called once for each Monobehaviour in the scene. We can keep track of the time to make it run only once per frame, but if there are no Monobehaviours it won’t run.

If anyone from Unity’s reading this, it would be nice to allow the DrawGizmo attribute to be applied to a method with no parameters and to have it run once per frame.

1 Like

you can also do something like:

[DisableAutoCreation]
public class DrawGizmosGroup : ComponentSystemGroup {
DrawGizmoRunner runner
OnCreate() {
runner = new GameObject($"{World.Name} DrawGizmoRunner").AddComponent<DrawGizmoRunner>();
runner.system = this;
Object.DontDestroyOnLoad(runner.gameObject);
}

OnDestroy()  => Object.Destroy(runner.gameObject);
}

public class DrawGizmoRunner : MonoBehaviour {
internal DrawGizmosGroup system;
OnDrawGizmos() => system.Update();
}

then your gizmo systems will look like

[UpdateInGroup(typeof(DrawGizmosGroup))]
public class MyGizmos : ComponentSystem{...code in OnUpdate...}
3 Likes

I think I’ve seen advice given by Unity people saying that we should never put any code in a ComponentSystemGroup, but this does look like a nice way to do it.