Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
160 views
in Technique[技术] by (71.8m points)

c# - Coroutine not working from inside an instantiated object

I'm creating some lines of many diffent rectangles. Both lines and rectangles are created by code. I do some logic with the rectangle's vertices and update that information in my instantiated rectangles. This works really well.

Then on each rectangle I have 2 scripts, one storing data and the other storing a corutine to make the rectangle flash or stop flashing when certain conditions are met after lines and rectangles move possitions.

It does not work, it might have to be done with some other outside scripts and even diccionaries or lists, but as I'm new to coroutines I would like to know if it's possible to do it from each instantiated object by simply checking those bool and int variables as they change during the game.

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

public class rectanguloAnim : MonoBehaviour{
rectangulo rect; //script containing data from this rectangle

Color32 colOrig;
Material material;
IEnumerator currentFlashCoroutine;



void Start()
{
    rect = GetComponent<rectangulo>();
    colOrig = GetComponent<rectangulo>().colorOriginal;
    material = GetComponent<Renderer>().material;
}


void Update()
{
    // this bool and int change when the line and rect are interacted with
    if (rect.isIntermediate == true || rect.activeDirection != 0)
    {
        if (currentFlashCoroutine != null)
        {
            StopCoroutine(currentFlashCoroutine);
        }

        currentFlashCoroutine = ChangeColor(material, colOrig, Color.white);
        StartCoroutine(currentFlashCoroutine);
    }
    else
    {
        if (currentFlashCoroutine != null)
        {
            StopCoroutine(currentFlashCoroutine);
        }
    }


}

IEnumerator ChangeColor(Material toChange, Color32 startColor, Color32 endColor)
{
    float t = 0;
    float colorDuration = Random.Range(2.49f, 6f);

    while (t < colorDuration)
    {
        float timeDuration = Random.Range(.55f, .95f);
        if (t > timeDuration)
        {
            t = 0;
        }

        t += Time.deltaTime;
        toChange.color = Color.Lerp(startColor, endColor, t / colorDuration);
        yield return null;
    }
}

}

question from:https://stackoverflow.com/questions/65888939/coroutine-not-working-from-inside-an-instantiated-object

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think you should rather make your field

private Coroutine currentFlashCoroutine;

and then use

currentcurrentFlashCoroutine = StartCoroutine(ChangeColor(material, colOrig, Color.white);

and then do

if(currentFlashCoroutine != null)
{
    StopCoroutine (currentFlashCoroutine);
    currentFlashCoroutine = null;
}

Btw in doubt you could also use StopAllCoroutines since in your use case you seem to anyway only have a single routine in your class ;)


The second issue here is that you are stopping and starting a new routine every frame as long the condition is true.

You would rather do somthing like

void Update()
{
    // this bool and int change when the line and rect are interacted with
    if (rect.isIntermediate || rect.activeDirection != 0)
    {
        // only start a new routine if there is not already one running
        if(currentFlashCoroutine == null)
        {
            currentFlashCoroutine = StartCoroutine(ChangeColor(material, colOrig, Color.white);
        }
    }
    else
    {
        if(currentFlashCoroutine != null)
        {
            StopCoroutine (currentFlashCoroutine);
            currentFlashCoroutine = null;
        }
    }
}

IEnumerator ChangeColor(Material toChange, Color32 startColor, Color32 endColor)
{
    var t = 0f;
    var colorDuration = Random.Range(2.49f, 6f);

    while (t < colorDuration)
    {
        var timeDuration = Random.Range(.55f, .95f);
        if (t > timeDuration)
        {
            t = 0;
        }

        t += Time.deltaTime;
        toChange.color = Color.Lerp(startColor, endColor, t / colorDuration);
        yield return null;
    }

    currentFlashRoutine = null;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...