Unity Update函数中变量初始化:文本淡入淡出重复执行问题
解决Unity文本淡入淡出无法重复触发的问题
嘿,我完全懂你遇到的困扰——第一次运行时淡入淡出效果正常,但之后就再也触发不了,对吧?这问题的核心其实是你的控制变量没有在每次触发淡入淡出前重置,再加上时间判断逻辑只在第一次进入Level1时生效,后续就再也满足不了条件了。我来帮你一步步解决这个问题:
先分析原有代码的问题点
- 变量未重置:
fades和fadex只在初始化时设为0和1,完成一次淡入淡出后就停在1和0,下次调用函数时if(fades <1)或if(fadex>0)的条件直接不满足,自然没效果。 - 时间变量持续累加:
time一直在加,不会重置,后续即使回到Level1,时间早就超过5秒了,触发判断的条件永远不成立。 - 低效的组件获取:每次
Update()都调用GetComponent<Text>(),这会浪费性能,应该只在初始化时获取一次。 - 颜色值不规范: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
相关产品推荐
相关产品推荐

