Forum begins after the advertisement:
[Part 21] Fixing infinite loops for mobs spawned by EventManager
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 21] Fixing infinite loops for mobs spawned by EventManager
- This topic has 2 replies, 2 voices, and was last updated 3 weeks, 2 days ago by kyle.
-
AuthorPosts
-
October 22, 2024 at 4:31 pm #16138::Thanks to users ChoomGo for bringing the glitch up and Ronin for giving the suggestion to change it into an ‘if’ statement instead!
Hi all! Recently an issue about the
EventManager.cs
script from our Part 21 of the Vampire Survivor series causing the game to freeze was brought up. Here’s a post detailing what caused the script to freeze the game and a solution to the issue.The cause:
In the
EventManager.cs
script, we select a random available event to play using theGetRandomEvent()
function.public EventData GetRandomEvent() { // If no events are assigned, don't return anything. if (events.Length <= 0) return null; // Get a list of all possible events. List<EventData> possibleEvents = new List<EventData>(events); // Randomly pick an event and check if it can be used. // Keep doing this until we find a suitable event. EventData result = possibleEvents[Random.Range(0, possibleEvents.Count)]; while (!result.IsActive()) { possibleEvents.Remove(result); if (possibleEvents.Count > 0) result = events[Random.Range(0, possibleEvents.Count)]; else return null; } return result; }
In the function, there is a
while
loop, and what thewhile
loop was intended to do was to cycle through the list of all possible events, pick a random event (result
), and check if that event is active. If the event isn’t active, we remove it from the list of possible events and if there are still events left in the list, we choose a random remaining event to play.However, there is an issue with the
while
loop’s condition,!result.IsActive()
.IsActive()
is a function inEventData.cs
that returns a bool that determines whether the event should be removed in theEventManager.cs
script or not.public bool IsActive() { if (!GameManager.instance) return false; if (GameManager.instance.GetElapsedTime() > activeAfter) return true; return false; }
In the function, it will return false either if there is no GameManager present in the scene, or if the event’s activeAfter time has not been passed (i.e. if activeAfter is 60, the event cannot be activated until 60 seconds have passed).
The latter is the outcome that causes the Event Manager to freeze the game, as if the chosen event’s activeAfter has not passed yet,
while (!result.IsActive())
evaluates towhile (True)
. If there are still possible events after removing the inactive event, the if statement inGetRandomEvent()
selects another random event from possibleEvents without exiting the loop. This causes an infinite loop and hence freezes the game.The fix:
Instead of using a
while
loop to remove events that are not active yet, we can use aforeach
loop to only add events that are active into thepossibleEvents
list.public EventData GetRandomEvent() { // If no events are assigned, don't return anything. if (events.Length <= 0) return null; // Create a new list to populate with possible Events List<EventData> possibleEvents = new List<EventData>(); // Add the events in event to the possible events only if the event is active foreach (EventData e in events) { if (e.IsActive()) { possibleEvents.Add(e); } } // Randomly pick an event from the possible events to play if (possibleEvents.Count > 0) { EventData result = possibleEvents[Random.Range(0, possibleEvents.Count)]; return result; } return null; }
We just need to replace the old
GetRandomEvent()
with this new one and that’s it! Hopefully your newEventManager.cs
script should no longer freeze the game!has upvoted this post. October 24, 2024 at 5:23 pm #16163October 31, 2024 at 3:51 pm #16213 -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: