added 8 characters in body
Source Link

However, as mentioned at the beginning of my question, I am concerned about using run-time dynamic typing in this fashion (See my dispatch code in Entity - the second snippet in this post). This system will probably be handling a lot of messages, and I have some concerns about the overhead incurred (it also feels like a code smell toin general)

However, as mentioned at the beginning of my question, I am concerned about using run-time dynamic typing in this fashion (See my dispatch code in Entity - the second snippet in this post). This system will probably be handling a lot of messages, and I have some concerns about the overhead incurred (it also feels like a code smell to

However, as mentioned at the beginning of my question, I am concerned about using run-time dynamic typing in this fashion (See my dispatch code in Entity - the second snippet in this post). This system will probably be handling a lot of messages, and I have some concerns about the overhead incurred (it also feels like a code smell in general)

Source Link

Communicating events between entity components with minimal code overhead

I'm working on a game which utilises a variant of the entity component system pattern. In my current code, I have been communicating between components using code of the form:

_entity.GetComponent<MovementComponent>().TargetPosition = targetPosition;

I wanted to remove this very strong coupling which my components have (as a result of specifying exactly which component should receive the message), and transition towards an event / message system.

As a result, I've written an implementation which seems ideal, however it uses run-time dynamic typing which has me concerned that there may be a better way to achieve my goals.


My code is as follows, currently:

Inside Entity:

public void SendMessage<T>(T message) {
    _components.ForEach(x => (x as dynamic).Message(message));
}

Inside Abstract Component class:

public virtual void Message(IComponentMessage componentMessage) { }

Inside an example component (MovementComponent) that receives a move message:

public void Message(MoveMessage message) {
    Console.Write("Received message");
}

Dispatching a command to move:

private void IssueMovement(TileCoordinate targetPosition) {
    Console.Write("Dispatching move message");
    _entity.SendMessage(new MoveMessage(targetPosition));
}

Example Message class - MoveMessage:

public class MoveMessage : IComponentMessage {
    public readonly TileCoordinate MoveTo;

    public MoveMessage(TileCoordinate coordinates) {
        MoveTo = coordinates;
    }
}

NB: IComponentInterface is just an empty interface at the current moment in time.


The way I see it, my current approach has some big advantages:

  1. Adding a new message type does not require any modification elsewhere to be supported.
  2. Subscribing to an event is as easy as creating a method with the correct event class.
  3. There is practically no overhead for listening to a specific event - no need to instantiate a class, inherit some event-specific interface, register interest at run-time with a subscribe method, etc.
  4. As messages are represented by classes (like a MoveMessage), they can contain all the relevant data without needing to be cast or coerced.

However, as mentioned at the beginning of my question, I am concerned about using run-time dynamic typing in this fashion (See my dispatch code in Entity - the second snippet in this post). This system will probably be handling a lot of messages, and I have some concerns about the overhead incurred (it also feels like a code smell to

I would really appreciate feedback on this approach; particularly whether it seems like an abuse of dynamic to more experienced C# developers than I, but would also appreciate alternative suggestions.

Alternative approaches I've considered, and why I did not go with them initially:

  1. Exhaustive set of event properties which components can subscribe to manually - adds extra code overhead to each message type, which I'd like to avoid
  2. Dictionary from event Type to handler in each component - have to subscribe at run-time, which feels undesirable.
  3. Switching dynamically inside a non-overloaded handler - more viable than it sounds since most components will not listen to more than a few message types, but still has unpleasant code overhead

I am quite sure this code is okay, outside of the overhead induced by the run-time typing - my apologies if this makes it a bad fit. I am just hoping for a once-over review by someone more experienced to reassure me that this is a good design.