- Home /
The question is answered, right answer was accepted
WaitForSeconds in Update() function
Hello, I've been trying to make a script which makes the object "wander around" and stop for 5 seconds. After that, he wanders around again. But I'm getting an error saying:
"Update() can not be a coroutine."
This is my script so far:
var NPC : GameObject;
var Speed = 50;
var Range = 10;
var VectorRandom : Vector3;
function Update() {
NPC.transform.position += transform.TransformDirection(Vector3.forward)*Speed*Time.deltaTime;
if((NPC.transform.position - VectorRandom).magnitude < 3) {
yield WaitForSeconds(5.0);
Start();
}
}
function Start() {
VectorRandom = Vector3(Random.Range(NPC.transform.position.x - Range, NPC.transform.position.x + Range), 1, Random.Range(NPC.transform.position.z - Range, NPC.transform.position.z + Range));
VectorRandom.y = 1;
NPC.transform.LookAt(VectorRandom);
}
I know this is because Update keeps looping it, so wait won't work. I've tried everything to fix it, but nothing works.
Thank you.
Yeah, definitely the first thing you want to do is rename your Start function to something else.
Answer by fafase · Jul 01, 2015 at 08:23 AM
private var timer:float = 0.0f;
public var waitingTime : float = 5.0f;
function Update() {
NPC.transform.position += transform.TransformDirection(Vector3.forward)*Speed*Time.deltaTime;
if((NPC.transform.position - VectorRandom).magnitude < 3) {
timer += Time.deltaTime;
if(timer > waitingTime) {
timer = 0f;
Reset();
}
}
}
function Reset() {
VectorRandom = Vector3(Random.Range(NPC.transform.position.x - Range, NPC.transform.position.x + Range), 1, Random.Range(NPC.transform.position.z - Range, NPC.transform.position.z + Range));
NPC.transform.LookAt(VectorRandom);
}
Thank you very much that helped me a lot.
timer += Time.deltaTime;
if(timer > waitingTime) {
timer = 0f;
DoThis();
}
i was trying for ages to get the same effect with a very complicated code but yours is so simple.
Answer by GiyomuGames · Jul 01, 2015 at 02:32 AM
You a need separate function and probably a boolean or something. Sorry I don't have Unity nor Visual Studio now, also I code in C#, but the idea would be:
bool wanderingAround;
function WanderAround {
while (true)
{
wanderingAround = true;
yield WaitForSeconds(5.0); // assuming you want it to wander for 5 seconds
wanderingAround = false;
yield WaitForSeconds(5.0);
}
Then you just do "yield StartCoroutine("WanderAround");" in your Start function and use the boolean "wanderingAround" in your Update function to know whether the object is supposed to be wandering or not.
By the way calling your Start function in Update is really not normal. Start is called automatically when the object is instantiated and should never be called directly. You should probably follow a couple tutorials before moving further.
should never be called directly
It is perfectly acceptable to manually invoke Start() and there are times when you need to.
For example when you disable and re-enable a gameobject, Start will not run on re-enable so will often need to be invoked manually.
But yes, perfor$$anonymous$$g this action in Update() is highly unusual.
True! I simplified it to avoid confusing him/her for now. S/he seems to just be starting so s/he should remember that calling Start in the Update method = bad idea.
I know this won't work, because I need the if statement to keep checking. If it does it every 5 seconds, it just won't work, it'll only work if it does it every tick.
I yeah I missed that point. I think below is the skeleton of what you are trying to do: (not sure if it compiles, I don't know much about Javascript)
var NPC : GameObject;
var Speed = 50;
var Range = 10;
var VectorRandom : Vector3;
var stop = false;
function Update() {
NPC.transform.position += transform.TransformDirection(Vector3.forward)*Speed*Time.deltaTime;
if((NPC.transform.position - VectorRandom).magnitude < 3) {
StartCoroutine("Stop");
}
if (!stop)
$$anonymous$$ove();
}
function Stop() {
stop = true;
yield WaitForSeconds(5.0);
stop = false;
}
function $$anonymous$$ove() {
VectorRandom = Vector3(Random.Range(NPC.transform.position.x - Range, NPC.transform.position.x + Range), 1, Random.Range(NPC.transform.position.z - Range, NPC.transform.position.z + Range));
VectorRandom.y = 1;
NPC.transform.LookAt(VectorRandom);
}
You change the code, now it works. As it was when I posted, it would not work.
Answer by raja1250 · Jul 01, 2015 at 07:49 AM
use a seperate coroutine for delay of 5 min and call it in update function.
IEnumerator delay() { yield return new WaitForSeconds(5); } in the update function
StartCoroutine(delay());
You answer looks like total nonsense simply because you havent laid it out very well :D
As a result it appears that you are proposing to put that IEnumerator function inside Update.
I read it again and I see its not the case. Just thought Id let you know.
Answer by Ibzy · Jul 01, 2015 at 08:13 AM
You could create a coroutine with an infinite for loop that you call on Start() rather than checking every frame in Update():
Start(){
StartCoroutine(Wander());
}
IEnumerator Wander(){
for(;;){
VectorRandom = Vector3(Random.Range(NPC.transform.position.x - Range, NPC.transform.position.x + Range), 1, Random.Range(NPC.transform.position.z - Range, NPC.transform.position.z + Range));
VectorRandom.y = 1;
NPC.transform.LookAt(VectorRandom);
yield return new WaitForSeconds(5);
}
}
Edit: Didn't see the comment about having to check for the magnitude on every tick. The below will do the check on Update, but put the yield in the coroutine:
var NPC : GameObject;
var Speed = 50;
var Range = 10;
var VectorRandom : Vector3;
var Wandering = false : Boolean;
function Update() {
NPC.transform.position += transform.TransformDirection(Vector3.forward)*Speed*Time.deltaTime;
if((NPC.transform.position - VectorRandom).magnitude < 3 && !Wandering) {
Wandering = true;
StartCoroutine(Wander());
}
}
IEnumerator Wander() {
yield WaitForSeconds(5.0);
VectorRandom = Vector3(Random.Range(NPC.transform.position.x - Range, NPC.transform.position.x + Range), 1, Random.Range(NPC.transform.position.z - Range, NPC.transform.position.z + Range));
VectorRandom.y = 1;
NPC.transform.LookAt(VectorRandom);
Wandering = false;
}
Be careful, with this code you'll call the subroutine Wander for each update when (NPC.transform.position - VectorRandom).magnitude < 3. Therefore is will be called many times in a row whereas you only want to call it once.
Sweet :) I would personally put "Wandering = true;" at the beginning of Wander() just to make it more readable and robust.
This is close to working, but it doesn't because IEnumerator is (I think) a C# command ins$$anonymous$$d of JS.
Follow this Question
Related Questions
How to make Update wait for AI Decision? 1 Answer
reload script continues adding the reload amount 1 Answer
Why isn't my flashing script working? 1 Answer
Javascript Class Update 2 Answers
Prefab Instantiation 1 Answer