首页 > 解决方案 > 第一次完成后如何重新启动协程?

问题描述

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 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;
    }

第一次协程在 OnTriggerEnter 内部启动并将 alpha 颜色更改为 0 第二次是在 Update 中并将 alpha 颜色更改为 1

但是有一个问题。更新中的协程重新开始,在将 alpha 颜色更改为 1 后,传送始终为真。

是什么也使 NavMeshAgent 组件永远不会再次启用。

标签: c#unity3d

解决方案


最简单的方法是在您的协程本身中放置一个循环,只需将整个事情包装在一个 do-while 语句中,并在/如果您需要通过 while 条件退出协程。

或者,StartCoroutine 方法返回实际运行的协程的值,您可以存储并检查协程是否已完成返回值。


推荐阅读