I’m trying to wrap my head around the best way to structure some code, and could use some suggestions as after many hours thinking about this I feel like the gaps in my knowledge are letting me down.
I have a whole section of my game where the player can perform a large number of different kinds of actions which do various things from changing the properties of existing objects/actors to creating new objects/actors. I want all of these actions to be undoable/redoable. To this end, I am using the Command pattern (Command · Design Patterns Revisited · Game Programming Patterns) to encapsulate every player action in an object that records state, so that it can be undone.
I then have a class for my CommandStack, which keeps track of these objects, and has for example this function which takes a new command and handles it:
CommandStack->AddCommand(UCommand* NewCommand);
Every command could be done one of two ways: (1) with a 2D UMG widget, or (2) with a 3D VR widget. Whichever way is used, on pressing the button a new Command object is created with the appropriate parameters, which then needs to be sent to the CommandStack.
This is where my knowledge of efficient/standard practices for good OOP structure breaks down.
My initial thought was to have a central Controller class (AActor derived?) which has many subsystems as components, such as the CommandStack (along with other systems like the SaveSystem for example). So every UI element would need a reference to the Controller, such that when a button is pushed it does something like this:
USetHeightCmd* NewCommand = NewObject<USetHeightCommand>(this);
NewCommand->SetPreviousValue(Widget->GetValue());
NewCommand->SetCurrentValue(Widget->GetInput());
ControllerRef->CommandStack->AddCommand(NewCommand);
But this means that every widget needs a reference to the Controller actor/object, so either needs to be given that reference on spawn, or has to get it through GetAllActorsOfClass for example. I suppose there’s nothing wrong with that, and it will work, but it seems clumsy and too tightly coupled to me, but I don’t know what the alternative should be. Something involving delegates perhaps (can’t say I totally understand delegates yet)?
I’ve been running into this issue more and more as I’m trying to structure everything, and while I totally get (and appreciate) keeping systems separate so everything is more modular and maintainable, I’m struggling to understand how to link all these things together without just making sure everything has a reference to everything else.
What are the correct/elegant ways to connect different systems like this?