简体   繁体   English

在 Unity3D 中使用协程淡出游戏 object,然后再淡入。无限循环

[英]Using a Coroutine in Unity3D to fade a game object out, and back in. Looping infinitely

I'm trying to get a game object in Unity 3D to fade out(fade speed should be adjustable from editor), pause/wait 2 seconds (pause length be adjustable from editor), and fade back in, looping infinitely.我正在尝试让 Unity 3D 中的游戏 object 淡出(淡出速度应该可以从编辑器中调整),暂停/等待 2 秒(暂停长度可以从编辑器中调整),然后淡入,无限循环。 Coroutine is what I'm trying to utilize here to decrease alpha value but I'm unsure of exactly where I'm making my errors. Coroutine 是我在这里试图用来降低 alpha 值的东西,但我不确定我到底在哪里犯了错误。

I'm getting a single error.我收到一个错误。 (Cannot convert method group "FadeOut" to non-delegate type "object") (无法将方法组“FadeOut”转换为非委托类型“object”)

Here is my code:这是我的代码:

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

public class ScriptFader : MonoBehaviour
{
    // attached game object for fading
    public GameObject Sphere;

    // fade speed length
    public float fadeSpeed;

    //Pause length between fades
    public int fadePause;

    void Awake()
    {
        StartCoroutine(FadeOut(fadeSpeed));
    }


    //Fade Out Coroutine
    public IEnumerator FadeOut(float fadeSpeed)
    {
        Renderer rend = Sphere.transform.GetComponent<Renderer>();
        Color matColor = rend.material.color;
        float alphaValue = rend.material.color.a;


        //while loop to deincrement Alpha value until object is invisible
        while (rend.material.color.a > 0f)
        {
            alphaValue -= Time.deltaTime / fadeSpeed;
            rend.material.color = new Color(matColor.r, matColor.g, matColor.b, alphaValue);
            yield return new WaitForSeconds(fadePause);
        }
        rend.material.color = new Color(matColor.r, matColor.g, matColor.b, 0f);
        StartCoroutine(FadeIn(fadeSpeed));
    }

    //Fade In Coroutine
    public IEnumerator FadeIn(float fadeSpeed)
    {
        //waits for the return value of FadeOut coroutine to commence
        yield return FadeOut;

        Renderer rend = Sphere.transform.GetComponent<Renderer>();
        Color matColor = rend.material.color;
        float alphaValue = rend.material.color.a;


        //while loop to increment object Alpha value until object is opaque
        while(rend.material.color.a < 1f)
        {
            alphaValue += Time.deltaTime / fadeSpeed;
            rend.material.color = new Color(matColor.r, matColor.g, matColor.b, alphaValue);
            yield return null;
        }
        rend.material.color = new Color(matColor.r, matColor.g, matColor.b, 1f);
        StartCoroutine(FadeOut(fadeSpeed));
    }
}

I second Pluto's answer , but I would approach Fade() a little differently:支持 Pluto 的回答,但我会以不同的方式处理Fade()

private IEnumerator Fade()
{
    Renderer rend = Sphere.transform.GetComponent<Renderer>();
    Color initialColor = rend.material.color;
    Color targetColor = new Color(initialColor.r, initialColor.g, initialColor.b, 0f);

    float elapsedTime = 0f;

    while (elapsedTime < fadeDuration)
    {
        elapsedTime += Time.deltaTime;
        rend.material.color = Color.Lerp(initialColor, targetColor, elapsedTime / fadeDuration);
        yield return null;
    }
}

You can, of course, pass in the material and the two colors as arguments. That'd be cleaner.当然,您可以将材料和两个 colors 作为 arguments 传递。这样会更干净。 But the logic inside this while loop is, I think, a little easier to understand, as well as more common and ubiquitous, and it lets you explicitly set how long you want the fade animation to take.但是我认为这个 while 循环中的逻辑更容易理解,也更常见和无处不在,它允许您明确设置淡出 animation 需要多长时间。

Lerp() stands for "linear interpolation". Lerp()代表“线性插值”。 If you're not familiar with it, I suggest you learn it;如果你不熟悉它,我建议你学习它; you'll be using it everywhere.你会在任何地方使用它。

For example, if you have black as the starting color and white as the target, putting 1/2 as the third argument would get you the shade of gray right in-between;例如,如果您将黑色作为起始颜色,将白色作为目标颜色,则将 1/2 作为第三个参数将使您获得介于两者之间的灰色阴影; 3/4 would be closer to white, and 1/4 closer to black. 3/4 更接近白色,1/4 更接近黑色。

You can use it for colors as Color.Lerp() , but also numbers, vectors, and essentially any value that lives on a spectrum.您可以将它用于 colors 作为Color.Lerp() ,也可以用于数字、向量,以及本质上存在于频谱上的任何值。

You could just write a coroutine that controls the effect:你可以只写一个协程来控制效果:

void Start() => StartCoroutine(FadeInOut());  

IEnumerator FadeInOut()
{
    var material = Sphere.GetComponent<Renderer>().material;
    //forever
    while (true)
    {
        // fade out
        yield return Fade(material, 0);
        // wait
        yield return new WaitForSeconds(fadePause);
        // fade in
        yield return Fade(material, 1);  
        // wait
        yield return new WaitForSeconds(fadePause);
    }
}

IEnumerator Fade(Material mat, float targetAlpha)
{
    while(mat.color.a != targetAlpha)
    {
        var newAlpha = Mathf.MoveTowards(mat.color.a, targetAlpha, fadeSpeed * Time.deltaTime);
        mat.color = new Color(mat.color.r, mat.color.g, mat.color.b, newAlpha);
        yield return null;
    }
}

Your error is here (as I'm sure your stack trace would have shown):您的错误在这里(因为我确定您的堆栈跟踪会显示):

//Fade In Coroutine
public IEnumerator FadeIn(float fadeSpeed)
{
    //waits for the return value of FadeOut coroutine to commence
    yield return FadeOut; // !!! ERROR

You're missing the actual call to the function (the parentheses).您错过了对 function(括号)的实际调用。 I'm not actually sure what you intended with that line... does it need to exist at all?我实际上不确定您对该行的意图......它是否需要存在?


But honestly, Coroutines are overkill for simple cyclers (in your case, an Alpha cycle).但老实说,Coroutines 对于简单的循环程序(在你的例子中,是一个 Alpha 循环)来说有点过分了。 See font size with coroutines for an example.有关示例,请参见协程的字体大小

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM