Game freezes up for a second after executing code, how do I fix this?
Hello, I created a script to have a boss character fire a laser using the line renderer, it works well enough for my purposes but to get the effect my code is kind of sloppy and during part of the code execution towards the end the game will freeze for a split second before resuming. How can I fix or trim down my code to prevent this?
public class anemoneLaser : MonoBehaviour {
public BossBehavior bossBehavior;
public float laserWidth;
public float laserTimer;
public float startTimer;
private float nextShot;
private float nextStartUp;
public bool laserStarting;
public bool laserReady;
public bool laserOff;
public float minWidth = 0;
public float maxWidth = 2.3f;
LineRenderer redLaser;
ParticleSystem laserSparks;
private AudioSource laserCharge;
private AudioSource laserShot;
// Use this for initialization
void Start ()
{
GameObject bossBehaviorObject = GameObject.FindWithTag("Boss");
if (bossBehaviorObject != null)
{
bossBehavior = bossBehaviorObject.GetComponent<BossBehavior>();
}
if (bossBehavior == null)
{
Debug.Log("Cannot find 'BossBehavior' script");
}
AudioSource[] laserSounds = GetComponents<AudioSource>();
laserCharge = laserSounds[0];
laserShot = laserSounds[1];
laserTimer = nextShot;
startTimer = nextStartUp;
laserWidth = 0;
redLaser = GetComponent<LineRenderer>();
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
redLaser.sortingLayerID = spriteRenderer.sortingLayerID;
redLaser.sortingOrder = spriteRenderer.sortingOrder;
redLaser.widthMultiplier = laserWidth;
laserSparks = GetComponentInChildren<ParticleSystem>();
laserSparks.Pause();
}
// Update is called once per frame
void Update ()
{
redLaser = GetComponent<LineRenderer>();
redLaser.widthMultiplier = laserWidth;
if (laserWidth < 0)
{
laserWidth = 0;
}
// Starting countdown for laser
if (laserStarting)
{
laserOff = false;
startTimer -= Time.deltaTime;
}
if (bossBehavior.bossActive && laserStarting && startTimer < 0 && !laserOff)
{
laserWidth = 0.1f; //sets laser to a minimum width so player knows its about to go off
laserStarting = false;
laserCharge.Play();
laserSparks.Play();
StartCoroutine(PrepareToFire());
}
//Laser ready to fire
if (laserReady)
{
laserTimer -= Time.deltaTime;
}
if (bossBehavior.bossActive && laserReady && laserTimer < 0 && !laserOff)
{
StartCoroutine(FirinMahLaser());
}
}
IEnumerator PrepareToFire()
{
yield return new WaitForSeconds(0.8f);
Debug.Log("PrepareToFire()");
startTimer = nextStartUp;
laserReady = true;
}
// Increases width of laser to maxWidth value before finishing and going into Cool Down
IEnumerator FirinMahLaser()
{
//laserShot.Play(); //Not sure where to place this yet so it doesn't play more then once
yield return new WaitForSeconds(3.5f);
laserTimer = nextShot;
if (laserWidth < maxWidth && !laserOff)
{
Debug.Log("Adding Width");
laserWidth += 0.1f;
}
else if (laserWidth >= maxWidth && !laserOff)
{
yield return new WaitForSeconds(2.0f);
Debug.Log("Laser Width at Max");
StartCoroutine(CoolingOff());
}
}
//Called to reduce width and turn off laser then move on to prepare for the next firing
IEnumerator CoolingOff()
{
while (laserWidth > minWidth && !laserOff)
{
Debug.Log("Cooling off WHILE loop");
laserWidth -= 0.01f;
}
if(laserWidth <= minWidth && !laserOff)
{
Debug.Log("WHILE loop broken");
laserSparks.Stop();
laserOff = true;
laserStarting = false;
laserReady = false;
yield return new WaitForSeconds(10.0f);
StartCoroutine(PrepNext());
}
}
//Prepare for next laser
IEnumerator PrepNext()
{
Debug.Log("PrepNext()");
laserWidth = 0;
laserTimer = nextShot;
startTimer = nextStartUp;
yield return new WaitForSeconds(2.0f);
laserStarting = true;
}
//TODO Add collision to laser
}
The freeze up happens after the while loop is broken, maybe that's what is creating the lag? Any help would be appreciated. Thanks.
Answer by WeirderChimp · Jan 15, 2017 at 02:45 AM
Hey, so i had a look at your code and its likely that the while loop in your CoolingOff co-routine is whats causing the problem.
I assume you dont want your CoolOff to complete in a single frame which is whats its currently doing. If you add the line. yield return null;
below the laserWidth -= 0.01f
this will make your co-routine yield for a frame and it will check the while loop again in the next frame and they - the 0.01 and so on until (laserWidth < minWidth && !laserOff).
Also i noticed that your cooldown(and other variables) is fps depended, this means that laserWidth -= 0.01f;
will be called each frame and therefor doesnt take into account actual time.
So for example if you have 60fps your laserWidth will be -0.6 in 1 second. but for whatever reason if your fps is 30 it will take 2 seconds to get to -0.6. you should look into Time.deltatime
to fix this problem.
Hope this helps ~Scott
Thanks, that did it, though I still experience a frame rate drop but its not too bad.
Your answer
Follow this Question
Related Questions
Unity freezes when I juggle Lists and SortedLists. 1 Answer
unity editor freezes on play, because of script 1 Answer
Function runs fine the first time but crashes if I run it twice? 1 Answer
Unity game freezes a few seconds after loading scene 2 Answers
How do I get my character to stop moving while he is attacking? 0 Answers