You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Update函数中变量初始化:文本淡入淡出重复执行问题

解决Unity文本淡入淡出无法重复触发的问题

嘿,我完全懂你遇到的困扰——第一次运行时淡入淡出效果正常,但之后就再也触发不了,对吧?这问题的核心其实是你的控制变量没有在每次触发淡入淡出前重置,再加上时间判断逻辑只在第一次进入Level1时生效,后续就再也满足不了条件了。我来帮你一步步解决这个问题:

先分析原有代码的问题点

  1. 变量未重置:fades和fadex只在初始化时设为0和1,完成一次淡入淡出后就停在1和0,下次调用函数时if(fades <1)或if(fadex>0)的条件直接不满足,自然没效果。
  2. 时间变量持续累加:time一直在加,不会重置,后续即使回到Level1,时间早就超过5秒了,触发判断的条件永远不成立。
  3. 低效的组件获取:每次Update()都调用GetComponent<Text>(),这会浪费性能,应该只在初始化时获取一次。
  4. 颜色值不规范:Unity的Color类中r/g/b/a都是0-1的浮点数,你用255的话会被自动 clamp到1,虽然效果可能没问题,但规范写法应该用0-1的数值。

解决方案:用状态机+变量重置实现可重复触发

我给你重构了代码,加入了状态管理和变量重置逻辑,这样每次回到Level1都能重新触发淡入淡出:

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

public class StageSet : MonoBehaviour 
{
    Text stage;
    Created c; // 别直接new,建议通过Inspector赋值或Find获取场景中的实例
    float time = 0;
    float fadeAlpha = 0; // 用单个变量管理透明度,更简洁
    // 用状态枚举管理当前淡入淡出阶段
    enum FadeState { Idle, FadingIn, FadingOut, Completed }
    FadeState currentState = FadeState.Idle;

    void Start()
    {
        // 只初始化一次Text组件,提升性能
        stage = GetComponent<Text>();
        // 获取Created脚本的实例(推荐拖到Inspector面板赋值,更可靠)
        c = FindObjectOfType<Created>();
        // 初始化文本和颜色
        stage.text = "Stage " + c.getLevel();
        stage.color = new Color(1, 0, 0, fadeAlpha);
    }

    void Update () 
    {
        // 当回到Level1且当前无淡入淡出操作时,重置状态并启动流程
        if (c.getLevel() == 1 && currentState == FadeState.Idle)
        {
            currentState = FadeState.FadingIn;
            time = 0; // 重置时间计数器
            fadeAlpha = 0; // 重置透明度
            stage.text = "Stage " + c.getLevel(); // 确保文本同步最新关卡
        }

        time += Time.deltaTime;

        // 根据当前状态执行对应操作
        switch(currentState)
        {
            case FadeState.FadingIn:
                FadeIn();
                break;
            case FadeState.FadingOut:
                // 淡入后停留2秒再开始淡出(可自行调整时长)
                if(time > 2)
                {
                    FadeOut();
                }
                break;
            case FadeState.Completed:
                // 完成后可以隐藏文本或做其他操作
                break;
        }
    }

    void FadeIn()
    {
        // 用Time.deltaTime控制速度,保证不同帧率下效果一致
        fadeAlpha += Time.deltaTime * 0.5f; // 0.5是淡入速度,数值越大越快
        fadeAlpha = Mathf.Clamp01(fadeAlpha); // 确保透明度不超过1
        stage.color = new Color(1, 0, 0, fadeAlpha);

        // 淡入完成后切换到停留状态
        if(fadeAlpha >= 1)
        {
            currentState = FadeState.FadingOut;
            time = 0; // 重置时间计算停留时长
        }
    }

    void FadeOut()
    {
        fadeAlpha -= Time.deltaTime * 0.5f;
        fadeAlpha = Mathf.Clamp01(fadeAlpha);
        stage.color = new Color(1, 0, 0, fadeAlpha);

        // 淡出完成后回到Idle状态,等待下次触发
        if(fadeAlpha <= 0)
        {
            currentState = FadeState.Idle;
        }
    }

    // 提供公共方法,需要手动触发时调用(比如关卡重置按钮)
    public void ResetFade()
    {
        currentState = FadeState.Idle;
        time = 0;
        fadeAlpha = 0;
        stage.color = new Color(1, 0, 0, fadeAlpha);
        stage.text = "Stage " + c.getLevel();
    }
}

额外优化:用协程实现更简洁的逻辑

如果你觉得状态机有点繁琐,用Unity的协程可以写出更线性、易读的代码,同样支持重复触发:

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class StageSet : MonoBehaviour 
{
    Text stage;
    Created c;
    bool isFading = false; // 标记是否正在执行淡入淡出

    void Start()
    {
        stage = GetComponent<Text>();
        c = FindObjectOfType<Created>();
        stage.color = new Color(1, 0, 0, 0); // 初始透明
    }

    void Update () 
    {
        // 只有在Level1且无淡入淡出操作时触发
        if (c.getLevel() == 1 && !isFading)
        {
            stage.text = "Stage " + c.getLevel();
            StartCoroutine(FadeInOutSequence());
        }
    }

    // 协程管理淡入→停留→淡出的完整流程
    IEnumerator FadeInOutSequence()
    {
        isFading = true;
        float fadeDuration = 1f; // 淡入/淡出的时长(秒)
        float waitDuration = 2f; // 停留时长

        // 淡入过程:从0到1
        float elapsed = 0;
        while(elapsed < fadeDuration)
        {
            elapsed += Time.deltaTime;
            float alpha = Mathf.Lerp(0, 1, elapsed / fadeDuration);
            stage.color = new Color(1, 0, 0, alpha);
            yield return null; // 等待下一帧
        }

        // 停留指定时长
        yield return new WaitForSeconds(waitDuration);

        // 淡出过程:从1到0
        elapsed = 0;
        while(elapsed < fadeDuration)
        {
            elapsed += Time.deltaTime;
            float alpha = Mathf.Lerp(1, 0, elapsed / fadeDuration);
            stage.color = new Color(1, 0, 0, alpha);
            yield return null;
        }

        isFading = false; // 标记完成,允许下次触发
    }

    // 手动触发方法
    public void TriggerFade()
    {
        if(!isFading)
        {
            StopAllCoroutines(); // 停止当前可能在运行的协程
            StartCoroutine(FadeInOutSequence());
        }
    }
}

关键修复点总结

  • 重置变量:每次触发淡入淡出前,把时间计数器、透明度变量都重置回初始值。
  • 状态管理:用状态枚举或布尔标记,避免重复触发同一流程。
  • 帧率无关:用Time.deltaTime控制淡入淡出速度,保证不同设备上效果一致。
  • 组件复用:只在Start()中获取一次Text组件,减少性能消耗。

内容的提问来源于stack exchange,提问作者FlowORemi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:28:15