What needed fixing?
When using Unity’s built in Handles over Gizmos, you’ll notice some features missing.
One of these features is the ability to draw a solid cube/box. In fact, when it comes to drawing a cube they only give access to a DrawWireCube function.
private void SceneGUI(SceneView obj)
{
Handles.color = Color.yellow
Handles.DrawWireCube(Position, Size);
}

This is fine in most use cases, but I’m deciding to be a little selfish. I want solid colors.
Thankfully, Handles does have a Draw function we can use to achieve this.
Handles.DrawAAConvexPolygon(a, b, c, d);
This little code bit is what we will be using to display a set of vector points into quads which will make our box.
The Process
First, we want to define our 8 corners using a center and size-
void DrawSolidCube(Vector3 center, Vector3 size)
{
Vector3 half = size * 0.5f;
// 8 corners of the cube
Vector3[] verts = new Vector3[8]
{
center + new Vector3(-half.x, -half.y, -half.z),
center + new Vector3( half.x, -half.y, -half.z),
center + new Vector3( half.x, half.y, -half.z),
center + new Vector3(-half.x, half.y, -half.z),
center + new Vector3(-half.x, -half.y, half.z),
center + new Vector3( half.x, -half.y, half.z),
center + new Vector3( half.x, half.y, half.z),
center + new Vector3(-half.x, half.y, half.z),
};
}
Coordinates explanation:
- half is half the size of the cube in each direction (so you build it centered on
center). - Each vertex is offset along X, Y, Z from the center:
-half.xorhalf.xis left or right-half.yorhalf.yis down or up-half.zorhalf.zis back or forward
Each corner is basically one possible combination of ±X, ±Y, ±Z.
How this connects to the faces:
Each cube face is a rectangle (quad) made from 4 of these points.
For example:
- Back face uses verts 0 → 1 → 2 → 3.
- Front face uses verts 5 → 4 → 7 → 6.
- Left face uses verts 4 → 0 → 3 → 7.
- Right face uses verts 1 → 5 → 6 → 2.
- Top face uses verts 3 → 2 → 6 → 7.
- Bottom face uses verts 4 → 5 → 1 → 0.
In simpler terms:
You build a cube by picking four of the eight points for each flat side.
How do we fill in the faces?
We will make a new function that uses the pre-built Handles functions to build our faces using the above face points.
public static void DrawQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
{
Handles.DrawAAConvexPolygon(a, b, c, d);
}
What’s happening:
DrawQuadis just a helper function that takes four points (corners of one face of the cube).- It uses
Handles.DrawAAConvexPolygon, a Unity Editor function that draws a solid (filled) polygon between the points you give it.
So DrawQuad is simply saying:
“Hey Unity, please fill in a surface (polygon) between these four 3D points.”
Since Unity doesn’t give us a built in function to Draw our Cube, we can now use DrawQuad to make our cube.
void DrawSolidCube(Vector3 center, Vector3 size)
{
Vector3 half = size * 0.5f;
// 8 corners of the cube
Vector3[] verts = new Vector3[8]
{
center + new Vector3(-half.x, -half.y, -half.z),
center + new Vector3( half.x, -half.y, -half.z),
center + new Vector3( half.x, half.y, -half.z),
center + new Vector3(-half.x, half.y, -half.z),
center + new Vector3(-half.x, -half.y, half.z),
center + new Vector3( half.x, -half.y, half.z),
center + new Vector3( half.x, half.y, half.z),
center + new Vector3(-half.x, half.y, half.z),
};
// Define each face with 4 vertices
DrawQuad(verts[0], verts[1], verts[2], verts[3]); // Back
DrawQuad(verts[5], verts[4], verts[7], verts[6]); // Front
DrawQuad(verts[4], verts[0], verts[3], verts[7]); // Left
DrawQuad(verts[1], verts[5], verts[6], verts[2]); // Right
DrawQuad(verts[3], verts[2], verts[6], verts[7]); // Top
DrawQuad(verts[4], verts[5], verts[1], verts[0]); // Bottom
}
Please keep in mind:
- The order you send the points (
a, b, c, d) matters because it affects the direction of the face’s “normal” (which way it’s facing). - If the points are not in the right order (clockwise or counterclockwise), sometimes the polygon won’t render correctly or could be invisible from certain angles.
Let’s test it out
All we have to do now is switch our Handles code from earlier with-
private void SceneGUI(SceneView obj)
{
Handles.color = Color.yellow; DrawExtensions.DrawSolidCube(Position, Size);
}

As you can see above, we’re drawing our solid box now.
Honestly though, this thing not optimized yet. We can actually cache our verts to help relieve some of the burden. While we’re at it, I’m also going to give it a color property.
public static class DrawExtensions
{
static Vector3 cachedCenter;
static Vector3 cachedSize;
static Vector3[] cachedVerts = new Vector3[8];
public static void DrawSolidCube(Vector3 center, Vector3 size, Color color)
{
Handles.color = color;
Vector3 half = size * 0.5f;
if (center != cachedCenter || size != cachedSize)
{
cachedVerts[0] = center + new Vector3(-half.x, -half.y, -half.z);
cachedVerts[1] = center + new Vector3(half.x, -half.y, -half.z);
cachedVerts[2] = center + new Vector3(half.x, half.y, -half.z);
cachedVerts[3] = center + new Vector3(-half.x, half.y, -half.z);
cachedVerts[4] = center + new Vector3(-half.x, -half.y, half.z);
cachedVerts[5] = center + new Vector3(half.x, -half.y, half.z);
cachedVerts[6] = center + new Vector3(half.x, half.y, half.z);
cachedVerts[7] = center + new Vector3(-half.x, half.y, half.z);
cachedCenter = center;
cachedSize = size;
}
// Define each face with 4 vertices
DrawQuad(cachedVerts[0], cachedVerts[1], cachedVerts[2], cachedVerts[3]); // Back
DrawQuad(cachedVerts[5], cachedVerts[4], cachedVerts[7], cachedVerts[6]); // Front
DrawQuad(cachedVerts[4], cachedVerts[0], cachedVerts[3], cachedVerts[7]); // Left
DrawQuad(cachedVerts[1], cachedVerts[5], cachedVerts[6], cachedVerts[2]); // Right
DrawQuad(cachedVerts[3], cachedVerts[2], cachedVerts[6], cachedVerts[7]); // Top
DrawQuad(cachedVerts[4], cachedVerts[5], cachedVerts[1], cachedVerts[0]); // Bottom
}
public static void DrawQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
{
Handles.DrawAAConvexPolygon(a, b, c, d);
}
}
What’s the difference:
- We established “static Vector3[] cachedVerts = new Vector3[8];”
- We now check for size and center as well before recalculating
- We now set the color in the function instead of outside of it
Using the above, we stop trying to create a new set of verts every frame. Not only this, but we don’t change the already established verts unless the cachedSize or cashedCenter are different.
Now let’s just decide on a color-
private void SceneGUI(SceneView obj)
{
Color fadedYellow = Color.yellow;
fadedYellow.a = 0.3f; DrawExtensions.DrawSolidCube(Position, Size, fadedYellow);
}

In Conclusion
A lot of the time what Unity doesn’t provide us out of the box, we can end up providing ourselves.
