I love books. I enjoy reading. And I always look for thought-provoking books. Some books provide insights that when you hear them for the first time, you are taken you aback. As you digest their message, you start wondering, "That is so obvious, why didn't I ever think of that?". And as you apply their message in your life, you notice how you become more productive, efficient, or happier.
In this post, I want to do the same. I want to share tips and insights that will help you develop a game engine quicker and more efficiently.
Let's begin
Tip 1: Game Engine Dev is 75% Programming and 25% Art
Contrary to what you may believe, game engine development requires some artistic skills. As someone who has been doing this for the past six years, I can say that game engine development is 75% technical, 25% art.
I learned this fact the hard way. In the beginning, I bought game characters and tried to render them with my primitive engine. It didn't go so well and spent hours trying to figure out the problem. Against my will, I was forced to learn 3D modeling tools. As I learned 3D modeling techniques, Computer Graphics concepts started making sense. As a result, I was able to improve the engine and know its limitations.
So, I strongly recommend you to take some time to learn how game artists model game characters, their workflow, etc. It will pay off.
TIp 2: A Class should have only ONE responsibility
A game object can have several behaviors and properties. It needs to be able to send information to the GPU (i.e., attributes, space transformation). It needs to be able to detect when it has collided; it needs to determine its current velocity after a force has been applied, It needs to create the illusion that it walks through animation, etc.
Your instinct may be to make the game object responsible for all these behaviors. But don't do that. Instead, delegate these behaviors to other classes.
For example, in my game engine, a game character inherits its properties and behaviors from these classes.
The U4DEntity class is the Root Class. it contains the local and absolute space of the character. However, any linear algebra operations are delegated to the Transformation Manager. If the character needs to rotate, it doesn't do it the U4DEntity class; it delegates that operation to the transformation manager.
The U4DVisibleEntity provides virtual functions that will be overwritten by a game character, but all the rendering operations are delegated to a Rendering Manager.
And let's say that you want your character to have animation, well, the Armature manager takes care of all operations related to 3D Animations.
Insight 3: Don't use Setters & Getters in a Math Engine
In every OOP book, you will find a section dedicated to data encapsulation. Data encapsulation states that data-members should only be accessible by set() and get() methods and that they should be private. This is a rule to always keep in mind, but from experience, you should break this rule when developing a Math Engine.
Rules are meant to be broken, but only if you know what you are doing. I strongly suggest not to use setters/getter in your math engine.
Insight 4: Use Tolerance when comparing floating-point values
Keeping this in mind is paramount.
The sensitive nature of the algorithms involved in Collision Detection requires a robust numerical comparison. Else, you may end up missing collisions.
I ended up wasting several weeks of development because I didn't follow this advice. In one instance, I had several objects colliding. Everything seemed fine except that now and then, the engine would miss a collision. What made it strange is that it would only happen at particular angles, and it was intermittent. After weeks of debugging, I found the problem. I was comparing floating-point values as if they were integer-point values.
Insight 5: Collision Detection is all about Computational Geometry
Yep. Collision Detection boils down to knowing Computational Geometry, Theory of convex sets, and Geometric Algebra. It is about determining if a point lies in a Convex-Hull. It is about determining on which side of a plane a point is located. Is about determining the closest point to a Tetrahedron, etc.
When I started developing the game engine, I thought that the only math I needed was Linear Algebra. I was wrong. Very wrong. See, when it comes to implementing a Rendering Engine, then you do apply Linear Algebra concepts. But when it comes to Collision Detection, is all about Geometry.
Tip 1: Start Small-Implement Collision Detection with Spherical Volumes
You may want to implement a Collision Detection system using Convex-Hull volumes and avoid spending time using spheres or AABB. But don't do that. The problem with Collision Detection is that You Don't Know, What You Don't Know.
See, Collision Detection is an art as much as is a science. It is a new language, so to speak. For one, you need to be comfortable with Computational Geometry. Second, you need to familiarize yourself with Collision Detection algorithms. Thirdly, Collision Detection requires a vast amount of peripheral code. Most of them related to Computational Geometry. For example, you need to determine if a point in space lies within a Tetrahedron.
Therefore, Start Small. Implement a Collision Detection system that uses Spheres as bounding volumes instead of Convex Hulls bounding volumes. It will not give you a precise collision, but it will help you get comfortable with various algorithms.
Tip 2: Start Slow-Implement Collision Detection with non-moving objects first
Implementing a Collision Detection System is all about taking baby steps.
Is about learning little by little as you fall. Don't rush into implementing a collision detection algorithm suitable for moving objects. All you will be doing is opening a Pandora box. So, start Small and Slow. Implement a Collision Detection System ideal for static objects first.
Insight 6: Visualize the algorithm before implementing it
I am a visual person. If I can see the problem, then I can find a solution. So what I try to do is scribble down the algorithm I am about to implement. I try to draw pictures showing the flow, steps of the algorithm. I even try to scribble the problems that may arise at particular steps. Once I have a good idea how to implement it then and only then do I start coding.
Now if you are not a visual person, this trick may not work for you. Nonetheless, you may want to try to do something similar. Take a long walk, go for a hike, ride your bike, etc., and think how you may implement the algorithm. Once you are ready, fire up your laptop and code away.
It may seem as if you are wasting your time, but I have found out that when I do this, I end up with fewer bugs to fix.
Try out this trick; you may end up being more productive.
Insight 7: There is no one way to develop a game engine.
When I started engine development, I would take what I was reading about engine development as gospel. I didn't allow my imagination to fly. I wanted to do something complicated and was afraid of failure. So, during the beginning, engine development felt like a chore. Until I realized the beauty of game engine development is the fact that there are thousands of different ways to develop an engine. And that NO ONE, ABSOLUTELY NO PERSON knows the right way to develop a game engine. Yes, there are best practices you should follow, but there are no hard rules that state how to do it.
That was the moment when I fell in love with game engine development. At that moment, I became free "Intellectually," and I started experimenting with my own ideas. I still read articles and books, but I don't take their content to heart. Instead, I see it as a suggestion. I read from multiple sources, I analyze different code snippets, and once I feel ready, I go on and implement a particular feature the way I think it should be applied, not how someone else is telling me.
So, don't think there is one correct way to develop a game engine. There are plenty of ways. You build your own.