Forum begins after the advertisement:


[Part 21] Game freezing caused by RingEventData.cs

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [Part 21] Game freezing caused by RingEventData.cs

  • This topic has 13 replies, 4 voices, and was last updated 1 month ago by kyle.
Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #15850
    정춤고 (ChoomGo)
    Level 13
    Participant
    Helpful?
    Up
    2
    ::

    I added the code for this part and ran the build, but Unity itself keeps freezing. No error code appears, and it freezes immediately, so there doesn’t seem to be a way to solve it. Is there anyone who might be experiencing something similar to this?

    Terence’s suggestion is as follows:

    is causing this, you will eventually come across an object that, after deleting, will allow the game to continue running. Then you will know which script is causing this, and you can post it on the forums for us to have a look for you.

    I did that and found that the issue is with RingEventData.cs.

    RingEventData.cs
    1.57 KB • 44 extracted lines

    Formatting may be inconsistent from source.

    using UnityEngine;
    
    [CreateAssetMenu(fileName = "Ring Event Data", menuName = "Datas/Event Data/Ring")]
    public class RingEventData : EventData
    {
        [Header("Mob Data")]
        public ParticleSystem spawnEffectPrefab;
        public Vector2 scale = new Vector2(1, 1);
        [Min(0)] public float spawnRadius = 10f, lifespan = 15f;
    
        public override bool Activate(PlayerStats playerStats = null)
        {
            // Only activate this if the player is present.
            if (playerStats)
            {
                GameObject[] spawns = GetSpawns();
                float angleOffset = 2 * Mathf.PI / Mathf.Max(1, spawns.Length);
                float currentAngle = 0;
                foreach (GameObject g in spawns)
                {
                    // Calculate the spawn position.
                    Vector3 spawnPosition = playerStats.transform.position + new Vector3(
                        spawnRadius * Mathf.Cos(currentAngle) * scale.x,
                        spawnRadius * Mathf.Sin(currentAngle) * scale.y
                    );
    
                    // If a particle effect is assigned, play it on the position.
                    if (spawnEffectPrefab)
                        Instantiate(spawnEffectPrefab, spawnPosition, Quaternion.identity);
    
                    // Then spawn the enemy.
                    GameObject s = Instantiate(g, spawnPosition, Quaternion.identity);
    
                    // If there is a lifespan on the mob, set them to be destroyed.
                    if (lifespan > 0) Destroy(s, lifespan);
    
                    currentAngle += angleOffset;
                }
            }
    
            return false;
        }
    }

    The code above is what part 21 is about. Below is the addition of a code that gathers in the middle with the help of chat GPT. The same freesing occurred in both scripts.

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    [CreateAssetMenu(fileName = "Ring Event Data", menuName = "Datas/Event Data/Ring")]
    public class RingEventData : EventData
    {
        [Header("Mob Data")]
        public ParticleSystem spawnEffectPrefab;
        public Vector2 scale = new Vector2(1, 1);
        [Min(0)] public float spawnRadius = 10f;
    
        [Header("Convergence Data")]
        [Min(0)] public float convergenceTime = 5f;
        [Range(0f, 1f)] public float convergenceRatio = 0.9f;
        [Min(0)] public float disappearDelay = 0.5f;
    
        public override bool Activate(PlayerStats playerStats = null)
        {
            // Only activate this if the player is present.
            if (playerStats)
            {
                GameObject[] spawns = GetSpawns();
                float angleOffset = 2 * Mathf.PI / Mathf.Max(1, spawns.Length);
                float currentAngle = 0;
                List<GameObject> spawnedEnemies = new List<GameObject>();
    
                foreach (GameObject g in spawns)
                {
                    // Calculate the spawn position.
                    Vector3 spawnPosition = playerStats.transform.position + new Vector3(
                        spawnRadius * Mathf.Cos(currentAngle) * scale.x,
                        spawnRadius * Mathf.Sin(currentAngle) * scale.y
                    );
    
                    // If a particle effect is assigned, play it on the position.
                    if (spawnEffectPrefab)
                        Instantiate(spawnEffectPrefab, spawnPosition, Quaternion.identity);
    
                    // Then spawn the enemy.
                    GameObject s = Instantiate(g, spawnPosition, Quaternion.identity);
                    spawnedEnemies.Add(s);
    
                    currentAngle += angleOffset;
                }
    
                // Start the convergence coroutine
                playerStats.StartCoroutine(ConvergeAndDestroyEnemies(spawnedEnemies, playerStats.transform));
            }
    
            return false;
        }
    
        private IEnumerator ConvergeAndDestroyEnemies(List<GameObject> enemies, Transform playerTransform)
        {
            float elapsedTime = 0f;
    
            while (elapsedTime < convergenceTime)
            {
                foreach (GameObject enemy in enemies)
                {
                    if (enemy != null)
                    {
                        Vector3 directionToPlayer = playerTransform.position - enemy.transform.position;
                        float distanceToMove = directionToPlayer.magnitude * (convergenceRatio * (elapsedTime / convergenceTime));
                        enemy.transform.position += directionToPlayer.normalized * distanceToMove * Time.deltaTime;
                    }
                }
    
                elapsedTime += Time.deltaTime;
                yield return null;
            }
    
            // Wait for the specified delay before destroying
            yield return new WaitForSeconds(disappearDelay);
    
            // Destroy all enemies
            foreach (GameObject enemy in enemies)
            {
                if (enemy != null)
                {
                    Destroy(enemy);
                }
            }
        }
    }
    and 1 other person have upvoted this post.
    #15851
    정춤고 (ChoomGo)
    Level 13
    Participant
    Helpful?
    Up
    0
    ::

    Unity doesn’t stop if I don’t put ring event data in Enemy spawner. Unity stops when I add it.

    #15854
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Can you remove the line that starts the ConvergeAndDestroyEnemies() coroutine and see if that fixes the freezing? The issue seems to be that one of your loops are running forever.

    #15897
    정춤고 (ChoomGo)
    Level 13
    Participant
    Helpful?
    Up
    0
    ::

    Unity stops even when I remove the code and add a ring event. I don’t think this cs file is the cause of the stop. I’m just guessing maybe there’s another cause.

    #15901
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    How about if you remove the entire loop in Activate()? Does it still crash?

        public override bool Activate(PlayerStats playerStats = null)
        {
            // Only activate this if the player is present.
            if (playerStats)
            {
                GameObject[] spawns = GetSpawns();
                float angleOffset = 2 * Mathf.PI / Mathf.Max(1, spawns.Length);
                float currentAngle = 0;
                List<GameObject> spawnedEnemies = new List<GameObject>();
    
                foreach (GameObject g in spawns)
                {
                    // Calculate the spawn position.
                    Vector3 spawnPosition = playerStats.transform.position + new Vector3(
                        spawnRadius * Mathf.Cos(currentAngle) * scale.x,
                        spawnRadius * Mathf.Sin(currentAngle) * scale.y
                    );
    
                    // If a particle effect is assigned, play it on the position.
                    if (spawnEffectPrefab)
                        Instantiate(spawnEffectPrefab, spawnPosition, Quaternion.identity);
    
                    // Then spawn the enemy.
                    GameObject s = Instantiate(g, spawnPosition, Quaternion.identity);
                    spawnedEnemies.Add(s);
    
                    currentAngle += angleOffset;
                }
    
                // Start the convergence coroutine
                playerStats.StartCoroutine(ConvergeAndDestroyEnemies(spawnedEnemies, playerStats.transform));
            }
    
            return false;
        }
    #15905
    정춤고 (ChoomGo)
    Level 13
    Participant
    Helpful?
    Up
    0
    ::

    I modified it to the code above, and Unity stopped again. I’ll restore it to the original code and then look again.

    #15909
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    The other possibility is that the issue is with the EventManager script. Your issue looks like it is an issue with one of your loops though, which makes me think that the while loop in ConvergeAndDestroyEnemies() is the most likely culprit.

        private IEnumerator ConvergeAndDestroyEnemies(List enemies, Transform playerTransform)
        {
            float elapsedTime = 0f;
    
            while (elapsedTime < convergenceTime)
            {
                foreach (GameObject enemy in enemies)
                {
                    if (enemy != null)
                    {
                        Vector3 directionToPlayer = playerTransform.position - enemy.transform.position;
                        float distanceToMove = directionToPlayer.magnitude * (convergenceRatio * (elapsedTime / convergenceTime));
                        enemy.transform.position += directionToPlayer.normalized * distanceToMove * Time.deltaTime;
                    }
                }
    
                elapsedTime += Time.deltaTime;
                yield return null;
            }
    
            // Wait for the specified delay before destroying
            yield return new WaitForSeconds(disappearDelay);
    
            // Destroy all enemies
            foreach (GameObject enemy in enemies)
            {
                if (enemy != null)
                {
                    Destroy(enemy);
                }
            }
        }
    #15919
    정춤고 (ChoomGo)
    Level 13
    Participant
    Helpful?
    Up
    0
    ::

    I deleted the displayed code. Still trying to add a code where monsters gather in the middle. Thank you for your kindness.

    #16027
    Ronin
    Level 19
    Participant
    Helpful?
    Up
    0
    ::

    I am also having this issue…

    #16034
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    I am also having this issue…

    Ronin, you’ll need to find out which parts of your code are causing the infinite loop which causes the crash. For starters, you can comment out the parts with while loops and see if the crash still happens.

    #16037
    Ronin
    Level 19
    Participant
    Helpful?
    Up
    2
    ::

    Thank you for the response, it seems to be related to this loop in the EventManager…

            while (!result.IsActive())
            {
                possibleEvents.Remove(result);
                
                if (possibleEvents.Count > 0)
                {
                    result = events[Random.Range(0, possibleEvents.Count)];
                }
                else
                {
                    return null;
                }
            }
    have upvoted this post.
    #16039
    Ronin
    Level 19
    Participant
    Helpful?
    Up
    1
    ::

    I changed the while loop to an if statement instead, this seems to have fixed the issue, events are now able to run without a crash.

    has upvoted this post.
    #16046
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Fantastic. Glad you managed to figure it out on your own.

    #16140
    kyle
    Level 5
    Moderator
    Helpful?
    Up
    1
    ::

    Hi! We’ve pinpointed the bug to the GetRandomEvent() function in the EventManager.cs script. The solution can be found in this post here – [Part 21] Fixes to the Event Manager Script.. Hope the solution manages to work for you all!

      1 anonymous person
    has upvoted this post.
Viewing 14 posts - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: