Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

[Solved] C# need help with optimizing a script

Discussion in 'Scripting' started by clearrose, Feb 23, 2016.

  1. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    I have an script that returns my spawned objects back to a object pool when they hit a trigger located outside of the cameras view. But when they do return to the pool, each object generates a range from 68B - 108B worth of garbage per object. With the amount of objects that are returning at one time, I do get huge spikes go GC ranging from 1KB to 7KB. I need to eliminate the garbage generated by each object when they return to the object pool. Except I don't know exactly what in my script is causing the objects to create the garbage, so if anyone is willing to help solve the problem it would be greatly appreciated :).

    Note: I don't think this line of code is the problem, because i have it being called from another script for a special set of objects and i didn't get any GC spikes from that script:

    Code (CSharp):
    1. NewObjectPool.instance.PoolObject(SpawnedObject);
    Heres my profiler data:

    Screen Shot 2016-02-23 at 2.07.03 PM.png

    My script for returning the objects to the pool:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestoryOverTime : MonoBehaviour
    5. {
    6.     public GameObject SpawnedObject;
    7.     public bool IsVisible;
    8.  
    9.     public void OnTriggerEnter2D(Collider2D other)
    10.     {
    11.         if (other.tag == "NotVisible")
    12.         {
    13.             IsVisible = false;
    14.  
    15.             if (SpawnedObject.tag == "CoinHolder")
    16.             {
    17.                 Invoke ("ReturnObjects", 7.5f);
    18.             }
    19.  
    20.             else if (SpawnedObject.tag == "PowerUpHolder")
    21.             {
    22.                 Invoke ("ReturnObjects", 7.5f);
    23.             }
    24.  
    25.             else if (SpawnedObject.tag == "ObstacleHolder")
    26.             {
    27.                 Invoke ("ReturnObjects", 7.5f);
    28.             }
    29.         }
    30.  
    31.         else if (other.tag == "ObjectsAreVisible")
    32.         {
    33.             IsVisible = true;
    34.         }
    35.     }
    36.  
    37.     public void ReturnObjects ()
    38.     {
    39.         if (SpawnedObject.tag == "CoinHolder")
    40.         {
    41.             NewObjectPool.instance.PoolObject(SpawnedObject);
    42.         }
    43.  
    44.         else if (SpawnedObject.tag == "PowerUpHolder")
    45.         {
    46.             NewObjectPool.instance.PoolObject(SpawnedObject);
    47.         }
    48.  
    49.         else if(SpawnedObject.tag == "ObstacleHolder")
    50.         {
    51.             NewObjectPool.instance.PoolObject(SpawnedObject);
    52.         }
    53.     }
    54. }
    55.  
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    That's probably your Invoke calls. I'd replace them with something you write yourself and see if that fixes your garbage problem. A time-tracking variable with Update is pretty guaranteed not to produce garbage:
    Code (csharp):
    1. float returnObjectsAtTime = -1f;
    2. void Update () {
    3. if (returnObjectsAtTime != -1f && Time.time > returnObjectsAtTime) {
    4. ReturnObjects();
    5. returnObjectsAtTime = -1f;
    6. }
    7. }
    8. public void OnTriggerEnter2D(Collider2D other) {
    9. if (other.tag == "NotVisible") {
    10. //etc
    11. returnObjectsAtTime = Time.time + 7.5f;
    12. }
    13. }
    I noticed ReturnObjects has the same line in each if block - is that intentional? Why?
     
  3. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Thank you very much for the help. First thanks for pointing out:

    This was a mistake, probably left over from a previous version of the script. It has continuously evolved with the game over time.

    Second, did try your suggestion but it hasn't seemed to make a difference sadly. But I made a interesting discovery in the profiler while testing:

    Screen Shot 2016-02-23 at 4.00.37 PM.png

    Besides the script "DestoryOverTime" Anything using OnTriggerEnter2D seems to be creating excess garbage for each object that is entering a trigger. Is this normal? If not, how can the garbage be reduced?

    Note: must of the time the "DestoryOverTime" script is the only one in the list, the above example is excessive.
     
  4. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    EDIT: Oops almost forget to post the new version of the script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestoryOverTime : MonoBehaviour
    5. {
    6.     public GameObject SpawnedObject;
    7.     public bool IsVisible;
    8.     private float ReturnObjectsAtTime = -1f;
    9.  
    10.     void Update ()
    11.     {
    12.         if (ReturnObjectsAtTime != -1f && Time.time > ReturnObjectsAtTime)
    13.         {
    14.             ReturnObjects ();
    15.  
    16.             ReturnObjectsAtTime = -1f;
    17.         }
    18.        
    19.     }
    20.  
    21.     public void OnTriggerEnter2D(Collider2D other)
    22.     {
    23.         if (other.tag == "NotVisible")
    24.         {
    25.             IsVisible = false;
    26.  
    27.             if (SpawnedObject.tag == "CoinHolder")
    28.             {
    29.                 ReturnObjectsAtTime = Time.time + 7.5f;
    30.                 //Invoke ("ReturnObjects", 7.5f);
    31.             }
    32.  
    33.             else if (SpawnedObject.tag == "PowerUpHolder")
    34.             {
    35.                 ReturnObjectsAtTime = Time.time + 7.5f;
    36.                 //Invoke ("ReturnObjects", 7.5f);
    37.             }
    38.  
    39.             else if (SpawnedObject.tag == "ObstacleHolder")
    40.             {
    41.                 ReturnObjectsAtTime = Time.time + 7.5f;
    42.                 //Invoke ("ReturnObjects", 7.5f);
    43.             }
    44.         }
    45.  
    46.         else if (other.tag == "ObjectsAreVisible")
    47.         {
    48.             IsVisible = true;
    49.         }
    50.     }
    51.  
    52.     public void ReturnObjects ()
    53.     {
    54.         NewObjectPool.instance.PoolObject(SpawnedObject);
    55.     }
    56. }
     
  5. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Update:

    Ok, I used the deep profiler and it seems to have something to with using tags with triggers:

    Screen Shot 2016-02-23 at 4.34.23 PM.png

    Any suggestions ? alternatives to tags ?
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    I don't use tags, but I suspect that comparing them using == might generate some garbage. Try using .CompareTag instead maybe?
     
  7. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Thanks, this help me and worked wonderfully. Now on to doing this with my other scripts that use tags and triggers.

    New script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestoryOverTime : MonoBehaviour
    5. {
    6.     public GameObject SpawnedObject;
    7.     public bool IsVisible;
    8.     private float ReturnObjectsAtTime = -1f;
    9.  
    10.     void Update ()
    11.     {
    12.         if (ReturnObjectsAtTime != -1f && Time.time > ReturnObjectsAtTime)
    13.         {
    14.             ReturnObjects ();
    15.  
    16.             ReturnObjectsAtTime = -1f;
    17.         }
    18.        
    19.     }
    20.  
    21.     public void OnTriggerEnter2D(Collider2D other)
    22.     {
    23.         if (other.CompareTag("NotVisible"))
    24.         {
    25.             IsVisible = false;
    26.  
    27.             if (SpawnedObject.tag == "CoinHolder")
    28.             {
    29.                 ReturnObjectsAtTime = Time.time + 7.5f;
    30.                 //Invoke ("ReturnObjects", 7.5f);
    31.             }
    32.  
    33.             else if (SpawnedObject.tag == "PowerUpHolder")
    34.             {
    35.                 ReturnObjectsAtTime = Time.time + 7.5f;
    36.                 //Invoke ("ReturnObjects", 7.5f);
    37.             }
    38.  
    39.             else if (SpawnedObject.tag == "ObstacleHolder")
    40.             {
    41.                 ReturnObjectsAtTime = Time.time + 7.5f;
    42.                 //Invoke ("ReturnObjects", 7.5f);
    43.             }
    44.         }
    45.  
    46.         else if (other.CompareTag("ObjectsAreVisible"))
    47.         {
    48.             IsVisible = true;
    49.         }
    50.     }
    51.  
    52.     public void ReturnObjects ()
    53.     {
    54.         NewObjectPool.instance.PoolObject(SpawnedObject);
    55.     }
    56. }
    57.  
    Screen Shot 2016-02-23 at 4.57.02 PM.png