How to reduce garbage collection in script?

According to the profiler, this script seems to be creating tons of garbage, and I’ve been tweaking it for the past couple of days to get rid of the garbage, but the the profiler still shows tons of garbage collection spikes, and I’m not sure what else to tweak in it.

var speed = 2.5;
var Wait : float = 0.1;
var animator: Animator;
var Dlo : Transform;
var Wen : Transform;
var playDlo : boolean = true;
var playWen : boolean = true;
var damaging : boolean = false;
var dieEffectsPrefab : GameObject;
var hurtEffectsPrefab : GameObject;
var HitCount : float = 0.0;
var MaxHits : float = 0.0;
var canDamage : boolean = true;
var hurtable : boolean = false;
var stall : boolean = false;
var bombstall : boolean = false;
var hitArea : float;
private var dist: float;
private var DloDir : Vector3;
private var Dloangle : float;
private var WenDir : Vector3;
private var Wenangle : float;

function Start()
{
animator = GetComponent("Animator");
animator.SetBool("Surprised", false);
gameObject.tag = "Enemy";
playDlo = true;
playWen = false;
animator.SetBool("Hurt", false);
canDamage = true;
hurtable = false;
}

function Update ()
{
DloDir = transform.position - Dlo.position;
Dloangle = Vector3.Angle(DloDir, Dlo.forward);
WenDir = transform.position - Wen.position;
Wenangle = Vector3.Angle(WenDir, Wen.forward);

    if (Input.GetKeyDown(KeyCode.C) || Input.GetButtonDown("Slash")) {
    Drag();
}
  
    if (Dlo.GetComponent("WeaponWD").hurtable1 == true){
        hurtable = true;
    }
    animator.SetFloat("Hits", HitCount);
  
    if (Input.GetKey(KeyCode.F1) && Dlo.GetComponent.<CharacterController>().enabled == true && Dlo.GetComponent("playerscript").grounded == true){
        playDlo = true;
        playWen = false;
    }
    else if (Input.GetKey(KeyCode.F2) && Wen.GetComponent.<CharacterController>().enabled == true && Wen.GetComponent("playerscript").grounded == true){
        playDlo = false;
        playWen = true;
    }
    //Moves toward Dlo
    if (playDlo == true){
    dist = Mathf.Sqrt(Mathf.Pow(Mathf.Abs(Dlo.position.x - transform.position.x),2) + Mathf.Pow(Mathf.Abs(Dlo.position.z - transform.position.z),2));
    distY = Mathf.Sqrt(Mathf.Pow(Mathf.Abs(Dlo.position.y - transform.position.y),2));
    if(dist <= 15 && distY <= 3){
        transform.LookAt(Vector3(Dlo.position.x, transform.position.y, Dlo.position.z));
    }
}
    else if (playWen == true){
    dist = Mathf.Sqrt(Mathf.Pow(Mathf.Abs(Wen.position.x - transform.position.x),2) + Mathf.Pow(Mathf.Abs(Wen.position.z - transform.position.z),2));
    distY = Mathf.Sqrt(Mathf.Pow(Mathf.Abs(Wen.position.y - transform.position.y),2));
        if(dist <= 15 && distY <= 3){
        transform.LookAt(Vector3(Wen.position.x, transform.position.y, Wen.position.z));
        }
}

if(dist <= 10 && distY <= 3){
    animator.SetBool("Surprised", true);
    transform.position += transform.forward * speed*Time.deltaTime;
}

if(dist > 15 && distY > 3){
    animator.SetBool("Surprised", false);
}

if(dist <= hitArea && distY <=5 && stall == true && HitCount < MaxHits && Dloangle < 60 && playDlo == true || dist <= hitArea && distY <=7 && stall == true && HitCount < MaxHits && Wenangle < 60 && playWen == true){
        ApplyDamage1();
        ApplyDamage11();
        stall = false;
    }

if (HitCount >= MaxHits){
        gameObject.tag = "Untagged";
        Instantiate(hurtEffectsPrefab, transform.position, transform.rotation);
        Instantiate(dieEffectsPrefab, transform.position, transform.rotation);
        Destroy(gameObject);
        ApplyDamage11();
    }

}

function Drag () {
    if (playDlo){
        if (Dlo.GetComponent("WeaponWD").comboCount < 3){
            stall = true;
            yield WaitForSeconds (0.5);
            stall = false;
        }
        if (Dlo.GetComponent("WeaponWD").comboCount >= 3){
            stall = true;
            yield WaitForSeconds (0.7);
            stall = false;
        }
    }
  
    if (playWen){
        if (Wen.GetComponent("WeaponWD").comboCount < 3){
            stall = true;
            yield WaitForSeconds (0.5);
            stall = false;
        }
        if (Wen.GetComponent("WeaponWD").comboCount >= 3){
            stall = true;
            yield WaitForSeconds (0.7);
            stall = false;
        }
    }
}

function Cfunct (){
    hurtable = true;
}



function ApplyDamage1 () {
    stall = false;
    yield WaitForSeconds(0.05);
    Instantiate(hurtEffectsPrefab, transform.position, transform.rotation);
    yield WaitForSeconds(0.2);
    HitCount += 1;
    return;
}

function ApplyDamage11 () {
    animator.SetBool("Hurt", true);
    yield WaitForSeconds(0.05);
    Instantiate(hurtEffectsPrefab, transform.position, transform.rotation);
    yield WaitForSeconds(0.2);
    animator.SetBool("Hurt", false);
    bombstall = false;
}

function MaxDamage () {
    stall = false;
    HitCount += 3;
    bombstall = true;
    return;
}

function OnCollisionEnter (col : Collision)
{
    if (!enabled) return;
    if(col.gameObject.tag == "bomb" && bombstall == false){
        MaxDamage();
        ApplyDamage11();
    }
}

function OnCollisionStay (col : Collision)
{
    var Dloda = Dlo.GetComponent("Damage");
    var Wenda = Wen.GetComponent("Damage");
    if (Dloda.canDamage == true && Dloda.canDamage2 == true || Wenda.canDamage == true  && Wenda.canDamage2 == true){
        if(col.gameObject.name == "Dlo" && playDlo == true){
            Dloda.ApplyDamage();
            Dloda.blinkOut();
        }
        else if (col.gameObject.name == "Wen" && playWen == true){
            Wenda.ApplyDamage();
            Wenda.blinkOut();
        }
    }  
}

Any help to get rid of garbage collection is appreciated. Thank you :slight_smile:

Try caching your ‘anotherTransform.GetComponent.()’ calls to instance variables (like you have with your animator variable) so you don’t have to fetch them every time you use them in Updates or other methods. You can do this during Awake or Start depending on other things you might want to do with them at the same time.

Ah, thank you. That reduced some of the garbage collection, it still seems to be creating garbage though. Could the “anotherTransform.position” be creating the garbage maybe?

No. In C# transform.position is a value type (struct) so I assume accessing it in UnityScript shouldn’t be causing any GC problems.

You could also try setting up string constants to use in place all of the string literals, and replace the use of strings with id’s where you can, eg. animator.SetBool(“someName”, false) could be animator.SetBool(someNameId, false) - read the docs Unity - Scripting API: Animator.SetBool, generate the ids you need (in Awake, Start, or even in another class) using Unity - Scripting API: Animator.StringToHash. The same technique can be applied to material properties, too.

String literals do not create garbage that can be collected. Not sure what the Animator does internally, though.

It was more a general small optimisation, like the calls to animator using id’s rather than strings. Sorry, should have mentioned that.

Also, Instantiate will allocate memory - if you do lots of them then consider pooling, ie. creating a set of objects to reuse at startup rather than instantiating new ones when you need them. You might want to check if the UnityScript versions of things like WaitForSeconds allocate memory as well. In C# you can reuse objects like WaitForSeconds created to perform yields.