3D Bezier Curves in Unity

In game, showing 4 tracers being rendered
In game, showing 4 tracers being rendered from the player to the enemy

One of the effects I wanted for Cipher Break was some sort of tracer effect to show when the player had successfully ‘hit’ an enemy by typing the right character.

I could just draw a straight line from the player to the enemy, like a tracer round in the real world, but that wouldn’t be very interesting, and it doesn’t really play into the whole “you’re in a computer” aesthetic. I thought it’d be much more interesting to use Bezier Curves to draw the tracer fire.

Bezier curve“. Licensed under Public domain via Wikimedia Commons.

Bezier curves are mathematically interpolated lines, they have a start and end point, and then x number of control points in between that decide the shape of the line.

I tend to think about them like a tourist who’s forgotten to do any sightseeing until the last minute and they need to get to the airport on time. They start at the hotel and have to see The Houses of Parliament and the Tower of London and still make their flight… best they can do is drive as close as possible, while still not taking themselves too far from the next sightseeing location. Ok, that’s a terrible analogy.

Not being a mathematician, I didn’t understand what the Wikipedia page was talking about, so I started looking around for code. Fortunately it’s a problem that has been solved a load of times before, so sources weren’t too hard to find, but everything I found was incomplete, or in the wrong language or incompatible in some way.  So I set about making my own class.

As you can see from one of the comments, I cobbled together some of this code. I think this is my source for the GetPointAtTime() function.

Now to plot a curve, you just decide how smooth you want it, 10 points would be very rough, 100 would be very smooth.

The problem with beziers is that they doesn’t plot these points evenly along the curve. You can see this on the curve set to 10 above. Depending on the distance between each of the 4 control vector3s, the points plotted by GetPointAtTime() will be close together or spaced apart. This isn’t a problem if we’re just drawing lines, but I want to construct a 3D mesh and map a texture to it. If the spaces between each point is uneven, then the texture will be distorted.

Evenly spacing points along a bezier

The solution is to find the length of the curve and then divide it into equal segments. However, because the bezier function just returns a list of points, we have to calculate all those points and find the distance between each of them and then add them up. First add a couple of public variable to the Bezier class;

Then we add a function to the Bezier class.

This function runs through the bezier, generating _precision points, saves the lengths between each of those points and saves the total. Then, for each  _num  it counts up the distances in sequence, when it finds the arc length that’s a good match, it saves out a point into an array.

On the left, the original points, on the right the points calculated
On the left, the original points, on the right the points are evenly spaced

Now our points are evenly spaced out, we can use them to build a mesh that won’t be textured unevenly.

Here’s my complete Bezier class;

In the next part I’ll go into creating a mesh based on these points.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">