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

基于_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:10:23