Entity Component System in MMORPG games

Putting the memory usage improvement aside, why people choose the ECS architecture, as it looks pretty drastic to me, when you can simply follow the “composition over inheritance” rule.

For example, suppose we want flexible abilities like moving and defense.
We shall define:

interface IMovable
{
	public void Move(Direction direction);
}

class PositonState
{
	public int X {get; set;}
	public int Y {get; set;}
}
class VelocityState
{
	public int Size {get; set;}
	public Direction Direction {get; set;}
}
class MovingBehavior : IMovable
{
	private long _timer;
	
	// relevant states
	private PositonState _position;
	private VelocityState _velocity;
	
        public MovingBehavior(PositonState position, VelocityState velocity)
	{
		this._position = position;
		this._velocity = velocity;
	}
	public void Move(Direction direction)
	{
		// some logic that depends on the position and velocity states
	}
}

Now, suppose we want to add the moving ability to player, all we need is adding the relevant states and the behavior:

class Player : IMovable
{
	// states
	private PositonState _position;
	private VelocityState _velocity;
	
	// behaviors
	private MovingBehavior _movingBehavior;
	
	public Player()
	{
		// initialize states
		// ...
		
		// initialize behaviors
		this._movingBehavior = new MovingBehavior(this._position, this._velocity);
	}
	
	public void Move(Direction direction)
	{
		this._movingBehavior.Move(direction);
	}
}

Adding abillity to defence can be implemented likewise.

What do you earn?

  • Explicit entities (players, NPCs, monsters) that aren’t hidden behind general ‘Entity’ class.
  • Using more intuitive code (e.g. for netcode, rendering), encapsulated objects without any fear from “breaking” the ECS paradigm.

What do you think guys?

What you’re effectively describing is SOLID programming principles. Take your code sample one step further and inject the new instance of MovingBehaviour (or a factory instance that creates it) and you’re there. What programming in this style has a tendency to do is produce highly maintainable, easy to understand code that is extremely easy to test.

This is my go-to for designing systems as, especially when combined with high coverage of unit tests, it’s proven extremely effective. My code base is resistant to unexpected breakage (ie, a fix here breaks something else there) and very easy to refactor. Having said that, there is a cost… and that cost is performance.

I’ve been meaning to do up a video on this topic and post it here, but I haven’t had the opportunity yet. As a bit of a spoiler, the general cost of writing code in this fashion can be as much as 30% in terms of performance. This seems to come from the additional layers of abstraction you put in your code. Instead of one class that does many things, accessing data directly, you have many classes doing one thing that your call stacks have to traverse through. The cost is small, but it adds up over many, many operations.

What’s important to realize here is that this doesn’t mean SOLID principles should never be used… in fact, they’re probably still the go-to for 90% of your code base. What it does mean is that it’s useful to be aware of this. You need to decide what level of performance your code needs to meet and if the coding approach you want to take will have a negative impact on this. If it does, you need to take alternative strategies. For instance, you can still put those performance intensive pieces of your code behind targeted components, but perhaps you need to do it at a broader scale, choosing different design principles for the implementation at that level while you follow your preferred style more globally.

Anyway, this is something that has come up for me recently and I figured I’d share. Hopefully I can get around to making that video so I can share the research I’ve done so far :slight_smile:

@Trinith
Thank you very much for your detailed answer!

I would like to watch such a video :slight_smile: