Language…
6 users online: Danik2343, DinoMom, Firstnamebutt, masl, Saibot1997, Zavok - Guests: 215 - Bots: 330
Users: 64,795 (2,380 active)
Latest user: mathew

C++ Object Management Problem

I'm trying to make a game in C++. The game has lots of objects that are supposed to interact with each other, and I'm having trouble trying to manage them.

Say we have this set of objects.



The arrows indicate pointer members to other objects. M is the master object, and all objects must be reachable from it.

Now, let's say I wanted Object 1 to query Object 2. How could I do that? Object 1 doesn't know about Object M or Object 2, and there's a chance Object 2 may not exist yet. The easiest way I can think of to implement this is to have every object in the game have a pointer leading back to object M. Does that sound like a good idea?

Click the character on the right side of my layout to visit my Discord server and discuss and play and look at and get updates and sneak peeks of the games and other things I'm making.

The authors of these 2 My Little Pony fan games have removed their games from the Internet.
Rise of the Clockwork Stallions has been updated! Download My Little Pony: Rise of the Clockwork Stallions DX: Director's Cut and My Little Pony: Magic Shards now! Spread this link!

Well, first of all, what exactly are you trying to achieve with the current structure? Like, why specfically did you decide to go with this implementation of a "master object" that has multiple children? It seems a bit over-complicated to me. In the most straight-foward case, you would manage your objects by simple having a vector or an array with pointers to each of them that you would then iterate over every frame. While hierarchical game objects are pretty common in game enginges (both Unity and Unreal Engine use them), I'm not sure if they are what you are going for here.

In any case, if you do have a good reason to use the current structure, then what you're looking for is "how to traverse a tree", because the structure you have is pretty much just that. The master object in your example is the root of the tree. A tree's root must always be known, otherwise traversing it is impossible. This doesn't necessarily mean that every object should have a pointer to M (although if you're really trying to do hierarchical game objects, then it might be a goood idea for every object to have a pointer to its immediate parent). In the simplest case, you would just have a function "getRoot()" that would return M and was accessible by every game objects.

Regarding your question on how to search for objects in this structure, well, first of all, every game object needs to have a unique identifier. Let's call it "uniqueId". This can be whatever works best for you. It could simply be a string (this is pretty much what Unity and Unreal Engine are doing), but if you want the best performance, it could also be a magic number. The only thing that matters is that it's unique and identifies your objects. Next, you need to use recursion to traverse your tree. Using the names suggested above, this could look something like this:

Code
GameObject* findObject(GameObject* root, std::string uniqueId)
{
	if (root->uniqueId == uniqueId)
	{
		return root;
	}

	for (size_t i = 0; i < root->children.size(); ++i)
	{
		GameObject* foundObject = findObject(root->children[i], uniqueId);

		if (foundObject != nullptr)
		{
			return foundObject;
		}
	}

	return nullptr;
}

GameObject* findObject(std::string uniqueId)
{
	return findObject(getRoot(), uniqueId);
}

// [...]

GameObject* foundObject = findObject("Object1");

if (foundObject != nullptr)
{
	// Do something with the found object
}


As you can see, the function can return nullptr if an object isn't found, which answers the second part of your question, so you would always have to check for nullptr when searching for an object.
Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!
Originally posted by RPG Hacker
Well, first of all, what exactly are you trying to achieve with the current structure? Like, why specfically did you decide to go with this implementation of a "master object" that has multiple children? It seems a bit over-complicated to me. In the most straight-foward case, you would manage your objects by simple having a vector or an array with pointers to each of them that you would then iterate over every frame.

Well, if you see a problem with the whole structure, feel free to point that out. Thanks for saying that.

Click the character on the right side of my layout to visit my Discord server and discuss and play and look at and get updates and sneak peeks of the games and other things I'm making.

The authors of these 2 My Little Pony fan games have removed their games from the Internet.
Rise of the Clockwork Stallions has been updated! Download My Little Pony: Rise of the Clockwork Stallions DX: Director's Cut and My Little Pony: Magic Shards now! Spread this link!

Well, as mentioned, it kinda depends on what exactly your end goal is. I assume you just want to process a bunch of objects inside a level? In that case, I would go with my suggestion above and just use an std::vector<GameObject*> containing pointers to all your spawned game objects. You then just have to iterate this vector once per frame. If you need anything more complex (like hierarchical objects), I need more details so I can recommend a different solution.
Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!
All right, here's my game's exact structure. What I'm trying to make is an RPG completely from scratch using just C++ and a C++ library called Simple DirectMedia Layer.

Object M is an object called State Handler. It contains a vector of pointers to State objects. I'm using a state stack system, so the state at the top of the stack gets the most attention. Each state can contain pointers to whatever objects the state needs.

The Explore State contains a Map Manager. The Map Manager contains a Map as well as controls to do stuff with the Map and the things inside the Map. The Map contains a vector of the Entities in the Map such as the player, people, treasure chests, and other interactable objects. The Map also contains a vector of Triggers on the map. Each Trigger contains an action detailing what to do when you step onto or interact with the trigger tile.

The Menu State gets pushed onto the state stack when you press the pause button while in the Explore State, and it gets popped off the stack when you press the cancel button. The Menu State contains a UI Manager. The UI Manager contains several windows, or Panels as my game calls them, as well as controls to do stuff with the UI elements. The Menu State object draws text into several of these windows, but one of them contains a list of choices, or a Choicebox as my game calls it. The choices in the menu will push more Menu States to the state stack such as an Item Menu State or an Equipment Menu State. Each choice should also contain an action detailing what to do when you select it. There might also be another action on what to do if you highlight it.

Here's my big problem. Actions should be EXTREMELLY flexible. They should be able to call any member function of any object in the game, but they're at the end of my hierarchal structure, so my way of linking the Actions up with the objects they're supposed to modify is extremely messy. I think if they just contained a pointer to the State Handler, I could link the Actions up to their objects easily.

Click the character on the right side of my layout to visit my Discord server and discuss and play and look at and get updates and sneak peeks of the games and other things I'm making.

The authors of these 2 My Little Pony fan games have removed their games from the Internet.
Rise of the Clockwork Stallions has been updated! Download My Little Pony: Rise of the Clockwork Stallions DX: Director's Cut and My Little Pony: Magic Shards now! Spread this link!

Alright, now I'm having a clearer picture of what you actually want. In the opening post you only spoke of "objects interacting with one another", so naturally, I assumed you meant game objects in a game world.

You've mentioned a state stack. I think these are used at least somewhat commonly in games (have seen it being used in at least one major title I worked on). However, in your sample picture, you show a structure that looks more like a tree than a stack. How comes? In an actual state stack, states would be layered directly on one another and you would only have a single top-most state at all times. Stacks are usually pretty simple in structure, unlike trees, so maybe that could be a hint that you are trying to overcomplicate the solution.

Also you mentioned that you want arbitrary objects in the stack to be able to communicate with one another. Why is that? It's a bit difficult to comprehend. For example, let's say you had a "main menu" state, then above that an "in-game gameplay" state and on top of that a "pause menu" state. You're saying you want the "pause menu" state to be able to communicate with the "main menu" state, for example? Why is that? I don't see a clear benefit, and it seems like a dangerously over-flexible system that could easily lead to problems when not handled super carefully. I'd say in a typical state stack, state objects should only ever be able to directly communicate with their immediate parent, so getting a message from a hypothetical object C to a hypothetical object A would require passing the message throubh object B first.

While I currently don't quite understand how you plan to utilize a flexible system like this, if you do have a need for it, what you're probably looking for is called an "event handler". Basically, there should be some global object receiving and handling events. Every single one of your state objects could send events to this handler. Then each frame, this event handler would go through its list of events and traverse the state stack, passing them to every single state along the way, until either a single one responds to it or it has run through all states.

For example, object C could send an event "Event_IJustDidSomethingCool", and then during event handling, object A (among others) would get the event "object C just sent Event_IJustDidSomethingCool". It could then either ignore the event or decide "WOW, this is super relevant to me, I should probably do something!". This "something" could be whatever you need. The state could just manage some internal stuff, but it could also go on to send an event of its own (like a response to object C, for example). Anyways, it should end with object A communicating to the event handler "Thanks, I handled this event", which should make the event handler clear the event from its queue, no longer sending it to any other states.

That's a very typical event system, and in games, something like this is very commonly used for UI, especially for input handling. Though in that case, it's not really multiple UI objects communicating with one another, but rather an extern input handler getting the player's input and then sending events to all UI objects until a single one decides to respond. This also answers your question on what happens if a state object doesn't actually exist in the stack: nothing at all. The event is simply sent to all existing state objects and ignored by all of them, causing nothing to happen at all.
Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!
Originally posted by RPG Hacker
You're saying you want the "pause menu" state to be able to communicate with the "main menu" state, for example?

No, I'm not doing that. That's not going to happen.

Click the character on the right side of my layout to visit my Discord server and discuss and play and look at and get updates and sneak peeks of the games and other things I'm making.

The authors of these 2 My Little Pony fan games have removed their games from the Internet.
Rise of the Clockwork Stallions has been updated! Download My Little Pony: Rise of the Clockwork Stallions DX: Director's Cut and My Little Pony: Magic Shards now! Spread this link!

Then can you define more clearly what you mean when you say that every action should be able to call any method of any other object? Maybe with a concrete usage example?
Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!
I don't think I even know fully, but I think Actions are going to interact with objects on the top state or the State Handler.

For example, the Action for a Trigger on the Map will warp the player to a different spot on the Map. This Action is changing an Entity on the Map in the Explore State, which is the state on the top of the stack.

The Action corresponding to selecting the "Items" option in the menu should tell the State Handler to push a new state called Item Menu State to the state stack.

Click the character on the right side of my layout to visit my Discord server and discuss and play and look at and get updates and sneak peeks of the games and other things I'm making.

The authors of these 2 My Little Pony fan games have removed their games from the Internet.
Rise of the Clockwork Stallions has been updated! Download My Little Pony: Rise of the Clockwork Stallions DX: Director's Cut and My Little Pony: Magic Shards now! Spread this link!

I'd say your use case is simple enough then that you don't really need a complex and flexible solution like that. For example, if you explore the map and flip a switch and want to have something on the map react to the switch, both things are part of the explore state, which should still be active, so you don't really need to communicate between states. If if you're in the pause menu and select the "items" option, all you probably want to do is push the "items" state onto the state stack, which again is something that the pause menu state itself can do, it doesn't really need to communicate with any other states. So I think going with just a simple solution where states can only commmunicate internally, as well as maybe with their immediate parent, shouls suffice for you. It's generally a good idea to always start with a simple solution and only implement a complex solution once you know you'll need it.
Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!