FireFoxxie
FireFoxxie

Reputation: 47

Unity, C# | How do I have a wait time between methods?

My goal: To get my snail to seem like it's moving on its own. Example: Going right for a few seconds, going left for a few seconds, staying in one place for a few seconds.

Current Status: Snail sits still in one place when I attempt to use WaitForSeconds

Without WaitForSeconds, my snail changes directions back and forth successfully(Except doing this really fast)

I've only started learning Unity and C# yesterday. Any tips/suggestions would be of much help, even if it's not on my original question. If there's anything else I can do to help you help me, let me know! :)

using UnityEngine;
using System.Collections;

public class SnailMove : MonoBehaviour {
void Start()
{

}
// Use this for initialization
void Update () 
{
    Waiting();
}

// Update is called once per frame
void Movement () 
{

    int direct = Random.Range(-1, 2);
    if (direct == 1) 
    {
        transform.Translate(Vector3.left * 1f * Time.deltaTime);
        transform.eulerAngles = new Vector2(0,180);
    }
    if (direct == -1)
    {
        transform.Translate(Vector3.left * 1f * Time.deltaTime);
        transform.eulerAngles = new Vector2(0,0);
    }
}
  IEnumerator Waiting()
    {
    Movement ();
    yield return new WaitForSeconds (5);
    }
}

Upvotes: 2

Views: 6098

Answers (3)

stromdotcom
stromdotcom

Reputation: 381

Your logical flow is a little confused. You start the Waiting() coroutine every frame, when you probably want to call it once (in Start() for example) and loop your coroutine. The result is you have a whole bunch of Waiting() coroutines running and all competing with each other.

You have two options here:

void Start() {
    StartCoroutine(Waiting());
}

IEnumrator Waiting() {
    while(true) {
        Movement();
        yield return new WaitForSeconds(5f);
    }
}

I got nauseated typing that though, because while(true) is a horrible idea. Better would be to track time in Update() and call Movement() every 5 seconds, like so:

private float timer = 0f;

void Update() {
    timer += Time.deltaTime;
    if (timer > 5f) {
        Movement();
        timer -= 5f;
    }
}

Upvotes: 1

Bunny83
Bunny83

Reputation: 1109

Coroutines need to be started with StartCoroutine. From your description it sounds like you want something like this:

using UnityEngine;
using System.Collections;

public class SnailMove : MonoBehaviour
{
    public float speed = 1f;
    int direction = 0;
    void Start()
    {
        StartCoroutine(ChangeDirection());
    }

    void Update () 
    {
        if (direction == 1) 
        {
            transform.Translate(Vector3.left * speed * Time.deltaTime);
            transform.eulerAngles = new Vector2(0,180);
        }
        else if (direction == -1)
        {
            transform.Translate(Vector3.left * speed * Time.deltaTime);
            transform.eulerAngles = new Vector2(0,0);
        }
    }

    IEnumerator ChangeDirection()
    {
        while(true)
        {
            yield return new WaitForSeconds (5);
            direction = Random.Range(-1, 2); // returns "-1", "0" or "1"
        }
    }
}

Upvotes: 2

Tim Botha
Tim Botha

Reputation: 51

Good day I believe that your problem is that you are calling waiting in your update method that gets called on every frame regardless of previous executions, this implies that only the thread that called waiting before waits and as such the method can be called again as the other thread only waits.

try this:

using UnityEngine;
using System.Collections;

private bool waiting = false;

public class SnailMove : MonoBehaviour {
void Start()
{

}
// Use this for initialization
void Update () 
{
    if(waiting == false)  
    {
       Waiting();
    }
}

// Update is called once per frame
void Movement () 
{

    int direct = Random.Range(-1, 2);
    if (direct == 1) 
    {
        transform.Translate(Vector3.left * 1f * Time.deltaTime);
        transform.eulerAngles = new Vector2(0,180);
    }
    if (direct == -1)
    {
        transform.Translate(Vector3.left * 1f * Time.deltaTime);
        transform.eulerAngles = new Vector2(0,0);
    }
}
  IEnumerator Waiting()
    {
    Movement ();
    waiting = true;
    yield return new WaitForSeconds (5);
    waiting = false;
    }
}

This will make the update function wait for the boolean waiting to be set to false before it will call the function again.

Upvotes: 1

Related Questions