🤑 Indie game store🙌 Free games😂 Fun games😨 Horror games
👷 Game development🎨 Assets📚 Comics
🎉 Sales🎁 Bundles

Drawing Unity gizmos in builds

A topic by popcron created 3 days ago Views: 60
Viewing posts 1 to 1
(Edited 2 times)

In the Unity game engine, theres a useful thing that can help you debug your games, this is the Gizmo toggle.

First, an intro to how gizmos are drawn. Every MonoBehaviour has a magic OnDrawGizmos and OnDrawGIzmosSelected methods. The engine listens for these and executes them when a camera finishes drawing, this includes the hidden scene camera and any other camera. These methods are still compiled into the builds, which means that any code in it, will stay there, but will never be called.

Its a really nice feature when debugging in the editor, however they arent visible in builds. Which is why i made this thread, to explain how you can implement the GL class in unity to display the same gizmos, in builds.

Now to the GL class. This class provides a handy method that can emulate the OpenGL implementation of glVertex3(x, y, z). This method is used to specify a vertex of a shape, and pairing this with GL.Begin() and GL.End() methods tells OpenGL if its a new shape, or a continuous one. So how do you draw a line, in screen space? Well, you have to perform your GL code inside the OnPostRender code, which has to be attached to a camera.

using System.Collections.Generics;
using UnityEngine;
public class GizmoManager : MonoBehaviour
{
    public Material material;
    void OnPostRender()
    {
        material.SetPass(0); //optional, i have mine set to "Sprites-Default"
        //OnPostRender method
        GL.Begin(GL.LINES);
        GL.Color(Color.yellow);
        GL.Vertex(Vector2(0, 0));
        GL.Vertex(Vector2(100, 100));
        GL.End();
    }
}

Ok, you have a diagonal line drawing now, but the Gizmos class still exists, can I override it or hide it? Yes.

One way, is to create a new class called Gizmos, and create your own gizmo methods inside it. This can be placed in the same GizmoManager class file. The only caveat with this is that you have to implement all of the old methods yourself.

public class Gizmos
{
    public static void DrawLine(Vector3 a, Vector3 b, Color color)
    {
        //DrawLine method
    }
}

If you compile this, and try to call Gizmos.DrawLine(), it will default to your implementation of this class. If you want to specify the Gizmos you've been using before you have to explicitly specify the namespace it belongs to.

//DrawLine method
UnityEngine.Gizmos.color = color;
UnityEngine.Gizmos.DrawLine(a, b);

In fact, if you place this line in your own DrawLine implementation, you will be able to draw lines again. So moving on now, how do you call the OnPostRender class from the old one, so that your DrawLine methods draws a line?

A way to do this, is to add the two vectors two a list of lines in the GizmoManager class, and then in the OnPostRender method, for loop through this method and draw all of the lines. Then clear this list after for loop through all of the lines. Why? Because OnDrawGizmos runs before OnPostRender, so theoretically, every line asked to be draw, will be drawn.

So what do we do know to our code? We add a new structure type:

public struct GizmoLine
{
    public Vector3 a;
    public Vector3 b;
    public Color color;
    public GizmoLine(Vector3 a, Vector3 b, Color color)
    {
        this.a = a;
        this.b = b;
        this.color = color;
    }
}

Now that this is declared, you can create a list of this type in your GizmoManager, and now that you have a list, add to it when you call DrawLine in your Gizmos class.

NOTE: Make this list static, so you can access it from the Gizmos class.

//DrawLine method
GizmoManager.lines.Add(new GizmoLine(a, b, color));

Then in your OnPostRender method

//OnPostRender method
GL.Begin(GL.LINES);
for(int i = 0; i < lines.Count; i++)
{
    GL.Color(lines[i].color);
    GL.Vertex(lines[i].a);
    GL.Vertex(lines[i].b);
}
GL.End();
lines.Clear();

Now if you play your game, your Gizmos.DrawLine method should add a GL Line to the list, and have the OnPostRenderer will loop through all lines, and draw this line. Which means its visible in builds. However, the lines are still not visible when the gizmo toggled is turned off. This because the OnDrawGizmos method, only runs if the gizmo toggle is on. So the solution here is to call the Gizmos.DrawLine() method from the OnRenderObject() method on your game objects.

NOTE: The OnPostRender method doesnt run every frame in the editor, which means your gizmos wont be drawn when in edit mode, a workaround for this is to execute the real UnityEngine.Gizmos.DrawLine() method if the Application.isPlaying property is false.

You might also notice that the lines arent visible through other objects, you can fix this by setting the material to a shader that ignores the ztest.


For those in a "rush", heres the full .cs file, just drag and drop onto your Camera and you're good to go.

And here is an example of my 2D game Paintime