Game Objects or Entity Systems
To start, I intentionally left out “component” from Entity Systems. They add an extra layer of indirection which will probably make this post more bias towards Entity Systems. While I like the fact that components allow you to abstract objects more easily and to allow you to customize entities without needing to open up a code editor, I dislike not having a concrete class that I can play with.
One of the biggest problems I face is that I have to have my tools work for me and not against me. This often leads to times where I completely refactor my game engine for what seems to be no apparent reason other than I didn’t like the way something worked. Generally these issues would appear minor to most people, but for me they are huge.
This almost always leads to sideways progression instead of forward progression. An example of this recently is that my current engine uses a sort of Unity GameObject system. All game objects can have children and scripts attached to them and has the same style event system unity has (all though mine is almost as fast as a straight function call, we’ll save that for another day). While this approach works, I don’t like creating manager classes that you attach to the root game object and then have to pull them out in scripts with something like “var bulletManager = rootObject.getScript<BulletManager>()”.
Just relying on GameObjects and scripts seems clunky to me and this is where I feel Entity Systems shine (and why I added it to my current game engine). My MC clone actually uses this for both client and server. I really liked the way things are split up in to units of work (but kept together). On one hand I like to define an entity’s structure (data) in a single class and have systems interact with that data. On the other hand, its nice to just be able to attach a script to a single object and watch it work.
Both of these examples work in my game engine today. I wonder which one people would prefer…
Entity System
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public interface IPositionable { Vector2 position { get; set; } } public interface IVelocity { Vector2 velocity { get; set; } } public class MovableEntity : IPositionable, IVelocity { public position { get;set; } public velocity { get;set; } } public class VelocitySystem : System { public void init() { require<IPositionable, IVelocity>( (pc, vc) => { pc.value += vc.value; }); } public void update() { //call the helper function from require on each entity base.processEntities(); } } //init game Root.instance.addSystem(new VelocitySystem()); Root.instance.createEntity(new MoveableEntity()); |
GameObjects and Scripts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class TrasnformScript : Script { public Vector2 value; } public class VelocityScript : Script { public Vector2 value; } public MovementScript : Script { private TransformScript transform; private VelocityScript velocity; private void init() { transform = gameObject.getScript<TrasnformScript>(); velocity = gameObject.getScript<VelocityScript>(); } private void fixedupdate() { transform.value += velocity.value; } } //init game var go = rootObject.createChild("movableEntity"); go.createScript<TransformScript>(); go.createScript<VelocityScript>(); go.createScript<MovementScript>(); |