Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Depth sorted Gizmos in the Unity Editor
using System;
using System.Collections.Generic;
using UnityEngine;
public static class SortedGizmos
{
static List<ICommand> commands = new List<ICommand>(1000);
public static Color color { get; set; }
public static void BatchCommit()
{
#if UNITY_EDITOR
Camera cam = null;
var sv = UnityEditor.SceneView.currentDrawingSceneView;
if (sv != null && sv.camera != null)
{
cam = sv.camera;
}
else
{
cam = Camera.main;
}
if (cam != null)
{
var mat = cam.worldToCameraMatrix;
for (int i = 0; i < commands.Count; ++i)
{
commands[i].Transform(mat);
}
// sort by z
var a = commands.ToArray();
Array.Sort<ICommand>(a, compareCommands);
// draw
for (int i = 0; i < a.Length; ++i)
{
a[i].Draw();
}
}
#endif
commands.Clear();
}
public static void DrawSphere(Vector3 center, float radius)
{
commands.Add(new DrawSolidSphereCommand
{
color = color,
position = center,
radius = radius
});
}
public static void DrawWireSphere(Vector3 center, float radius)
{
commands.Add(new DrawWireSphereCommand
{
color = color,
position = center,
radius = radius
});
}
public static void DrawCube(Vector3 center, Vector3 size)
{
commands.Add(new DrawSolidCubeCommand
{
color = color,
position = center,
size = size
});
}
public static void DrawWireCube(Vector3 center, Vector3 size)
{
commands.Add(new DrawWireCubeCommand
{
color = color,
position = center,
size = size
});
}
static int compareCommands(ICommand a, ICommand b)
{
float diff = a.SortValue - b.SortValue;
if (diff < 0f) return -1;
else if (diff > 0f) return 1;
else return 0;
}
interface ICommand
{
void Transform(Matrix4x4 worldToCamera);
void Draw();
float SortValue { get; }
}
struct DrawSolidSphereCommand : ICommand
{
public Color color;
public Vector3 position;
public float radius;
private Vector3 transformedPosition;
public void Transform(Matrix4x4 mat)
{
transformedPosition = mat.MultiplyPoint(position);
}
public void Draw()
{
Gizmos.color = color;
Gizmos.DrawSphere(position, radius);
}
public float SortValue { get { return transformedPosition.z; } }
}
struct DrawWireSphereCommand : ICommand
{
public Color color;
public Vector3 position;
public float radius;
private Vector3 transformedPosition;
public void Transform(Matrix4x4 mat)
{
transformedPosition = mat.MultiplyPoint(position);
}
public void Draw()
{
Gizmos.color = color;
Gizmos.DrawWireSphere(position, radius);
}
public float SortValue { get { return transformedPosition.z; } }
}
struct DrawSolidCubeCommand : ICommand
{
public Color color;
public Vector3 position;
public Vector3 size;
private Vector3 transformedPosition;
public void Transform(Matrix4x4 mat)
{
transformedPosition = mat.MultiplyPoint(position);
}
public void Draw()
{
Gizmos.color = color;
Gizmos.DrawCube(position, size);
}
public float SortValue { get { return transformedPosition.z; } }
}
struct DrawWireCubeCommand : ICommand
{
public Color color;
public Vector3 position;
public Vector3 size;
private Vector3 transformedPosition;
public void Transform(Matrix4x4 mat)
{
transformedPosition = mat.MultiplyPoint(position);
}
public void Draw()
{
Gizmos.color = color;
Gizmos.DrawWireCube(position, size);
}
public float SortValue { get { return transformedPosition.z; } }
}
struct DrawSolidMeshCommand : ICommand
{
public Color color;
public Vector3 position;
public Vector3 scale;
public Quaternion rotation;
public Mesh mesh;
private Vector3 transformedPosition;
public void Transform(Matrix4x4 mat)
{
transformedPosition = mat.MultiplyPoint(position);
}
public void Draw()
{
Gizmos.color = color;
Gizmos.DrawMesh(mesh, position, rotation, scale);
}
public float SortValue { get { return transformedPosition.z; } }
}
struct DrawWireMeshCommand : ICommand
{
public Color color;
public Vector3 position;
public Vector3 scale;
public Quaternion rotation;
public Mesh mesh;
private Vector3 transformedPosition;
public void Transform(Matrix4x4 mat)
{
transformedPosition = mat.MultiplyPoint(position);
}
public void Draw()
{
Gizmos.color = color;
Gizmos.DrawWireMesh(mesh, position, rotation, scale);
}
public float SortValue { get { return transformedPosition.z; } }
}
}
@MateoPeri

This comment has been minimized.

Copy link

@MateoPeri MateoPeri commented Aug 10, 2020

How does this work? Does it need to be in an Editor folder?

@bugshake

This comment has been minimized.

Copy link
Owner Author

@bugshake bugshake commented Aug 10, 2020

It can be anywhere in your project.

To use it you can call the various draw functions like SortedGizmos.DrawSphere from various scripts at various times. (All this does is add a struct to a list)

Then, once per frame, from within a DrawGizmos body you call SortedGizmos.BatchCommit, for example:

void OnDrawGizmos()
{
    SortedGizmos.DrawSphere( Vector3.zero, 1.5f );
    SortedGizmos.DrawSphere( Vector3.right, 1.5f );
    SortedGizmos.BatchCommit();
}

This will draw the gizmos with proper depth sorting and clear the list.

Note that this code will not be optimized out when you build your project.

@MateoPeri

This comment has been minimized.

Copy link

@MateoPeri MateoPeri commented Aug 10, 2020

I tried drawing some gizmos and then placing a regular sprite in the scene, but the gizmos are always rendered on top on the sprite.
Doesn't matter how much I change the Z-position of the sprite, it is always drawn under the gizmos.

With regular (3D) cubes this doesn't happen.

Why could that be?

@MateoPeri

This comment has been minimized.

Copy link

@MateoPeri MateoPeri commented Aug 10, 2020

Sprite (left) and cube (right)
image

Both are placed on top of the gizmos, but only the cube is rendered correctly.
image2

@bugshake

This comment has been minimized.

Copy link
Owner Author

@bugshake bugshake commented Aug 11, 2020

Ah, this script cannot help you there.

Gizmos completely ignore the depthbuffer. My script will sort them, so the gizmos themselves look normally in 3D (allthough will not intersect).

If you want gizmo's and normal scene to intersect using the depth buffer, you need to use open GL direct mode drawing in the render method, see https://docs.unity3d.com/ScriptReference/GL.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.