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 1 month ago by kyle.
Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #16138
    kyle
    Level 7
    Moderator
    Helpful?
    Up
    1
    ::
    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 the GetRandomEvent() 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 the while 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 in EventData.cs that returns a bool that determines whether the event should be removed in the EventManager.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 to while (True). If there are still possible events after removing the inactive event, the if statement in GetRandomEvent() 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 a foreach loop to only add events that are active into the possibleEvents 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 new EventManager.cs script should no longer freeze the game!

    has upvoted this post.
    #16163
    정춤고 (ChoomGo)
    Level 13
    Former Patron
    Helpful?
    Up
    3
    ::

    Amazing Work!

    and 1 other person have upvoted this post.
    #16213
    kyle
    Level 7
    Moderator
    Helpful?
    Up
    0
    ::

    No problem! Sorry, had to update the code again to add an if statement that checks whether possibleEvents is greater than 0, since if it’s empty there will be a ListIndexOutOfRange error if there are no possibleEvents for the Random function to choose.

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: