How can I use a coroutine to start over again when the first time has finished ?

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

public class Teleporting : MonoBehaviour
{
    public List<GameObject> teleporters = new List<GameObject>();
    public GameObject objectToTeleportMaterial;
    public float fadeSpeed = 0.1f;
    public bool toTeleport = false;

    private List<Vector3> teleportersPositions = new List<Vector3>();
    private bool teleported = false;
    private Material material;
    private GameObject myother;
    private List<Component> components = new List<Component>();


    // Start is called before the first frame update
    void Start()
    {
        teleporters.AddRange(GameObject.FindGameObjectsWithTag("Teleporter"));

        if (teleporters.Count > 0)
        {
            foreach (GameObject teleporter in teleporters)
            {
                teleportersPositions.Add(teleporter.transform.position);
            }
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        myother = other.gameObject;
        material = objectToTeleportMaterial.GetComponent<Renderer>().material;
        TeleportingVisualEffect(material, 0f, 5f);
    }

    // Update is called once per frame
    void Update()
    {
        if(teleported == true)
        {
            myother.GetComponent<NavMeshAgent>().enabled = false;          
            myother.transform.position = teleporters[0].transform.position;
            TeleportingVisualEffect(material, 1f, 5f);
            teleported = false;
        }
    }

    private void Teleport(GameObject objectToTeleport)
    {

    }

    private void TeleportingVisualEffect(Material material, float fadeTargetOpacity, float fadeDuration)
    {
        MaterialExtensions.ToFadeMode(material);
        StartCoroutine(FadeTo(material, fadeTargetOpacity, fadeDuration));
    }

    // Define an enumerator to perform our fading.
    // Pass it the material to fade, the opacity to fade to (0 = transparent, 1 = opaque),
    // and the number of seconds to fade over.
    IEnumerator FadeTo(Material material, float targetOpacity, float duration)
    {

        // Cache the current color of the material, and its initiql opacity.
        Color color = material.color;
        float startOpacity = color.a;

        // Track how many seconds we've been fading.
        float t = 0;

        while (t < duration)
        {
            // Step the fade forward one frame.
            t += Time.deltaTime;
            // Turn the time into an interpolation factor between 0 and 1.
            float blend = Mathf.Clamp01(t / duration);

            // Blend to the corresponding opacity between start & target.
            color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);

            // Apply the resulting color to the material.
            material.color = color;

            // Wait one frame, and repeat.
            yield return null;
        }

        if(targetOpacity == 1)
        {
            myother.GetComponent<NavMeshAgent>().enabled = false;
        }

        teleported = true;
    }

    private Material GetMaterial(GameObject ObjectToTeleport)
    {
        Material material = null;

        if (ObjectToTeleport.GetComponent<Renderer>().material != null)
        {
            material = ObjectToTeleport.GetComponent<Renderer>().material;
        }
        else
        {

            foreach (Transform child in ObjectToTeleport.transform)
            {
                if (child.GetComponent<Renderer>().material != null)
                {
                    material = child.GetComponent<Renderer>().material;
                }
            }
        }

        return material;
    }
}

This code make an object to fade out/in by changing the alpha color.

The problem is in the function FadeTo when the variable targetOpacity value is 1 then in the Update the variable teleported is true all the time so it’s starting the coroutine over and over again and also the property NavMeshAgent is never enabled true again in the FadeTo :

if(targetOpacity == 1)
        {
            myother.GetComponent<NavMeshAgent>().enabled = false;
        }

Now there are only two teleporters in the List and I can’t make a simple teleporting of the object/s between them. I want to teleport an object from teleporters[1] to teleporters[0] this flag teleported is not working as I thought it will.

Hi DubiDuboni,

I think the problem comes from the fact that the teleportation is never actually stopped. In Update, all that is required to start the coroutine FadeTo is that the flag teleported is true. At the end of the coroutine, the flag is assigned to true, which enables it to start again.

Also, all the information for the object to teleport are instance variables, which means thek keep their value until you reassign them, which explains why the same object can be teleported in loop. Try setting teleported with true only when there is a collision (I guess teleportation is trigged when an object collide with the teleporter). By doing so the condition in Update will only execute right after a collision occured, and when a new collision occur, the class field will be updated before starting the coroutine, so the right object will have the animation.

1 Like