Structured Programming rediscovered and honed for game development.
I've been looking into game dev lately. Always been a gamer. Always wanted to make games. But getting into it seems completely overwhelming. I found a podcast on DEV with Jason Weimann talking about game dev, and then his youtube channel with videos like this one.
His videos are incredibly helpful. But I noticed that many of them are centered around dealing with Object-Oriented ceremony and footguns. This is because Unity uses the OO model pervasively, and requires your code to use it as well. Being an old dev interested in system design, I went looking for other game dev organization schemes. I discovered the Entity-Component-System or ECS architecture.
The three parts of ECS are:
- System - logic for a single aspect of game objects
- Component - data about a single aspect of a game object
- Entity - a game object with a unique ID, contains components
The obvious interaction here is to pass the Entity to a System behavior. Such as "add to inventory" in the Inventory system or "take damage" in the Health system. The behavior can check if the Entity has a component that it knows how to work with. And if so perform the requested behavior on that component.
ECS cleanly separates the systems of the game into maintainable slices. The Unity folks seemed to think so as well since in 2018 they made an announcement that they were adding ECS to Unity. Not only for maintainability reasons but for performance.
At the end of 2020 this still remains to be seen. They have now hidden the beta ECS packages. (You can still install if you know the URL.) Presumably because there is so much churn that it is guaranteed to break game code in future updates.
On the whole the system ends up breaking down into data structures with no behavior, and functions or procedures that operate on those data structures (and the implicit side effects those procedures cause) to produce a behavior. This is the same arrangement used by Structured Programming.
Structured Programming came about in the late 1950s, at first primarily being about block structured syntax. And later officially branded in a 1966 paper by Corrado Böhm and Giuseppe Jacopini. But probably more well known as championed by Edsger W. Dijkstra, where we got our "... Considered Harmful" memes.
Like most things that are created and released into the world, the creators and proponents of this paradigm probably assumed it would be used in a certain beneficial way. To tame the spaghetti of Assembly code. But instead of using the tools to organize our code we just moved the spaghetti into procedures with Procedural Programming.
Most languages have procedural programming -- a descendant of structured programming -- as the substrate underneath their paradigm. Meaning once you get past the declarations the code is written as a statement-oriented and block-structured procedure.
The primary difference is purpose. Structured Programming is meant to put your program on good footing for maintenance. A video game is just a program, right?
Look at it this way. If a business has a universe of applications and services working together to deliver business value, a video game is a microverse (or sometimes an even larger universe) of all the same kinds of things working together to deliver user value (game experience). The breakdown of a triple-A game into its many systems, when translated into the business world, would be the domain of a software architect. So in essence ECS is not simply a program structure, but a base architecture.
This significant difference in packaging compared to business systems leads to another important adaptation. Namely, you can add or remove arbitrary Components (data structures) from an entity at runtime. This is quite different from structured programming where data structures were completely pre-defined. Additions and removals of this kind would need a recompile and redeploy.
Since ECS is an architecture, this property of entities makes perfect sense. Put on your Business Dev hat and consider a Customer. Accounting does not need to know about every sales lead... only the ones that buy something. And then they care about their own specific aspects of that customer which sales may not, e.g. billing address. In this analogy the billing address is part of the Accounting ECS component, but not the Sales component. And Accounting ECS system requires that component it be present to perform its function.
Remember, an ECS Component is only data. State would have been a better name for it, but nobody asked me back in 2007 when they named it.
I have previously made a connection between Structured Programming and Functional Programming. Basic FP (without all that category theory) takes Structured Programming and draws out one more key concept -- the side effect -- and makes it first class and explicit instead of implicit. This greatly increases the testability and maintainability of code. And so I think ECS could create a strong synergy between game dev and FP. Wait: FP and game dev -- am I crazy? I don't think so... check out John Carmack's thoughts on the subject.
Like most new ideas, ECS stands upon the shoulders of giants that came before. It is not new at its core, but how it is applied is novel. Unity seems to be a popular and "easy" entry into the world of game dev. I look forward to trying their ECS system. Especially since F# is also usable with Unity. ECS and F# would make the ultimate combo for me.