0
\$\begingroup\$

I have a World class that currently only has one instance. It has data and methods that need to be accessed by all other game objects. Right now I'm hardcoding a reference to the global variable world in all of my methods, and this doesn't seem to be the right approach.

Another idea I tried was a dependency-injection-esque approach, where each object stores its own reference to the world object, but this clutters memory with unnecessary references, so I don't think this is the right approach either.

Another approach I tried was passing world as an argument directly into the method call, but this led to repetitive code as I was constantly passing world into any function that needed it.

A bit of research hasn't worked for me because it's hard to summarise my problem into a few words that can return Google search results. It seems this isn't a problem in the majority of applications, so I'm wondering if this is mainly a gamedev situation.

What is the best way to solve this problem?

\$\endgroup\$
5
  • \$\begingroup\$ Why not make it be a true singleton and have the class store a static reference to its only instance? You could then expose that. \$\endgroup\$ – Weckar E. Apr 15 at 1:56
  • \$\begingroup\$ There are basically two approaches I would consider in this case. The easiest and most obvious one is to use a Singleton design pattern (google this later for more good architecture ideas) as Weckar suggests. This should be the easiest to implement and have the least amount of changes to your current design. The more difficult approach would be to redesign your classes to create code modules that avoid as many outside dependencies as possible (IE you create Inventory, AI, Weapon, Car, etc modules) you may still need a singleton but it should help with organization. \$\endgroup\$ – Benjamin Danger Johnson Apr 15 at 2:06
  • \$\begingroup\$ @BenjaminDangerJohnson I've heard of the singleton pattern, but I'm not exactly sure what you mean by creating code modules that avoid outside dependencies. I tried to keep the question quite general in case it could be of use to others in the future, but my particular case is that I need to access terrain data to do a lot of actions, based on the object's current position. How do I store and access this data? \$\endgroup\$ – EnderShadow8 Apr 15 at 2:27
  • \$\begingroup\$ No problem, by code modules I mean separate files in a way that avoids too many dependencies. This way you can minimize the amount of direct object sharing and points of failure. For example, let's say you want to drop an item on the ground if a player tries to take it from a box and has no space, in this case instead of having your item directly access the world data to find a position to spawn itself you could instead have your item tell the player object to drop the item. With this kind of design you never have to worry about world data breaking the item system, only the player. \$\endgroup\$ – Benjamin Danger Johnson Apr 15 at 8:17
  • \$\begingroup\$ In my particular case, I'm doing tile based collision detection. Even if I have a separate function handleCollison or something, it still needs a reference from inside my object method. Otherwise, this is very similar to what I'm already aiming to achieve. \$\endgroup\$ – EnderShadow8 Apr 15 at 8:52
1
\$\begingroup\$

You are looking for an alternative to dependency injection. I'll offer you a perspective shift: The game world is external. You are just sending and receiving messages. It is not a great idea to have a dependency on something external that you can't control.

Wait. We are making games. And a game is a piece of software, it isn't a portal to another world. Or is it? (cue Jake Chudnow - Moon Men (instrumental), extended version to make sure it lasts while you read).

Hey Gamedev, Thereot here. And how do you handle things external to your game? For example, game input.


You need to access your input from your update code. And we want that code well delimited. Remember, don't mix concerns or responsibilities.

However, we have this problem of passing things around. We could have singletons, or do dependency injection. I have here a different solution: The input service will send messages.

That is, the game objects will have a sort of "inbox". A notification mechanism. For example, the service calls a method on them, or sets a property.

Since not every game object needs input, the service could have list of game objects that should receive the messages (call them observers, listeners, subscribers, fan club).

This approach can be applied for any services that deals with an external (or a let-us-pretend-external) input device. For example, we can use to handle actual messages from the network, or to handle collisions in our physics simulation.


But how would you handle output?

There are some services that that do output (physics, network, graphics, audio), and you need to tell them what to do. For example, you tell to the physics service to apply a force or a velocity.

However, we have this problem of passing things around, again. Well, I have another box for you: an "outbox". The game objects could publish messages for the services to pick up, where they describe what they want the service to do.

Those services already have a list of game objects that need to interact with them. So they could go over the list, and pick messages from the "outbox" of each game object.

We have a name for a message that describe what to do. We call it a Command.


I need to access terrain data to do a lot of actions, based on the object's current position. How do I store and access this data?

There are a lot of spatially aware logic that makes sense to handle as external to the core logic of the game. For example, you may need to find nearby game objects, or find a path to navigate the world. There are also collisions, and so on. And you would find a good idea to have dedicated data structures to handle that (e.g. grids, quad-trees, etc).

Perhaps for you, terrain is physics. For example, in a 3D game we could have a raycast downwards to check if the player avatar is on the ground, and what kind of ground. Or perhaps for you terrain is its own thing. For example, in a 2D game, you probably have a tile-map (or perhaps a texture) that you can query with some coordinates to get terrain information. Or it is a voxel game, and you just query the voxel.

When there is a collision (including the raycast contacting a different object), or when a game object moves to another tile, you can send a message.


What is the best way to solve this problem?

I don't know about best. But, the command pattern is a good counterpart for dependency injection.

Let us say you have a class that has a dependency. Your class calls a method on the dependency, and gets a return value. Ok, we are going to flip that around. Instead of calling a method we publish a command. Some time later, the "dependency" takes the published command. When it has a result, it calls a method in our class (or perhaps the command object includes a callback), which is the opposite of what we had before. Somehow we had your class call the other, now the other calls yours. The return value became a parameter. We left synchronous and arrived at asynchronous. And we left coupled and arrived at decoupled.

In fact, there could be one object taking the commands, or there could be multiple, or none.

This idea is a way to bring back the concept of passing messages that we had at the origins of object oriented programming.

Let us be honest, this is not free. You would be instantiating messages. If they are reference types, you would be making garbage, unless you pool them. As per dependencies, we have moved from A depends on B, to A and B depend on M, where M is the message type.

Of course, that is not the only way. I'll mention that you can use an actor model. An actor has in and out channels on which they do push and pull operations to communicate with other parts of the software (cough queues cough). In this case if you want something to happen in a different part of your system, push a message to the appropriate channel, on the other side an object can pull it some time later. "Queues decouple spacetime." -- Kain0_0 (source).

Make the above thread-safe, and parallelism becomes easier.

Since, Entity-Component-System has popularity in game development, I'll also mention that if you are doing an ECS sending a message could mean attaching a component to the entity for some another system to read it.

By the way, if you want, you can use an actual external device for communication. For example, one part writes to a file, and the other reads from the file. Hopefully a memory mapped file. Or it could be a network connection (and then you can start thinking about how to do a distributed system).


Remember that you can think about your architecture in terms of internal and external things, and passing messages between them. Then worry about the mechanism for that communication. Plus, often you can flip those around.

\$\endgroup\$
4
  • \$\begingroup\$ This also indirectly answered my other question about ECS - maybe it is the right path for me after all. \$\endgroup\$ – EnderShadow8 Apr 15 at 8:54
  • \$\begingroup\$ "And you would find a good idea to have dedicated data structures to handle that (e.g. grids, quad-trees, etc)." This is what I'm asking about - how do I reference these data structures? Do I hard code it into each method? Do I use dependency injection when it's really overkill? Do I pass it in as an argument to interested functions? \$\endgroup\$ – EnderShadow8 Apr 15 at 8:57
  • \$\begingroup\$ @EnderShadow8 some engines will have these references in a base class for all game objects and that's it. I believe I described an alternative. How do you handle input? It is common that engines have something like Input.IsKeyPressed("A"), and that is a Input that is referenced wherever. Did you solve that? Solve this the same way. \$\endgroup\$ – Theraot Apr 15 at 9:12
  • \$\begingroup\$ @EnderShadow8 Ok, the world. It is useful to able to query what things are nearby. For example, Ideally you would only render what is near the camera. And you would only check collision with nearby objects. If you need that, why not inject it? I removed a paragraph about how we went from globals to singleton to dependency injection, and that made our dependencies explicit, easier to track when we need to debug. If you don't want to inject it, and you don't want a reference in the base class, or any of that… I presented an alternative: Have the world call into the game object. \$\endgroup\$ – Theraot Apr 15 at 9:15

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.