- Home /
What options do I have for firing 'events' at a specific time? (Co-routines, polling, any others?)
I have an internal game calendar, tracking dates/month/year (in the game, not real-time) as well as a generic 'time since game began'. I have C# objects (not monobehaviours) that I need to fire at a specific time. For example, Object1 is created on 'Sunday, 1st January' but when the internal calendar reaches 'Monday, 9th January', I need code in Object1 to run. Object2 might be created on 'Sunday 1st January' as well, but won't fire till 'Thursday 16th' February'.
Currently, I'm using a co-routine to run the calendar itself, and I'm now looking for options on how to efficiently fire code from these objects. I know I could do it by running each object on a new co-routine and yielding, but I'm not sure I like the idea of the overhead the co-routine will create, plus it will create headaches if game time is paused as I'd have to go and pause each of the co-routines for however many objects are alive.
The only other way I know is through standard polling (ie. every time the date changes, run through the list of all objects to see if they have reached the point they need to run), but that feels like a lot of polling. Are there any other options out there?
Answer by allenallenallen · Dec 26, 2016 at 11:33 AM
So after some quick thinking, I have an idea.
Say you have the information (1. When to call 2. What to call 3. How to call) stored as a new class perhaps. You add all the future planned events into a list of that new class. Sort them in order of time.
Now whenever the time changes, you only need to check the first item of the list.
If the time doesn't match, then we don't do anything.
If the time matches, then fire off whatever you need to do for that event. Then remove that item from the list.
If you need to have the option of letting the user skip a whole bunch of in-game time, then just check after the time skip. Iterate through the list, do what needs to be done for the events, and then remove them from the list. Do it until you meet an event that will execute in the future.
Which means the amount of checks you need to do per time change is:
1 <= N <= number of events that need to be executed after time change
Whenever you need to add a new future event to the list, just iterate through the list and insert at the correct index after comparing the time.
Should be pretty easy to manage or even export to a file if you need to since it's just a single list. It's flexible too since it doesn't depend on anything. It's unaffected by game pausing and time skipping.
I hope I made sense. You seem like you know more about C# compared to the average user on here, so I didn't really go into much detail. I'll explain more if you need me to.
Yup, you made sense :D Actually, I've been messing around in C# on and off for over a year in Unity, but I'm much more familiar with Java. Thanks though!
It definitely looks like your way would definitely cut down on the calls I need to make each time change. The concern I do have would be regarding the sorting each time you add to the list. At this point, I'm not sure how frequently events will be firing and sorting is fairly expensive operation. Otherwise, it could be done with a Priority Queue perhaps, but I'm not sure how efficient that will be. Obviously, if events are only infrequent then the complexity is irrelevant, but there's a chance they'll be happening with a fairly high frequency. Any thoughts on that?
Sorting only needs to happen once when or after you add a new event(s). The whole list is always sorted so I don't think sorting at any point of time change will take a long time even if the list gets bigger.
I guess you can achieve the same thing with a Priority Queue but the sorting will take the same time. So basically the same.
-------------------- // Just came up with an idea as I was writing this... lol
Oh and I just thought of a way to $$anonymous$$imize the number of sorting we need to do. The reason we need to sort is that we need the earliest time of an event, right? And the reason we need the earliest time of an event is so we can execute stuff during that specific time change.
For now, we are sorting after insertion of new events at the end of that time change. But it could be another in-game year before the earliest event executes. We are basically sorting for no reason.
So the idea is that we have a variable that keeps track of the earliest time for event execution. We can then compare the execution time of a newly inserted event to the variable. If it's earlier, then we update the variable. We just insert that event at the very end of the list.
Now if the in-game time matches the variable, we finally sort the list. Then we do the stuff I wrote in the first post and fire off the events.
Now we can insert as many events as we want per time change or throughout the in-game time and only need to sort ONCE right before we fire the earliest event(s).
Our old method:
Let's say all events will execute at time 5.
Insert 2 events at time 1. Sort.
Insert 1 event at time 2. Sort.
Insert 5 events at time 3. Sort.
Insert 1 event at time 4. Sort.
Execute at time 5.
New method:
Let's say all events will execute at time 5.
Insert 2 events at time 1.
Insert 1 event at time 2.
Insert 5 events at time 3.
Insert 1 event at time 4.
Sort event at start of time 5. Then execute.
That looks like it'll work! I'll implement it and get back to you :D Thanks!
Your answer
Follow this Question
Related Questions
how well does unity work for turn-based game time-type? 3 Answers
Two-mode jumping 1 Answer
rotation synced to dspTime? 0 Answers
How can I create an offset for the values of a sine wave over time. 1 Answer
Timed actions 1 Answer