I'm trying something different for this post. BonaFide Prefab Painter is a Unity addon created by me, available for purchase in the Asset Store. I'm working on improving its usability by adding something Unity calls Handles and the plan is to go over how that is done at the same time.

Changes mentioned will be available in the (at time of writing) next version of the prefab painter, v2.5.4.


If you're not familiar with Bonafide prefab painter (doubt anyone is), it's a prefab painter tool I made for Unity for my current game project to quickly place hundreds of prefabs in a scene with a certain degree of control and help me build levels. The game is question is a top-top co-op action game, similiar to the Diablo series, so that's the kind of maps the Editor is created with in mind.

Quick example of what it can do:


The tool supports a few different brush types that will place prefabs in different ways, for example a circle, a square and a line.


The form of the brush is not shown

This is the issue I'm aiming at resolving today. Neither the size not the shape of brush is on display. Though not a requirement, adding this makes the editor easier to use and gives it a more professional look. UnityEditor.Handles supports a few different ways of drawing small gizmos with your editor and some of those will certainly fit.


The details of the current brush is placed in a

ToolsPlacementSettings
class. The handles only need care about the size and brush type.

public class ToolsPlacementSettings {
       public ToolsBrushType BrushType = ToolsBrushType.Single;
       public ToolsDistributionType DistributionType = ToolsDistributionType.Random;
       public float BrushSize = 1.0f;
       public float BrushSpacing = 1.0f;
       public ToolsSnappingType SnappingType = ToolsSnappingType.None;
       public float SnappingValue = 0f;
}


In the main Editor Window, DrawBrushHandlesis a method created for the purpose of drawing editor handles. The ToolsWindowPlacer object holds information about the current placement (preview objects, rotations, positions etc). The handles will only be interested in the

PlacementPosition,
and for lines the
StartDragPosition
.


private void DrawBrushHandles(ToolsWindowPlacer placer) {
  if (placer.PlacementSettings.BrushType == ToolsBrushType.Circle) {
    // TODO: Implement Circle brush
  } else if (placer.PlacementSettings.BrushType == ToolsBrushType.Line && placer.StartDragPosition.HasValue) {
    // TODO: Implement Line brush
  } else if (placer.PlacementSettings.BrushType == ToolsBrushType.Square) {
    // TODO: Implement Square brush
  }
}


Implementing the circle brush

The first brush, circle, is the easiest. We can look over Unity's documentation for Handles and see if we can find any method that fits.

https://docs.unity3d.com/ScriptReference/Handles.html

Handles.DrawSolidDisc() seems like a good candidate.


Handles.DrawSolidDisc(placer.PlacementPosition, Vector3.up, placer.PlacementSettings.BrushSize);



It's a good start but it's drawn over the objects we're trying to place. It needs to be transparent and would like better with a different color.

Handles.color
is a static variable that changes the color all handles are drawn with. Lets set it to a nice blue value with lots of transparency.


Handles.color = new Color(0f, 0.5f, 1f, 0.10f); 
Handles.DrawSolidDisc(placer.PlacementPosition, Vector3.up, placer.PlacementSettings.BrushSize);


Looking a letter better now.


Implementing the line brush

Next up is the line brush. Lucky for us there is a Handles.DrawLine() method we can use. It also needs a color set to look good. We're going for less alpha for this brush, as lines are thinner and harder to see.


Handles.color = new Color(0f, 0.5f, 1f, 0.5f);
Handles.DrawLine(placer.StartDragPosition.Value, placer.PlacementPosition);


The line is a bit hard to see, but the brush is easier to read in general so I don't think it will be an issue.


Implementing the square brush

There is no Handles.DrawSquare method. However, there is a DrawAAConvexPolygon method that can be used to draw a square. All we need to do is to create a list of vertices in the shape of a quad and we will have the shape we want. It will take a few more lines of code than the previous brushes but is still quite simple.


Handles.color = new Color(0f, 0.5f, 1f, 0.10f);
var center = placer.PlacementPosition;
var size = placer.PlacementSettings.BrushSize;
var corners = new Vector3[4];
corners[0] = center + new Vector3(-size, 0, -size);
corners[1] = center + new Vector3(size, 0, -size);
corners[2] = center + new Vector3(size, 0, size);
corners[3] = center + new Vector3(-size, 0, size);
Handles.DrawAAConvexPolygon(corners);



It looks like a square and covers the area of or brush.


Conclusion

Here we have a short demonstration of how Handles can be used in Unity editors to help out with visualization. The prefab painters will be a tiny bit easier to use and you can hopefully find your own uses for Handles.