【Unity】Unity GameObject渐变透明效果实现:通过代码动态修改材质透明度,实现自然流畅的淡入淡出效果

在 Unity 的日常开发中,我们经常会遇到需要显示或隐藏一个物体的场景。默认情况下,使用 SetActive()enabled 方法虽然能立即控制物体是否可见,但切换时过于突兀。如果能通过渐变透明度的方式来控制物体的显隐,将极大提升视觉体验。

本文将详细讲解如何在 Unity 的 URP(通用渲染管线)中,使用脚本动态控制材质透明度,实现渐变的显隐效果。


一、为什么不能用 SetActive() 实现渐隐/渐显?

在 Unity 中,SetActive(false) 会直接将 GameObject 从场景中禁用,包括它的渲染、脚本执行、碰撞体等所有行为,这种方式适用于逻辑性强、对性能要求高的场景。但它带来的问题也很明显:

  • 画面会瞬间消失,没有过渡效果;
  • 无法插入动画或渐变;
  • 禁用状态下无法再通过材质控制其透明度;

因此,如果我们希望让物体 逐渐显现或消失,最佳做法是通过材质透明度来控制物体可见性。


二、URP 中透明材质的设置方式

在标准渲染管线(Built-in)中,我们可以使用 Standard Shader 设置 Rendering ModeTransparent。但在 URP 中,Shader 和材质系统进行了重构,我们必须使用 Universal Render Pipeline/Lit 这类新 Shader,并手动设置材质透明属性。

2.1 手动设置 URP 材质为透明

  1. 选中你的 Material;
  2. Shader 选择:Universal Render Pipeline/Lit;
  3. 找到 Surface Type,选择 Transparent
  4. 调整 Base Map 或 Base Color 的 Alpha 值,即可控制透明度。

这样设置后,材质就能响应我们通过代码设置的透明值,产生渐变效果。


三、通过代码修改透明度的核心逻辑

为了实现渐变效果,我们需要在脚本中动态修改材质的透明度,并确保材质处于透明状态。

下面是完整的实现流程:

3.1 获取材质并设置为透明模式

private void SetMaterialTransparent(Material material)
{
    
    
    material.SetFloat("_Surface", 1); // 1 = Transparent
    material.SetFloat("_Blend", 0); // Alpha blending
    material.SetFloat("_ZWrite", 0); // 不写入深度缓冲
    material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
}

这个方法确保材质从 Opaque 转为 Transparent,并设置适当的混合模式和渲染顺序。

3.2 修改材质颜色的 Alpha 值

URP 中的 Lit Shader 使用 _BaseColor 属性表示主颜色,因此我们要修改这个值的 Alpha 分量:

private void SetAlpha(Material material, float alpha)
{
    
    
    if (material.HasProperty("_BaseColor"))
    {
    
    
        Color color = material.GetColor("_BaseColor");
        color.a = Mathf.Clamp01(alpha);
        material.SetColor("_BaseColor", color);
    }
}

四、渐隐 / 渐显效果实现:完整组件

我们可以将上面的逻辑封装成一个脚本组件,挂载到任意带有 MeshRenderer 的 GameObject 上。

4.1 完整脚本:URPTransparencyController.cs

using UnityEngine;
using System.Collections;

public class URPTransparencyController : MonoBehaviour
{
    
    
    public float fadeDuration = 1.0f;
    private Material material;

    private void Start()
    {
    
    
        material = GetComponent<Renderer>().material;
        SetMaterialTransparent(material);
        SetAlpha(material, 0f); // 初始为透明
    }

    public void FadeTo(float targetAlpha)
    {
    
    
        StartCoroutine(FadeCoroutine(targetAlpha));
    }

    private IEnumerator FadeCoroutine(float targetAlpha)
    {
    
    
        float startAlpha = material.GetColor("_BaseColor").a;
        float time = 0f;

        while (time < fadeDuration)
        {
    
    
            float alpha = Mathf.Lerp(startAlpha, targetAlpha, time / fadeDuration);
            SetAlpha(material, alpha);
            time += Time.deltaTime;
            yield return null;
        }

        SetAlpha(material, targetAlpha);
    }

    private void SetMaterialTransparent(Material mat)
    {
    
    
        mat.SetFloat("_Surface", 1); // Transparent
        mat.SetFloat("_Blend", 0);   // Alpha blending
        mat.SetFloat("_ZWrite", 0);
        mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
        mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
    }

    private void SetAlpha(Material mat, float alpha)
    {
    
    
        Color color = mat.GetColor("_BaseColor");
        color.a = Mathf.Clamp01(alpha);
        mat.SetColor("_BaseColor", color);
    }
}

五、调用方式示例

// 渐显
GetComponent<URPTransparencyController>().FadeTo(1f);

// 渐隐
GetComponent<URPTransparencyController>().FadeTo(0f);

你还可以通过按钮点击、UI 滑块、触发器等方式调用这些方法,实现交互式控制。


六、进阶拓展:渐变后自动隐藏对象

有时候你希望在透明度降为 0 后,将对象禁用以节省性能,可以在 FadeCoroutine 中加一个回调:

if (targetAlpha == 0f)
{
    
    
    gameObject.SetActive(false);
}

当然,你也可以用 UnityEvent 触发其他逻辑,例如:

public UnityEvent onFadeOutComplete;

七、常见问题排查

问题 原因
改变透明度没效果 材质未设置为 Transparent 模式
所有物体都变透明 多个对象共用同一个材质,未使用 .material
材质突然变黑/失真 渲染模式设置不当,可能没有启用混合模式
渐变期间无法交互 使用透明材质时 ZWrite 为 0,可能遮挡关系异常

八、小结

本文完整介绍了如何在 Unity 的 URP 环境中,通过代码控制材质透明度,平滑实现 GameObject 的显隐过渡。相比直接使用 SetActive(),这种方式更加自然、精细,适用于游戏中的过场动画、淡入淡出特效、UI 元素动态出现等各种场景。


猜你喜欢

转载自blog.csdn.net/qq_41140324/article/details/147108526
今日推荐