Actor Component System
Bryson McIver - April 21st, 2020
For a long time I've been dreaming of games where you're fully immersed in a world. I want the world to feel like it is living around me to the point where things are happening not just because I'm the hero and I've done something, but because that's just the way the game lives. I want to be the participant who can sway things either direction, but isn't the cause for everything happening in the game and could even just AFK (or set as a desktop background somehow) and watch as the world evolves. Maybe nothing significant happens, but the ebb and flow continues. I've thought of some specific examples recently for my top 3 ideas which I would love to see this type of naturally flowing world in.
- A game where two sides are at conflict and you're just a mercenary who each is trying to contract. Do you side with one of them and help push them to victory, do you take contacts from both and help each side accomplish what it thinks it takes to win or do you just observe the two factions going at it, grabbing and losing outposts and supplies.
- An environmental simulation. Something like "Equilinox" (on Steam) except even more hands off where the entities just live their lives, learn behavior, and evolve. Environmental factors would come into play and the player could either partake as an entity or observe and effect in some type of god mode.
- An RPG (likely space or medieval) where the economy matters greatly and the other NPCs are simulated agents within the economy. They'll craft, collect and transport resources based on their own skills, knowledge, and current economic state. Take this a step further and start generating content where you effect the economy (maybe in an MMO with other players, Star Citizen is attempting to build a system like this).
While the complexity of a game like this would be quite difficult, I think the design of a system which can support this type of autonomy and flexibility is quite and interesting challenge.
Components
Most people in game development know about components since they are wildly used across many engines to separate concerns across different systems and create reusable pieces to be applied to any entities in your system, although they are often used vary differently depending on the engine you are dealing with.
Actors
The actor model of programming separates each piece of computation (in this case entity) into something that can send and receive messages as well as act on these messages. These are often used in concurrent systems because each actor can do their processing at the same time on whatever messages they receive.
ECS
Entity components systems take components to the extreme and each game object consists of only components and nothing else. This gives you the flexibility of being able to add and remove behavior and systems by changing the components attached to an entity. This allows you to add a skill of a player by just adding that component or add that same component to an enemy to give them that skill and remove them at will. In something like an environmental simulation, you could mutate the parameters of a component to simulate evolution and have a small chance of gaining a new component all together to completely change the behavior of an entity.
Actor Component System
My idea for these simulation games is to take ECS one step further and create ACS (I'm sure I'm not the first one to think of this though, but I haven't read about this idea yet). In this system your top level entity is an actor, able to send and receive messages. The components on this actor are also actors, and they can do all the actions of an actor as well. I think that this gives you deep modularity and decoupling that you can create emergent behaviors this way (as you would need in an interesting simulation).
Let's take for example an actor which has a stomach component, a navigation component and a sight component. The stomach would send a message to the top level actor, requesting food when it was hungry. That top level actor would send the message to the other components and those would decide if they can do anything about that. The sight component sees a berry bush which would satisfy this hunger, so it sends out a message asking to get to that bush. The navigation component gets this from the top level actor and then moves us to the berry bush, which then the stomach component consumes (in a more detailed example we might have a component which can hit objects to cause the berries to fall and it might collect these.). This sounds pretty complex just for the simple behavior of wanting to go eat a berry, but what if we want to switch out the navigation component to one that acts like the actor is a bird and can fly where it wants to go. Well that's no problem because it just takes the same message and doesn't need to know what other components sent that message. Now we want to add a component for health and it can react to messages sent from the stomach about starving.
Outside actors also don't need to have any idea what another actor can and can not do. If someone tries to hit someone else, they just send the message to the other actor, that actor distributes to the components and if one of those components (or multiple of them) process hit messages then they'll react accordingly. As long as you generalize the message types sent out enough such that they can be handled by a variety of components and you have a standard set of these, then your actors are able to interact with each other without knowing anything about each other (and concurrently which can be useful in large simulations).
I can have a weather actor (with a rain component and a flying straight line navigation component) travel across the landscape, a mage who uses water magic, and a river all emit the same soaking event to agents who come in contact with them and if those agents have components which react to getting soaked (ex. temperature component) then interaction is created. I don't need to go and edit every existing actor in the world when I add a new one, I can simply create a waterfall with components and all of the actors will already have their behaviors ready.
There is one case where this obviously falls apart, and that's if you need to add a new message type to your game. A new message type means that no one has ways to handle it yet and they'll all just drop the message creating no interactions. Careful planning has to be done when designing your initial message set to limit the work of going back and supporting additional message as the smaller the set the more dynamic behavior between components can exist. It isn't that hard to add a new message type though, since all your actors are made of component actors, so you already have the code separated and don't have to worry about intertwining or breaking systems you aren't expecting to.
I've struggled for a while with how you define and balance actor level behavior as well in this system. If you get messages about being hungry and thirsty, which do you do? I think how you approach this may be a per game design decision. If I'm working on an environmental simulation, I could use the processing at the top level agent to filter and decide which messages to pass on based on simple rules I define for that agent type. My bunny agents could pick thirst over hunger, and idle wander when they have no desires. I don't particularly like this because you are tied to knowing about what types of messages are in the components below you, but if you know that a bunny is made up of x,y,z components then that isn't an issue. You could attempt to use some type of statistical or machine learning approach, creating a "brain" which makes decisions after being trained in the simulated environment. This approach seems to add another massive level of difficulty and complexity on this system though, and won't lead to tuning of the environment easily. To balance these two ideas, some type of system which attempts to maximize value based on behaviors and their expected values on the known state of things allows you to explicitly define high level behaviors of actors, tune their expected values to produce types of game play but still allow them to have some agency (especially if randomness is added in instead of pure maximization of value) in how they choose to go about their lives. I can define the aggressive general who sees more value in attacking enemy encampments and chooses that behavior more often to tell his officers to attack. Or tie the expected values to different components representing skills on the actor, and have an actor with a high mining skill expect more value from his mining returns and will therefore lean towards mining and selling his ore.
I'm not completely sold by any of my ideas for the "brain" of the actor or how to produce less primitive actors past the "I'm hungry example", but I do feel like the system has real flexibility and power. If we want to run a giant simulation (with real players even), we can horizontally scale out the NPCs and have them each run on their own small server to simulate a massive world (of course holding world state would become a problem at some point and we might have to address that inside our actors with memory of some type). If anyone does have experience in a system like this or has seen anyone else talking about a system like this, please reach out to me because my current progress on actually implementing this is slow and I'd love to hear about anyone's experience building something this flexible and if it backfired on them.