基于_Glow参数实现Unity纹理3秒淡入淡出过渡的技术问题
解决方案
要实现旧纹理3秒淡出→切换纹理→新纹理3秒淡入的平滑过渡,不需要拆分两个协程,用单个协程分阶段处理更简洁。以下是优化后的代码及关键说明:
关键改进点
- 用
Mathf.Lerp实现稳定的插值过渡,避免帧率影响过渡速度 - 分三步执行:淡出旧纹理→切换纹理→淡入新纹理
- 触发新过渡时停止旧协程,防止多协程冲突
- 移除了原代码中重复使用同一协程实例的错误逻辑
修改后的完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class VFXController : MonoBehaviour { private AssetBundle assetBundle; private Texture nextTexture; private Renderer renderer; public GameObject visual; // 定义过渡时长(淡出/淡入各3秒)和目标Glow值 private const float FadeDuration = 3f; private const float TargetGlowValue = 12.6f; void Start() { assetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "session_vfx_textures")); if (assetBundle == null) { Debug.Log("Failed to load AssetBundle!"); return; } renderer = visual.GetComponent<Renderer>(); // 初始化Glow值为目标值,确保初始状态正确 renderer.material.SetFloat("_Glow", TargetGlowValue); InitEvents(); } private void InitEvents() { EventsManager.current.onChangeVFXTexture += ChangeTexture; } private void OnDestroy() { EventsManager.current.onChangeVFXTexture -= ChangeTexture; assetBundle?.Unload(true); // 记得卸载AssetBundle避免内存泄漏 } private void ChangeTexture(SessionNames name) { nextTexture = assetBundle.LoadAsset<Texture>(name.ToString()); if (nextTexture == null) { Debug.LogWarning($"Texture {name.ToString()} not found in AssetBundle!"); return; } // 停止当前正在执行的过渡协程,防止多次触发导致冲突 StopAllCoroutines(); StartCoroutine(TextureTransitionCoroutine()); } private IEnumerator TextureTransitionCoroutine() { // 1. 旧纹理淡出:3秒内从当前Glow值降到0 float startGlow = renderer.material.GetFloat("_Glow"); for (float t = 0f; t < FadeDuration; t += Time.deltaTime) { float normalizedProgress = t / FadeDuration; float currentGlow = Mathf.Lerp(startGlow, 0f, normalizedProgress); renderer.material.SetFloat("_Glow", currentGlow); yield return null; } // 强制设置最终值,避免浮点误差 renderer.material.SetFloat("_Glow", 0f); // 2. 切换到新纹理 renderer.material.SetTexture("_MainTex", nextTexture); // 3. 新纹理淡入:3秒内从0升到目标Glow值 for (float t = 0f; t < FadeDuration; t += Time.deltaTime) { float normalizedProgress = t / FadeDuration; float currentGlow = Mathf.Lerp(0f, TargetGlowValue, normalizedProgress); renderer.material.SetFloat("_Glow", currentGlow); yield return null; } // 强制设置最终值 renderer.material.SetFloat("_Glow", TargetGlowValue); } }
可选拆分协程方案
如果需要单独控制淡出/淡入逻辑(比如后续要扩展各自的动画曲线),可以拆成两个独立协程:
private IEnumerator FadeOutCoroutine() { float startGlow = renderer.material.GetFloat("_Glow"); for (float t = 0f; t < FadeDuration; t += Time.deltaTime) { float normalizedProgress = t / FadeDuration; renderer.material.SetFloat("_Glow", Mathf.Lerp(startGlow, 0f, normalizedProgress)); yield return null; } renderer.material.SetFloat("_Glow", 0f); renderer.material.SetTexture("_MainTex", nextTexture); StartCoroutine(FadeInCoroutine()); } private IEnumerator FadeInCoroutine() { for (float t = 0f; t < FadeDuration; t += Time.deltaTime) { float normalizedProgress = t / FadeDuration; renderer.material.SetFloat("_Glow", Mathf.Lerp(0f, TargetGlowValue, normalizedProgress)); yield return null; } renderer.material.SetFloat("_Glow", TargetGlowValue); }
在ChangeTexture方法中启动FadeOutCoroutine即可,这种方式适合需要对两段过渡逻辑做差异化扩展的场景。
内容的提问来源于stack exchange,提问作者Ando
相关产品推荐
相关产品推荐

