I often hear that using Event Dispatchers is the best way to send notifications from BP Actors to the Level Blueprint.
Based on that idea, I have been managing things like weather intensity changes and Skylight visibility (on/off) inside the Level Blueprint.
I once heard that “things that affect the entire level should be managed in the Level Blueprint,” but in practice this approach has caused many problems.
Weather changes can be triggered from many different places in the scene, and each of those Actors needs to send notifications via Event Dispatchers. Sending the events themselves is not the main issue, but the problem is that the Level Blueprint must bind to all of these dispatchers.
Binding all events in Event BeginPlay feels undesirable, and not just because of performance concerns, but also because the number of bindings grows very large.
Binding and unbinding dynamically is also possible, but it becomes very inefficient when the game supports loading from the middle of a stage, since the correct bindings must be re-established depending on the starting point.
This makes the whole system feel overly complex and fragile.
In this situation, what would have been the better architectural approach?
How should global systems like weather and lighting have been designed instead?
How do you usually manage weather systems?
Is it better practice to create a dedicated Weather Blueprint Actor and place things like the Directional Light and Sky Light inside it, then communicate with it via Blueprint Interfaces?
There are multiple ways to approach such a system depending on the complexity of the project requirements and the knowledge base of the development (i.e. C++ vs BP).
You can use Event Dispatchers, Interfaces in BP for sure, but the question remains ‘What to call exactly, and how to organise it?’
For example, if you want to control Time/Date/Weather states, should you be creating an event dispatcher for each? or aggregate multiple operations in one node/function etc?
I prefer to build my own system in C++ as a GameInstace Subsystem (Accessible globally basically), but again, that system must reference the Daylight actor itself (whether it’s a BP or just a directional light), but if I had to go with BP, I’d go with reducing my events to the bare minimum, and just pass the values as JSON strings and filter them in a global BP (i.e. {“weather“ : “clear“}, {“time“ : “12:00“}, etc)
However, you might want to check the brilliant ‘Ultra Dynamic Sky’ Game System on FAB, it has hundreds of params with very useful functions accessible globally in the game
In short, there’s no escaping Interfaces and event dispatchers, it’s a question on how to utilise them efficiently, I hope this helps.
I almost never use the Level Blueprint. Make a separate actor BP to manage this stuff. Or use GameState if it fits (GameState is a convenience actor provided for multiplayer networking the um, game state). It’s hard to re-use logic in the Level BP… if you make a specialty actor, you can just drag it to a new level.
For accessing one-off singleton actors in a level, using ‘GetActorOfClass’ is fast if you need to access a WeatherManager or whatever. Cache the ref if you need it often/per tick.
If you NEED an interface for this, sure. Honestly it may not be necessary. Interfaces are good for abstracting away and reducing coupling, but can also be a bit of a speed bump. For a global system that is always in memory, may not be the place. Depends on your design.
Same with events… if all your events are aimed at the weathermanager and nothing else, setting up multicast delegates and bindings may be extra error-prone work and upkeep vs just calling WeatherManagerRef->SetNewWeather(blah, blah). Totally depends on your game.
Using a subsystem like IAvArt points out is a really clean way too, I also prefer for a lot of non-networked systems. ie DialogueSubsystem. If youre doing c++ they are worth learning and really easy to set up.
i would suggest this, just easy to copy and paste between levels, it can register itself with a manager like the GameState for easy access and can replicate if you decide you want multiplayer.