For example, once time reaches 16pm I want to call an arbitrary event in the level blueprint. How can this be done? Surely this is what day sequence actors are intended for, unless I’m misunderstanding.
Should I just check the day sequence time every tick? That seems rather excessive to me performance wise, especially if many things happen at different times, it’ll just be branch spaghetti. Any ideas?
The other option is binding to an event dispatcher. For example, you can use an “UpdateWorldTime” function on the GameInstance that is called from a function set by timer on the GameMode every ~second. Then you can bind NPC BehaviorTree tasks, Spawners, etc. to the GameInstance dispatcher where necessary. This way you avoid using tick.
is it expensive to run code every tick for checking time-of-day triggers?
how can I avoid the code becoming a big mess when I have many triggers?
In general, if you move the position of the sun every tick based on the day sequence, something is already ticking every frame based on that, so adding your own tick that does very little for this one actor once a frame isn’t going to show up on a profile. (Ticks that do a lot, and ticks added to hundreds, or thousands, of actors, may show up on a profile) So, no, it’s not a big deal from a performance point of view.
To structure the code such that it’s not a big mess, I would probably have a list of callbacks (or events?) that should trigger “on or after” a certain time. This list stores a tuple of “time, callback” which could be a struct or an object or a map or whatever you want.
I would have an actor for “things triggers at time X” and that actor would add its callback to that list. (You could use the get-actor-of-class mechanism to find the level sequence for example) The function to add an element to the list should also make sure the list is sorted. Then, in the tick callback, you simply check:
is the list empty
if so, do nothing
else get the first pending callback
is the time for this pending callback before or at “now” in the sequence?
if no, do nothing
remove the first pending callback from the list, and call the callback function
You may additionally want a second callback (or event) on your sequence that fires each time it loops, where your “do thing at time X” actor can register so it re-registers itself when the day starts over.