3
\$\begingroup\$

I want to figure out how objects in a game environment like these:

  • A reward Chest
  • A mana depleting/replenishing zone
  • sudden stormy winds in a certain direction

should affect other entities' (player's) properties like:

  • Inventory
  • Health/mana values
  • add a force on the entity in a certain direction.

When the above such interactions occur, I'm thinking of using an event bus as follows:

  • The player interacts with a script on the chest and an event is raised containing the chest content via the environment manager. The player Manager (entity manager) should subscribe to this event and update accordingly.
  • In the case of mana zones, these zones can communicate the interaction to the environment manager which can raise the event which is already subscribed by the player manager.
  • similarly, force magnitude and direction can be communicated.

Some important points I'm keeping in mind:

  • These event types can be reused in most cases, e.g., all health-related interactions can be communicated via a single event type, all physics (rigid body) related interactions can be another type. This will probably keep the number of events type low.
  • The environment entities can choose to raise or player entities can choose to respond to an event.
  • This would be a local event bus that is open to the Core game system only. Trying to keep these events away from other systems.

I wanted to know what is generally used for this purpose in the game industry. Will this be overkill? Is there a better approach that handles all such interactions keeping the code entities decoupled from each other?

\$\endgroup\$
0
2
\$\begingroup\$

The approach and some evolutions / pitfalls

Fairly standard. To give your approach a handle of sorts: you want to centralise most or all interactions to go through some high level (if not top level) controller, say Environment, which reduces coupling. We'll call it something like "top level interactions mediator / intermediary / proxy". See associated design patterns.

The problem comes in when that top level, generalised controller Environment becomes too cluttered, which will usually happen quickly in such a general class. This is where you begin factoring Environment into new subsystems, delegating its responsibilities further down the control tree or hierarchy.

For example, if trading is a possiblity, then Environment, which may receive a message from a player requesting to trade, may delegate these messages down to a TradingSystem which acts as intermediary for the exchange of items between the two entities in question, which could be actual trading, looting a corpse, or pickpocketing, depending on the parameters in that message; this would probably be reflected in a similar UI between the three styles of interaction. TradingSystem may fire a message when that UI closes, indicating that the interaction is complete, which is picked up by Environment so that it can, for example, ensure that corpse can't be looted again, or even remove the body altogether once looted. TradingSystem can delegate control down, even further.

What we typically don't want is TradingSystem having a reference back up to its controller Environment. This increases coupling, and can make it difficult to trace what is controlling what, since subordinate controllers can (via method call) directly cause a parent controller to react, rather than requesting an action on part of a parent by notifying them via event / message / signal - you suggested choose to raise or player entities can choose to respond to an event - especially true for higher level controllers which should never have to listen to subordinates.

EDIT re question about messaging coupling The Observer Pattern, AKA pub-sub, loosens coupling in the following way: Publisher will have a list of Subscribers to be notified. These references are "loose" because they refer to type Subscriber which comes from a generic list of Subscribers which the Publisher holds. Publisher thus has no idea what the actual, concrete types (such as TradingSystem or Environment) these objects are, so it cannot call public methods on them, meddle with their public members, etc. And because the Publisher-Subscriber is intrinsically limited in functionality, it should remain the same throughout development. So no need to worry about these Subscribers changing and breaking Publisher code.

Will this be overkill?

Not really, but...

I'd always take the simplest approach for now, until that starts to get in the way of efficient development. Then I'd start formulating a plan as to how to solve the problem, systematically. As this plan is crystallising in my mind, and assuming the project is not on a schedule e.g. for a client where other tasks take priority, I'd tie up loose ends on current tasks, merge into the base branch, create a new branch off this base, and implement the planned solution in full.

I would not try to preempt what those problems might be as that is nearly always a waste of time and effort. It may be better to get started on making your game and do the simplest thing that works (for example, direct method calls or a modifying a globally-accessible array of message slots you can read and write as and when), for the time being.

Conclusion

It's good to stay on top of things, and working in "difficult" code can be tedious, but sometimes it is worth the wait to see all the potential ways in which you have problems with a given (sub)system, and the ways in which you could solve them all at once, so that when you finally do fix them, you do so as effectively and universally as possible for the current stage of development.

In the meantime, do the simplest thing that works.

\$\endgroup\$
2
  • \$\begingroup\$ "don't want is TradingSystem having a reference back up to its controller Environment" But Environment can provide some kind of interface to SubSystems So that subsystems can communicate back to other Entities via event/message/signal? \$\endgroup\$ – Sarthak_ssg5 Jun 6 at 17:22
  • \$\begingroup\$ @Sarthak_ssg5 Yes, usually this is executed as the Observer Pattern, which reduces coupling down to just a simple interface. I will clarify in more detail inthe answer. \$\endgroup\$ – Engineer Jun 6 at 19:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.