Crafting a Game Engine with User Experience in mind

I wouldn't recommend my game engine to anyone. Not that it doesn't work. It does. The major flaw of my engine is that it was not developed with the end-user in mind. It was developed with my curiosity in mind.

As I mentioned in my previous post, I'm pivoting and developing a new engine. Its a complete rewrite with all decisions revolving about the user-experience instead of my own.

With this new rewrite, I'm spending considerably more time thinking about the editor, its functionality and features than I ever did in the past. I'm spending more time making the controls and camera user-friendlier. I'm spending more time thinking how to make the experience of the user more enjoyable. With all honesty, I have yet to dwelve into low-level graphics stuffs; I'm dying to do so, but this time, I know better. Is all about the user, not about me. To put it simply, I've been thinking more about how to minimize the pain points of my target audience than doing hardcore coding.

I'm enjoying this new approach. Is forcing me to view things from another perspective. I made several bad decisions with my game engine, and thus I won't recommend anyone to use it. However, those decisions brought me to the place where I am now. It opened my eyes to where I should go next. And my next move is to make a game engine not for me but for you.

Thanks for reading.

Why I Decided to Rewrite My Game Engine

I have decided to rewrite my game engine. In fact, I already started a couple of weeks ago. I know, I know, it's an insane decision to develop an engine all over again. But I have good excuses to do so. Here are the three reasons why I'm rewriting my engine:

  • Acquired Expertise
  • Desired to learn a new language
  • Becoming an expert

Acquired Expertise

Over the past years, I have learned so much about computer graphics. I am not the same engineer who started writing an engine in 2013. And if given to chance, I would not develop Untold Engine the same way as I did. Looking at the codebase, I can pinpoint many issues with my game engine. As a matter of fact, I am embarrased with some implementations. But hey, I did not know, what I didn't know.

In a previous post, I mentioned three things that I would do differently. Code wise, I would implement the engine using ECS architecture. I would make use of compute kernels throughout the engine to help with performance. And more importantly, and this is a big one, the codebase would be a lot cleaner/simpler and less full of clutter.

Desired to learn a new language

I can rewrite my engine in C++. But I don't want to waste an opportunity to become an expert in Swift. You may say that is crazy, and maybe it is, but I want to be marketable and learning Swift may help landing job opportunities. Moreover, at work, I use C++ and Objective-C and I don't want to spend my weekends using the same languages. I want to try something new. Finally, Swift is kind of a cool language. I'm starting to like it.

Becoming an expert

My third reason for rewriting my game engine is a personal one. My personal goal is to be expert in this field. Is a personal goal that keeps me going.

We all know that the first time you do something, you are going to suck. The second time around, you will do better, and on and on.

I know that my game engine is not the best one out there. But I know that the second time around, I will develop a higher quality, higher performance game engine ready for the market to use.

So, wish me luck. I'm going to need it. :)

In Retrospect: Three Game Engine Development Choices I'd Change

If you had the option to rewrite your game engine from scratch, what would you do differently? If you ask me, I would do the following:

  1. Use ECS (Entity-Component-System) over OOP.
  2. Leverage Industry-Standard Exporting Formats rather than using my format.
  3. Bulletproof my engine by providing defaults upon load failures.

Let's go one by one so you know what I mean.

Use Entity-Component-System

I wrote my game engine using C++ and decided to take the OOP approach. OOP served me well until my engine became too complex. Soon after, I realized the limitations of OOP; it can lead to complex dependencies and deep class hierarchies, making the engine difficult to maintain and scale.

I've written smaller renderers using the ECS architecture, and I can tell you that if you implement ECS, your engine will improve its performance; ECS allows efficient memory access and cache coherency. Moreover, the codebase of these renderers is a lot cleaner and less convoluted.

Leverage Industry-Standard Exporting Formats

A huge mistake that I don't regret doing was coming up with my file-exporting format. Instead of using OBJ, FBX, USD, etc. I decided to come up with my format and write my exporter. I learned a lot about Computer Graphics doing so but it came at a cost.

See, I wrote a file exporter for Blender version 2.79. Since then, newer versions of Blender have been released and my file exporter no longer works. I can't export 3D models from newer versions of Blender into my game engine. I can fix the issues but I would have to do the same thing with newer versions of Blender. This is something I do not want to do.

So, instead of coming up with my format, I would leverage the industry-standard exporting formats such as USD and make it compatible with my game engine.

Bulletproof my engine by providing defaults upon load failures

Finally, I would prevent any crashes due to missing files, incorrect file paths, missing textures, etc. I would provide default textures, and 3D models in case the user forgot to provide the assets.

I would provide informative and user-friendly error messages. Instead of just catching the error, I would provide clear error messages that users would understand and provide guidance on resolving it.

As you can imagine, I failed to add default assets to my game engine. Some of the error messages are not informative enough, to the point that I have forgotten how to solve them. That is not good.

So, if I was crazy enough to rewrite my game engine all over again. These three things would be the top priority. So tell me, what would you do differently?

2022 was a waste for my engine until this happened

The year 2022 was an excellent year for me. I started a new job, and my family grew. But, in terms of the engine, not so much.

 
 

I'm sad to say that the Untold Engine saw little progress this year. Part of it was personal matters that needed my attention which reduced my bandwidth. But the main reason was the lack of direction for the game engine.

For most of the year, I had no idea what to do with my game engine. I wanted to niche down my game engine to a game genre. But could not decide on the game genre.

My instinct was to make the Untold Engine a Football Game Engine. And I implemented several systems to make the engine more football/soccer based. However, these implementations went nowhere. To make matters worst, some of these systems took a long time to implement.

So, I found myself going back and forth, trying different ideas. I hate to say this, but this year was mostly wasted trying to figure out what I wanted to do.

A couple of weeks ago, I realized what I needed to do.

See, I have been developing simple football/soccer demos for my game engine. Over time, I learned what is required from an engine to make a sports game. I also learned that the most tedious part of a sports game is the animation/physics synchronization and the AI system.

I kept thinking about how can I fix these issues, and it hit me:

I need a Debug Visualization Tool in my engine to help me visualize what the AI sees.

This realization changed everything. I went from being lost with my game engine to realizing that I could make my game engine unique and awesome. So, during my time off from work (Christmas vacation), I started implementing the necessary 2D visualization tools.

Let's go over the tools that I developed.

2D Visualization Tools

Zone Division

I developed a way to parse the field into zones. Each zone represents the zone the player is allowed to move during the game. Zones are helpful since they keep the team's formation throughout the game and allow for AI tactics/strategies.

Area Computation

I also integrated a Voronoi Diagram visualization tool. Voronoi Diagrams help the AI determine whether a player has enough space to dribble or if it should pass the ball. For example, if the Voronoi cell decreases in area, the player should pass the ball. On the other hand, if the cell increases in size, then it can continue dribbling. The same idea applies when looking for a teammate to pass the ball.

Nearest Teammate

As you may expect, I also implemented a Delaunay visualization tool. The Delaunay Triangulation algorithm informs the AI which teammate is nearest the active player. In addition, the AI system can determine which teammate should receive the ball by calculating the Voronoi Cell area.

Aside from these three main tools, I also added a Parameter Visualization tool. It helps me visualize the properties given to each player.

So what is next?

Now that I have a roadmap. The subsequent versions of the engine will focus on implementing more tools that help me develop football/soccer games efficiently. I'm excited to build a tool to visualize the player's animations and movements.

I'm excited about the future of the Untold Engine.

Thank you for reading.

Write your first GPU Kernel using Apple Silicon

Hey guys, I want to share how you can write your first GPU Kernel using Metal. Our example will be straightforward but will lay the foundation needed. All our code will do is write data from one buffer onto another.