Sponsored By

Filling in the dotted line: bezier curves and creative pride

A story about why sometimes we avoid the easy solution.

Aidan Barrett, Blogger

December 12, 2023

7 Min Read
Game Developer logo in a gray background | Game Developer

A few months back, I was tasked with adding curving functionality to an existing line rendering system. This should have been a pretty simple task, just modify the existing path waypoints and add the ability to generate a curve given a few parameters. What it did end up being, was a nightmare.

Here’s why.

So to give a little bit of backstory here, the game I’m working on is a little tower defense game  called Go! Save the Queen! The gameplay has the player following a queen that moves along a set path. The game was always planned to have curved paths, however, during testing it never ended up happening. Partially this was to save time because it wasn’t that important, but in hindsight, this was my first mistake.

Because it was a pretty non-essential part of the game, we kept pushing it back. This became a problem because more things kept getting added to the existing waypoint and path system. So by the time that I finally sat down to implement these curves I was already looking at a decently large mess of code.

Now if you’re at all familiar with game programming or just mathematics in general, the answer should be obvious. Bézier Curves! It’s easy, it’s simple, it’s reliable. Just throw the in the mathematical formula, iterate through the number of points in the curve, and badabing badaboom, you’re done.

Unfortunately, as will be laid out in this post, I did not want to implement a Bezier Curve.

The First Hour

So after rooting through some of, to be frank, the most frustrating spaghetti code of my life (I am not insulting another programmer, this one’s on me.) I had finally dedicated a space in it to account for curving. All that was left to do was to figure out how I was going to generate the positions of the curve.

What’s important to establish at this point in time was that I knew that a bézier curve was the “correct” way to do this. I was aware that there were plenty of resources that would make adding the bézier curve easy. However, I decided that I didn’t want to use one. I wanted to find a different solution.

So off I worked, creating some of the worst formulas for a curve that the world had ever seen.

The Second Hour

My first (almost successful) attempt involved using Unity’s Slerp function (also known as Sphere Lerp). The idea behind this one was that I would use Slerp between two points then use a center point to increase the curvature.

This, unsurprisingly, was dramatically ineffective.

Slerp is great but it just fundamentally doesn’t work this way. The curve it creates is basically always going to be part of a bigger circle, with the visible portion being determined by a set center point and the two point’s you lerp between. Even more damning, the size of the curve will always be tied to the distance between the points.

So unfortunately this attempt fell flat on its face.

The Third Hour

The next major attempt was, to be blunt, a little bit looney. At this point I was getting a bit tired of repeatedly throwing solutions at the wall and having none of them stick. It was beginning to dawn on me, that I was spending more time finding a work around to the “correct solution” than it might have been to just do that.

But I’m nothing if not stubborn so this monstrosity was born.

The idea behind this one was “If the slerp doesn’t work because the arc of the curve never goes past a certain point, what if I just add a modifier to the arc for every point that extends past the start and end of the point!”

The idea was born from multiplying the slerp in general and thinking about how this could maybe work if I just multiplied the parts that are furthest away from the start and end point. So I went and began creating and iterating on a modifier function that would multiply the Y value of the slerps points depending on how the progress through the lerp, increasing the closer it gets to the midpoint.

This actually worked!

Almost.

I had began to get the center of the curve to move upwards, but I hadn’t thought about what happens if the curve is on a slant. Afterall, I was only accounting for the Y value, meaning that the result was far less than optimal.

And even then, It also wasn’t really behaving correctly anyway. I tried a lot more different variations to get this to work. I really wanted this to be the solution.

After a while, I finally realized that all I was doing was wasting my time. This attempt wasn’t going anywhere and the sunk cost fallacy had kept me trying for far longer than it should have.

The Fourth Hour

After spending so much time trying to get away from using a bézier curve, I finally caved and just looked up the formula online and translated it to code.

It took less than 5 minutes to implement and test a perfectly functional bézier curve

I added the formula to that existing path system and it worked out of the box, barely any extra work needing to be done.

The answer to why I was so resilient to implementing a bézier curve was a little more complicated than just saying that I was lazy. A part of it was that I was lazy, I was a bit tired from looking at my aforementioned awful spaghetti code and wanted an easy solution.

At a glace I saw bézier curves as complex, afterall just look at that formula! I hate math! (said the programmer.) and deep down, the reason I saw them as complex was because I was just a little bit scared of them. I had never actually needed to implement one before despite knowing that I inevitably would need to. I was scared that I’d do it wrong, or I wouldn’t be able to figure it out, or that it would take three hours to do.

But ultimately, that fear wasn’t the primary motivator that caused me to drop down this several hour long rabbit hole.

Instead, it was a fear of that fear.

At the bottom of it all, what I was really scared of was that I just wasn’t good enough at programming. If I was intimidated by the bézier curve equation, does that mean that I’m just not cut out to be a programmer? Has all the time that I’ve spent improving been pointless?

At this point, the mention of pride in the title becomes relevant. Because I know I’m a good programmer. I know that I can accomplish what I’ve set out to do, and maybe if I find a way around needing a bézier curve, I can prove that without needing that silly equation.

This pride, motivated by fear, led me nowhere. I, in fact, ended up feeling worse about my programming skills than when I had started. It was only by just buckling down and doing the solution I knew was correct that I was able to work past it.

I wanted to share this story because I feel like this is at least somewhat common among creatives. The fear of learning new things, specifically the fear of trying and failing a new thing, is tough. It’s not easy to work with and frankly, can only be solved by just doing it.

Sometimes, you need to buckle down and learn the way to do something correctly.

Sometimes, you just need to fill in the dotted line.

Read more about:

Featured Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like