# changing color of sprite not every frame

So I have been trying making this game, which changes color of sprites in it. It should only happen when OnMouseDown(). but it is executing every frame and cannot go out of the couroutine. I want the color change to be slower. Please mark the colors should still change.

public class control : MonoBehaviour
{
public bool startstop = false;
SpriteRenderer m_SpriteRenderer;
private void Update()
{
StartCoroutine("Changecolor", 3f);
}
IEnumerator Changecolor()
{
yield return new WaitForSeconds(3);
if(startstop == true)
{
int random = Random.Range(1, 4);
if (random == 1)
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.blue;
}
else if(random == 2)
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.red;
}
else if(random == 3)
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.green;
}
else
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.yellow;
}
}
}
private void OnMouseDown()
{
startstop = !startstop;
}
}

• Right now you are creating new Coroutines every frame, which wait for 3 seconds, and then check if the startstop variable is true. This means if you press the mouse button once, startstop will be true and will keep changing the colours every frame. What would be the ideal result ? I'm not sure what you are trying to accomplish. Would you like sprites to change colour once every mouse click? Or just less often? – TomTsagk Oct 7 '19 at 11:12

All you need to do here is move your if statement into the Update function. In your case you would be calling the co routine every frame, and there would be a lot off calls waiting for those 3 seconds to pass and then once the startstop is true, a lot of them would be called. So here, you basically only call it once the startstop is true, and then you immediately change its value to false so no more than 1 call is executed.

public class control : MonoBehaviour
{
public bool startstop = false;
SpriteRenderer m_SpriteRenderer;
private void Update()
{
if(startstop){
StartCoroutine("Changecolor", 3f);
startstop = false;
}
}
IEnumerator Changecolor()
{
yield return new WaitForSeconds(3);
int random = Random.Range(1, 4);
if (random == 1)
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.blue;
}
else if(random == 2)
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.red;
}
else if(random == 3)
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.green;
}
else
{
m_SpriteRenderer = GetComponent<SpriteRenderer>();
m_SpriteRenderer.color = Color.yellow;
}
}
private void OnMouseDown()
{
startstop = !startstop;
}

• I like this answer, but perhaps on the startstop = !startstop inside the update function, I think it would be better if it was startstop = false instead. It doesn't really make a difference functionality-wise, because that code can only be reached if startstop is true, but it makes it more readable. – TomTsagk Oct 7 '19 at 11:13
• You're right. I try to change as little as possible from peoples code as not to introduce something they don't quite get, as a lot of code that people post is copied from somewhere else :D – Milos Romanic Oct 7 '19 at 11:16
• Thank you very much, – Laurenz Oct 7 '19 at 13:54
• but I was trying to loop the colors the whole time and not just once. – Laurenz Oct 7 '19 at 13:54
• In your code the change color method only gets executed once – Laurenz Oct 7 '19 at 13:55

The other way would be looping the coroutine instead of calling it multiple times, and stopping it when needed.

public class Control : MonoBehaviour
{
public bool startstop = false;
SpriteRenderer m_SpriteRenderer;

IEnumerator Changecolor() {
yield return new WaitForSeconds(3);
int random = Random.Range(1, 4);
if (random == 1) {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.blue;
} else if (random == 2) {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.red;
} else if (random == 3) {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.green;
} else {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.yellow;
}

this.StartCoroutine("Changecolor", 3f);
}

private void OnMouseDown() {
if (this.startstop) {
this.StartCoroutine("Changecolor", 3f);
this.startstop = !this.startstop;
} else {
this.StopCoroutine("Changecolor");
this.startstop = !this.startstop;
}
}
}


If this doesn't work you could fix it easily, as I'm at work and cant test it right now ^^

• were is the coroutine change color being called – Laurenz Oct 7 '19 at 14:22
• it still doesn't work sorry – Laurenz Oct 7 '19 at 14:23
• It's being called from OnMouseDown(), and it will be called again from itself. Then on another OnMouseDown we will call StopCoroutine so it stops calling itself – Milos Romanic Oct 7 '19 at 14:26
• how can it be called from Onmousedown() if the startstop is false nothing is being called !!! – Laurenz Oct 7 '19 at 14:36
• Hahahah well set it to true :D – Milos Romanic Oct 7 '19 at 14:58