The Quest for a Great Engine Design
architecture middleware engine
One big thing that I'm struggling with as a developer is wanting to do it right the first time. I'm such a perfectionist at writing code that sometimes I get so frustrated and lost trying to design a system that seems perfect. My brain isn't big enough to grasp all of the intimate details and relationships between components of the engine. Questions like, should I split the scene object into a renderable object for the render data, and scene node object for the spacial and transformation data? Or just lump them all together?" How decoupled should components be? Where do I even start?!
As I think about this problem, I am realizing that I have two major issues with my design philosophy. For on, I don't give myself enough room to make mistakes. Sometimes, in order to find the best way to do something, you have to try several different options. I found this out personally through my year-long school research project where I wrote a multithreaded software rasterizer. In my first attempt, I spent hours upon hours meticulously planning how the pipeline would work. Even worse, I gave in to the dreaded deadly sin of pre-optimization. In the end, I had to scrap the architecture entirely. I lacked the expertise to understand that the "optimizations" I was making were really making things slower--way slower. In my second attempt, I learned from my mistakes and built a designed architecture that was far superior. In the end, I didn't fail the first time. I just learned how not to make a software rasterizer (to paraphrase that grossly overused Edison quote). Sometimes we need to stumble in order to learn how to do it right.
The second problem with my stubbornly innate design philosophy is that I expect myself to be able to draft out a complete schematic of a fully functional game engine without even understanding its requirements. Every game engine that I know of has limitations--albeit some have more than others. At some point, the developers had to decide what type of games they were going to support and make assumptions based on that fact. Take the Doom 3 engine. From what I can tell from the source code, the guys at Id knew they were going to write an FPS, so they designed their engine to support an FPS. There are core engine classes that have special functionality to support certain types of world triggers and characters that are specific to an FPS. Somehow I got it into my head that my engine has to support every game type under the sun and be completely generic. I'm learning that this just isn't realistic. The difficult part for me now as hobby developer with virtually no real-world game development experience is knowing what my engine should support. Does it need to support instancing? How should physics components like joints be represented by the entity system? Should there be one entity per component? Or an entity for a tree of components? The same thing goes for mesh subsets and other things. How do you handle decals?
These are all important design questions that need to be answered before the core engine is built, because sometimes a new feature won't fit nicely into an existing solution. My problem is that I'm fairly ignorant about what these things require from the engine. It's like I have the drive and motivation, but there's just so much information to handle! I think I need to do a couple things. I need to spend more time playing around with existing solutions to see what's out there functionality wise and how it is presented to the end user. Also, I need to stop my daydreaming about designing the next big next-gen engine all by myself. Maybe I just need to set my sights lower to something achievable and take baby steps. Maybe a good first baby step is really learning DirectX 11 well.
One final observation. I have noticed when I look at engine code that every solution has its problems. There is no perfect engine (and never will be). I guess I shouldn't expect mine to be either.