# Draw 2D Physics Shapes in Unity

A tutorial on drawing physics shapes with your cursor using Unity3D.

In this tutorial I will show you how to draw and manipulate basic 2D physics shapes with your cursor using Unity, such as rectangles, circles and triangles. No additional external dependencies are required (tested with 2017.2, but should also work with 5.x).

# Background

Back in 2008, I had loads of fun playing IncrediBots. For the uninitiated, the game is very similar to Phun (now Algodoo); the game involved drawing basic physics shapes, placing rotating/sliding joints on them, and controlling motor joints with keyboard input. The game featured several puzzles and a rating system for published contraptions.

Here’s a few examples of things that you could make:

So let’s do the same thing in Unity! Conveniently, Unity has excellent support for 2D physics, so implementing a basic prototype is fairly simple to do.

There are 4 parts to this post:

This tutorial will implement drawing rectangles, circles, and triangles.

# Drawing 2D Polygon Meshes

To draw a mesh programmatically, Unity requires an array of its vertices and triangles. Unity allows each vertex to be colored differently, so we will demonstrate this by feeding our mesh random colors. To display the mesh, we apply it to a GameObject’s `MeshFilter` component.

Below is a script that can be added to any empty object to draw the shape in the image above.

Specifying vertices is easy, as we can list them in an array of `Vector2`s. The `vertices2D` array defines an I-shape. A small complication is that Unity wants an array of `Vector3`s, so we need to convert them. `System.Array.ConvertAll` is handy for this.

To find the triangles in a 2D polygon’s list of points, we can use a triangulation algorithm. I copied the well-suited `Triangulator.cs` class specified in the Unity3D wiki and dropped it in the project. There’s nothing too fancy here; just give the object a list of points and it will give back the indices of each triangle.

The next step involves creating an array of colors, one for each vertex. Here they are initialized to random colors with `Random.ColorHSV()` using Linq syntax.

The last step is to create the mesh from the vertices, triangles, and color data and apply the mesh to a `MeshFilter` to draw it. Note that it is a good practice to call `mesh.RecalculateBounds()` and `mesh.RecalculateNormals()` to ensure the mesh behaves as it should.

If we attach the script to an empty `GameObject`, we should see an I-shaped polygon with lots of colors (see above). Check out commit 1 — draw simple polygon mesh to view the results in Unity.

# Specifying Points with the Cursor

To capture input from the mouse and create shapes, we will create a controller that handles this. Its job is to create new shapes if no shapes are being drawn, update shapes if they require additional input, and set shapes loose if they are complete. To keep things simple, a script will collect new vertices whenever the left mouse button is released (click + drag is left as an exercise to the reader).

Let’s start with rectangles. To draw one, we can specify its two opposite corner vertices with mouse input.

## Drawing Rectangles

To aid with simple operations on lists of vectors, we will create a `Util.cs` script defining a few handy operations.

Next, create an empty `Rectangle` prefab and attach a script called `DrawRectangle.cs`. The rectangle prefab is expected have a `MeshFilter` to draw its mesh (make sure to add a material to properly display the mesh), and `LineRenderer` to draw a rectangle outline.

`DrawRectangle.cs` defines two public functions:

1. `AddVertex(Vector2 vertex)` adds a new vertex to its internal list of two vertices and calls `UpdateShape`.
2. If two vertices have been added, `UpdateShape(Vector2 newVertex)` replaces its second vertex with a new one. The four corners are extrapolated from the two vertices to update the mesh and line renderer. The shape is automatically redrawn by Unity every time this function is called.

The third function, `RectangleMesh(Vector2 v0, Vector2 v1, Color fillColor)`, serves to generate the rectangle mesh similar to the I-shaped polygon in the previous section.

One thing to note is that the rectangle’s transform set at the midpoint (centroid) of the mesh. The mesh’s vertices are relative to this center point. This will make some future calculations nicer (e.g., attaching a box collider). Also note that the script exposes a public `FillColor`, which fills the generated mesh with the given color.

## Draw Algorithm

The basic algorithm for drawing a rectangle is as follows.

1. If the left mouse button is released and no rectangle is being updated, create a new rectangle with its two opposite corner vertices at the current mouse position. Indicate that the rectangle is being updated.
2. If a rectangle is being updated, update the rectangle’s last corner vertex to be at the current mouse position.
3. If the left mouse button is released and a rectangle is being updated, stop updating it.

Below we define new script called `DrawController.cs`. Its job is to collect mouse input and send mouse coordinates to the currently active rectangle `GameObject`. In essence, it specifies the draw algorithm above.

The property `CurrentShapeToDraw` holds the current rectangle, and `IsDrawingShape` is the condition that allows vertices to be added to the current shape.

Check out commit 2 — draw rectangle to view the results in Unity.

From what is implemented, adding physics to these rectangles is simple. First, attach a `Rigidbody2D` and a `BoxCollider2D` to the rectangle prefab. The biggest change is in the `DrawRectangle.cs` script:

1. Add a public `SimulatingPhysics` property that when set, simulates physics with the `Rigidbody2D`. Otherwise, the shape is set to static so that it stops moving and other shapes may still interact with it.
2. Update the `BoxCollider2D`’s bounding box after we update the mesh.

Lastly, the `DrawController.cs` script sets `CurrentShapeToDraw.SimulatingPhysics` when the current rectangle is complete and ready to be released.

And voila, we have physics! Just make sure to add a static platform to prevent rectangles from falling through the scene. Check out commit 3 — add rectangle physics to view the results in Unity.

# Drawing Multiple Shapes

By extension, drawing circles, triangles, and arbitrary polygons should be very similar to drawing rectangles: supply some vertices via mouse input, create and update meshes/colliders, and simulate finished shapes. The `DrawController`’s code would largely be unchanged: what we need are scripts defined for each shape on how their mesh and collider should be drawn.

But there’s a small catch: how do we keep track of all the different types of shapes? I opted to use inheritance as it is a tidy way of getting a handle on all shapes and update them by their public interface. First, we create an abstract class inheriting from `Monobehaviour` called `DrawShape.cs`, which looks like this:

As we want to manipulate the `GameObject` properties, we use an abstract class instead of an interface. There may be some code duplication between shapes, but this format enables shapes to be independent of each other in terms of implementation.

The `DrawRectangle.cs` script should then be updated to inherit from `DrawShape`, with some additional `override` keywords for the appropriate methods/properties.

As we will be drawing rectangles, circles, and triangles, we should update `DrawController.cs` with all prefabs that we will be using and expose them as public members for Unity, on for each shape type. To make shape selection easier, we will create an enum called `DrawMode` that maps a shape type to a prefab so that the requested shape type will be instantiated upon drawing a new shape. There will also be a handy dropdown in the Unity inspector to change between the shape we want to draw.

## Drawing Circles

Unity does not support creating circle meshes or drawing circles out of the box, so we will need to implement our own circle-drawing algorithm. Fortunately, it does not require a large amount of code. The basic idea is to approximate a circle by drawing a regular polygon with enough line segments to be indistinguishable from a circle. To keep this illusion, the number of segments need to increase as the circle’s perimeter increases.

Below is the script for `DrawCircle.cs`, which inherits from `DrawShape`. Most of the code is identical to `DrawRectangle.cs`. Here we use a `CircleCollider2D` instead of a `BoxCollider2D`. The biggest difference is in the `CircleMesh(Vector2 v0, Vector2 v1, Color fillColor)` method.

We can create a manually tuned a linear function called `numSegments` which increases proportionally to the radius. For each segment, we evenly space `Vector2` points around the circle using cosine and sine functions. Then the rest is just a repeat of what we have seen before in `DrawRectangle`.

Check out commit 4 — draw circle and add physics to view the results in Unity.

## Drawing Triangles

With triangles, just change the collider type to `PolygonCollider2D` and we are halfway there. We can create a triangle mesh directly from the list of vertices specified by the cursor.

Can you guess how to draw arbitrary concave polygons? Hint: redefine the condition for when the shape is finished. Check out commit 5 — draw triangle and add physics to view the results in Unity.

## Conclusion

Congratulations on making it this far! As a reward, here’s an easter egg: press the spacebar when your cursor is near some shapes.

I hope you enjoyed the tutorial and have a newfound appreciation for Unity’s simple physics interface. And if anyone wants to collaborate with me on creating a full featured game out of this, contact me.

Like my content? Check out my blog at https://hyperparticle.com.

A programmer and mathematician that enjoys solving puzzles, one piece at a time. https://hyperparticle.com

## More from Dan Kondratyuk

A programmer and mathematician that enjoys solving puzzles, one piece at a time. https://hyperparticle.com

## Configuring HAProxy With Ansible Roles on AWS

Get the Medium app