Build Games with Your Game Engine
The Last of Isetta: the apple of our eye, as far as the game engine was concerned
When building an engine, there are some obvious ways of testing your code like unit tests and integration testing. While these traditional software engineering practices help with certain systems, like a math library, it isn't obvious how they transfer to something like a game engine which, as Casey Muratori put it, is an amorphous blob of input. Games have a different ecosystem for testing than software. For us, the way we were able to test our code was by a three tiered system: first with tech demos, then with sample games, and ending with a game jam. Tech demos tested if the feature was functional, sample games tested the feature in a gameplay setting with the engine as a whole, and the game jam tested the actual usability of the feature. Lastly, there's one major reason to build a game using the engine: the only way we were able to complete our engine in 15 weeks was because we targeted the engine's features at an existing game that we made. We didn't just target the engine at a genre, or an idea of a game, but an actual game with its design details and implementation.
Specifying the genre of the engine isn't useless because it can help guide as a reference for which features are engine-related and which are game-related. It's more helpful in the beginning of development when designing the engine architecture, but ultimately, the game really is the deciding factor of what features are needed within the engine. For example, most twin-stick shooters don't need a physics system beyond collisions, but if the game you've designed does, you aren't going to not develop physics because the genre says it's uncommon—that's one of the benefits of having your own engine!
Tech demos are certainly useful, but they serve a different purpose from games
You may argue against making a game by saying, "I'm interested in learning engine development, not game development", or, "I've made games before, I know how they work", but don't listen to yourself. Although it was useful in our case to have the game designed and implemented in another engine, this doesn't have to be the case for you. It can be just as good to have a game design document. The main point here is to be able to deconstruct a high-level game mechanic into what engine systems it relies on. This will also help with knowing your priorities and the dependencies of your engine features.
Having a target game for your engine can help prevent overscoping, feature-creep, and building unused features. For the Isetta Engine, we began wrapping the GUI library Dear, ImGUI in our own shim. Once we started doing this, we found that if we didn't restrict ourselves to just abstracting what the game needed for a GUI, we would have lost an additional week to just abstractions of features that weren't actually going to be used!
Another use of a target game can be pulled straight from game design: it gives you design pillars to make your decisions. For each decision you make with the engine, ask yourself, "does the game need this?" If the answer is no, put a
TODO there and keep working on features that the game needs. Especially if you are working on a team, you can trust that everyone is furthering the engine each day because no one is going off in their own rabbit hole of development.
A target game also gives you a way to showcase your work. Others will be able to contextualize what you've done and you will be able to see what you have left to do. This can act as great motivation to help get the project done; it is a similar feeling to when you get your first triangle rendered or game mechanic prototype working. Also, working incrementally like this will help you set a point where you're comfortable calling your engine "finished". We aren't saying you will ever feel like the engine is ever truly complete, but when you have the target game working and not completely hacked together, you can certainly call it a game engine!
"Okay, so I can just build one game." We wish. Before starting this project, we dismissed the idea of building multiple games on top of a game engine in just 15 weeks. We even dismissed building just one game originally! However, each game that you develop will help you prove that the engine is actually progressing outside of its own codebase. These games don't serve the same purpose of the target game, nor should they be the same scale. The target game is what drives the engine decisions; these sample games need to live with those decisions and work around those constraints like a developer would be forced to. We would suggest you try to mimic some pre-existing designs with each of these game, and have the game focus around a single mechanic. They don't need to be polished masterpieces, and actually, it's better if they aren't. Their purpose is to use features in a game-like manner, which is almost certainly different than how they were tested through the tech demos. Especially if you have a developer do this who wasn't involved in developing the feature, you will almost certainly find bugs and API problems that you had missed originally.
These games aren't meant to increase the scope of the engine. Don't let them drive new features. However, if you notice multiple games need the same type of system, that may be an indication it should be included in your engine. This is also a good time to notice if a certain feature needs to be hacked around or is too specific to be used by multiple games; that means that it may need to be refactored. This is even the case if the feature is for your target game, because that may mean you built game logic into your engine and you need to move it to where it belongs.
We would recommend to anyone developing a game engine, especially one without standard software development testing, that you start developing demos and games as soon as you can. You don't have to wait until the engine is built and exported into a linked library to build levels. You should be able to start developing them within the engine (just make sure they don't stay there forever!). We started making legitimate games after we had finished implementing our scene graph hierarchy, and you might find this to be a good marker for your own timeline as well. All code examples prior to this point are hard to translate into usable examples, as any examples before are mostly hacks in the main engine loop. This is why we'd recommend pushing to get the scene graph hierarchy done much sooner than we had, which was Week 6. The scene graph doesn't rely on as much as you'd believe; for example, you may associate having a scene graph with models or components, but those just elaborate on the basic things you'll need for testing (rendering for visualization, behaviors for...well, whatever feature you're working on).
Keep in mind, most people think of these when someone mentions the Unreal Engine...
Remember, you are building a game engine whose sole purpose is to help create games. If you don't develop at least one game with your engine, you don't really know if helps, do you?