Search Unity

Can I repeat a coroutine

Discussion in 'Getting Started' started by Photonphill, Apr 22, 2021.

  1. Photonphill

    Photonphill

    Joined:
    Mar 30, 2021
    Posts:
    18
    Hi all,

    I'm currently trying to make a simple object repeatedly pulse. I can get it to do it once using a coroutine that I found on youtube in which the instructor uses a collider and a mouse to trigger the pulse so it only occurs once. This is also the case when I run my script (i've not added the mouse trigger from the vid). I've lookied online but nobody seems to show how to repeat a coroutine. Is it possible? or is it better to attack the problem using a different method. I'm very new to coding and unity so i may have some extra stuff in my code that is not being used (public void maybe?). Any help would be much appreciated.
    the code I'm using is:

    public class pulseObject : MonoBehaviour
    {
    private bool coroutineAllowed;

    // Start is called before the first frame update
    void Start()
    {
    StartCoroutine("pulse");

    }

    public void StartPulse()
    {
    if (coroutineAllowed)
    {
    StartCoroutine("pulse");
    }
    }
    // Update is called once per frame
    private IEnumerator pulse()
    {
    coroutineAllowed = true;

    for (float i = 0f; i <= 1f; i += 0.1f)
    {
    transform.localScale = new Vector3(
    (Mathf.Lerp(transform.localScale.x, transform.localScale.x + 1f, Mathf.SmoothStep(0f, 1f, i))),
    (Mathf.Lerp(transform.localScale.y, transform.localScale.y + 1f, Mathf.SmoothStep(0f, 1f, i))),
    (Mathf.Lerp(transform.localScale.z, transform.localScale.z + 1f, Mathf.SmoothStep(0f, 1f, i)))
    );
    yield return new WaitForSeconds(0.1f);
    }

    for (float i = 0f; i <= 1f; i += 0.1f)
    {
    transform.localScale = new Vector3(
    (Mathf.Lerp(transform.localScale.x, transform.localScale.x - 1f, Mathf.SmoothStep(0f, 1f, i))),
    (Mathf.Lerp(transform.localScale.y, transform.localScale.y - 1f, Mathf.SmoothStep(0f, 1f, i))),
    (Mathf.Lerp(transform.localScale.z, transform.localScale.z - 1f, Mathf.SmoothStep(0f, 1f, i)))
    );

    yield return new WaitForSeconds(0.1f);

    }

    coroutineAllowed = true;

    }


    }
     
  2. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    You can repeat anything in code. That's what loops are for!

    [/programmer-humor]

    What you need to decide is if you want to loop outside the coroutine and keep calling it (unlikely) or have a loop that runs inside the coroutine and keeps executing as long as a condition is met. Then it's a matter of understanding the condition and choosing the appropriate loop structure. The most common ones look like this:

    Code (CSharp):
    1. for (int i = 0; i < length; i++)
    2. {
    3.     // Do stuff until i is no longer less than length
    4. }
    5.  
    6. foreach (var item in collection)
    7. {
    8.     // Do stuff for each item in collection
    9. }
    10.  
    11. while (condition)
    12. {
    13.     // Do stuff while condition is true
    14. }
    It will really help you to understand how code works a bit more before copying code from tutorials you find. If you can understand what they're doing at least from a top-down perspective, you'll actually learn by doing instead of just feeling lost every step of the way. Look into some basic C# guides and practice with some small stuff first, then come back to this!

    Good luck!
     
    stain2319 likes this.
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Also consider that (1) a coroutine may not be the best tool for the job, and (2) coroutines are hard to understand, especially for new programmers, so this means they are certainly not the tool you should be using for the job. And they are never necessary; anything a coroutine can do can be done in Update instead.

    So my suggestion would be: forget about coroutines, and use Update. The Update method is simple: it gets called once per frame. Make whatever change to your object you want to make on each frame.

    For example, if you're just trying to make your object pulse in scale forever, then try something like:

    Code (CSharp):
    1. void Update() {
    2.     transform.scale = Vector3.one * (1 + 0.2f * Mathf.Sin(Time.time));
    3. }
    Every frame, this will set the scale of your object to something between 0.8 and 1.2 times the standard size, oscillating sinusoidally according to the current time.
     
  4. Photonphill

    Photonphill

    Joined:
    Mar 30, 2021
    Posts:
    18
    Hi,

    Thanks for getting in touch, I'll definitely take these suggestions on board.

    I did end up coming at it from a different angle, I found a tutorial online that uses linear interpolation giving max and min scale, using 'i' and a 'while' statement to grow and shrink the object and repeating that.

    Here's the code I ended up going with:

    ***************************

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class GrowShrinkObject : MonoBehaviour
    {

    public Vector3 minScale;
    public Vector3 maxScale;
    public bool repeatable;
    public float speed = 2f;
    public float duration = 5f;


    // Start is called before the first frame update
    IEnumerator Start()
    {
    minScale = transform.localScale;
    while (repeatable)
    {
    yield return RepeatLerp(minScale, maxScale, duration);
    yield return RepeatLerp(maxScale, minScale, duration);
    }
    }

    // Update is called once per frame
    public IEnumerator RepeatLerp(Vector3 a, Vector3 b, float time)
    {
    float i = 0.0f;
    float rate = (1.0f / time) * speed;
    while (i < 1.0f)
    {
    i += Time.deltaTime * rate;
    transform.localScale = Vector3.Lerp(a, b, i);
    yield return null;
    }

    }


    }

    ***********************

    Thanks for the help,

    Happy coding :)

    Phill
     
  5. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    Glad you figured it out.

    For future reference, there's a button in the text editor here (looks like a page with carat brackets in it) that lets you paste code with formatting, line numbers, and syntax highlighting. It makes reading your code much easier.
     
  6. aMIGA_dUDE

    aMIGA_dUDE

    Joined:
    Oct 12, 2019
    Posts:
    22
    It would be nice if Unity made a video about this feature on this website. It be lot easyer then saying the likes of (looks like a page with carat brackets in it). Say upload video on to YouTube so we could give show how this is done in a easy way, it just an idea.
     
  7. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    There's a post pinned in the scripting forum, but no one ever reads that, either. It's not a big deal. We're very used to having to instruct people to use the button. :p
     
    BrandyStarbrite and JoeStrout like this.
  8. Photonphill

    Photonphill

    Joined:
    Mar 30, 2021
    Posts:
    18
    Hi Schneider21, thanks for the heads up. I'll try to remember to use that. :)
     
    Schneider21 likes this.