Is a C++ Hub a good idea?

I apologize but this will probably be somewhat rambly. My thinking is to have a Hub class that receives all events, from controllers, hits, overlaps, user events off the AI, and the GUI. As the events come in they are forwarded to the appropriate Actor to handle. The advantage is that only this Hub class will implement the Tick function. All other Actors and responses to events will be function calls from the Hub. Also, while the PC does activate the HUD by interacting in the game world, it seems weird to have the PC class manage the HUD, cleaner to have some Hub parse all events and send the relevant ones to a Hud class to manage. Lastly, it just seems an easier way of organizing and keeping track of stuff. And there is oh so much stuff to keep track of.

The problems I have are first, which class should Hub extend? Actor, GameMode, PlayerController.

The second is that UE5 seems very distributed, like muti-threaded, with each Actor having access to at least some events, and that introducing a Hub class might upset UE5 design. If I knew what that design was. Animations for example can be synchronized via speed, and that would be broken if a Hub class were to tell the Actor where it should be next tick.

You have two different ideas here:

and

You’re first idea can work out very well. Your second one is probably a bad idea.

You can sort of see your first idea in action as the GameplayMessageRouter in Lyra. I have some specific issues with it, but it’ll work as a point of reference that you can look at. It’s a centralized messaging system that everyone can register with to receive events and to broadcast them. Think of it like a big group of tons and tons of delegates, all with a common signature. Then you could have one class raise an event like “Unit Died” that anyone could respond to (maybe a scoring system or a telemetry system or another gameplay system). This is a great method to decouple systems from each other and make them only dependent on the event, and not who might raise that event.

Your second idea is a less good one. You don’t need a central system telling Actors to tick, the Engine already does this and is something that objects can do for themselves. You shouldn’t need an extra system telling Objects to do something they could figure out for themselves. The GameplayMessageRouter is for responding to changes in other systems, but not necessarily tight coordination between specific objects (like your sync’d animations example).

The GameplayMessageRouter is a WorldSubsystem. I have a version (from before Lyra was a thing) that is an Actor. I’ve also seen one where it’s an Actor Component (because it’s meant to support a more complicated routing system with multiple message systems).
The WorldSubsystem is definitely the easiest, the object is made for you and you have pretty easy global access.
The Actor is easy enough to make work and can be kept around if you’re using seamless travel.
I don’t have direct experience with the component version but it’s the most complicated since you now have to know which one you should use to broadcast your events.

Excellent answer. Thanks MagForceSeven.

The Tick thing. I’m not deep enough into what is required yet, but I am assuming that so long as the Actor class is responding to an event it does not also need to deal with ticking every cycle. Maybe a few Actors will need to do timing stuff as well, but maybe they can be handled by Kismet, I think, Timer functions.

Maybe, but the need to respond to events and the need to tick are orthogonal concerns. An Actor could do neither, it could do both. You could even tick to check something (polling) that you could be getting told through an event/callback. The need to do one doesn’t necessarily influence the need or not need to do the other.

It’s a reasonable place to start, for sure but ultimately (as with everything in coding) will be more nuanced than that. As long as you’re open to that when you need it, you should be fine.