- Home /
Making an object blink and then move position
Hey everyone,
I'm figuring that my problem is a simple one, but it's stumping me for some reason. I am messing around with the WalkerBoyStudios Lab #1, and I'm wanting to make an object blink 3 times and then move position. Currently, I am able to make it blink WHILE it moves, but I want it to blink first and then move after that. I am new to using coroutines, and so I'm assuming that the problem lies within my usage of them. Here is my current code:
This code currently makes the object blink and move sporadically, which is also NOT what I am looking to do. Any help is much appreciated!
You are more likely to get an answer if you edit your question and past your code directly into the question. Your code is not too long for a question. Be sure to select your code and use the 101/010 button to format it.
Here is the code:
using UnityEngine;
using System.Collections;
public class ScriptEnemy : $$anonymous$$onoBehaviour {
//Inspector Variables
public int numberOfClicks = 1;
public float respawnWaitTime = 1.0f;
public float blinkRate = 1f;
public int numberOfBlinks = 3;
private bool trigger;
//Private Variables
void Start () {
trigger=true;
}
// Update is called once per frame
void Update () {
if(numberOfClicks <= 0)
{
StartCoroutine(Junction());
}
}
IEnumerator Junction(){
if(transform.name == "Sphere")
{
yield return StartCoroutine(Blink(3));
yield return StartCoroutine($$anonymous$$oveEnemy());
}
else
{
yield return StartCoroutine($$anonymous$$oveEnemy());
}
}
IEnumerator $$anonymous$$oveEnemy(){
Vector3 position = new Vector3(Random.Range(-3.0f,5.0f), Random.Range(-4.0f,4.0f),0);
respawnWaitTime = Random.Range (0.0f, 1.5f);
StartCoroutine(RespawnWaitTime());
transform.position = position;
numberOfClicks = 1;
yield return null;
}
IEnumerator RespawnWaitTime() {
renderer.enabled = false;
yield return new WaitForSeconds(respawnWaitTime);
renderer.enabled = true;
}
void Change$$anonymous$$aterialColor() {
}
IEnumerator Blink(int numberOfBlinks) {
int i=0;
while(i<numberOfBlinks)
{
yield return new WaitForSeconds(blinkRate);
renderer.enabled = !renderer.enabled;
i++;
}
}
}
Answer by Jamora · Jul 29, 2013 at 06:39 PM
The biggest problem you have is that you are running your Junction every frame.
A quick fix is to check if you're already blinking and break if you are. Though boolean flags always give me the shivers; there is usually a better (read: more complicated) way...
private bool alreadyBlinking = false;
IEnumerator Junction ()
{
if (alreadyInJunction) yield break;
alreadyInJunction = true;
if (gameObject.name == "Sphere") {
yield return StartCoroutine(Blink(3));
yield return StartCoroutine(MoveEnemy());
} else {
yield return StartCoroutine(MoveEnemy());
}
alreadyInJunction = false;
}
I don't know if it's by design but, note that your MoveEnemy acts like a normal method. I think you've forgotten a yield: yield return StartCoroutine (RespawnWaitTime ());
Thank you, Jamora. I've been trying to find the answer, but would you be able to explain how yield return StartCoroutine
works?
Also, did you mean to for the global to variable to actually be:
private bool alreadyInJunction
rather than private bool alreadyBlinking
?
And what is the BEST way to do this? It's okay if it's complicated. I'd rather not have to chase bugs later on.
Jamora, thank you for your help! That worked perfectly!
yield return coroutine waits for the coroutine to finish before moving to the next line. It's the same as with yield return **new** WaitForSeconds();
You are creating a new instance of the class then waiting for it to finish. I'd imagine the constructor/Awake of WaitForSeconds to be just a counter.
Yes, you are corrent, I changed the name to be more descriptive at the last $$anonymous$$ute and forgot to change all instances.
Better is awfully subjective, but in my opinion a better way doesn't involve Update. It requires some thinking based on the behavior you want to achieve. Say, if Junction should be called at the Instantiation of the gameobject and end when the gameobject is destroyed, just start Junction at Start and have a while(true){ /* junction code */ yield return null;}
in Junction. Or it it's intermittent, have a method that is called when Junction should be started.
Your answer
Follow this Question
Related Questions
Blinking Lights 4 Answers
Turn signals using SetActiveRecursively(unity3) 1 Answer
Coroutines and keypresses 2 Answers
"Coroutine couldn't be started..." warning - harmless? 1 Answer