【Unity高级】如何动态调整物体透明度

news/2024/12/12 2:59:13/

本文介绍了如何设置及动态调整物体的透明度。

一、手动设置的方法

我们先来看下如何手动设置物体的透明度。

物体的透明与否是通过材质来设置的。只有我们把具有透明度的材质指给物体的渲染器(Render),物体就被设置成相应的透明度了。

看一下上面半透明(左二)物体的材质设置。

(1)将材质的Surface Type设置为Transparent,Blending Mode设置为Alpha。

(2)点开Base Map,(3)调整A值(Alpha通道)来改变透明度

(4)也可以调整物体表面光滑度,调整材质效果(比如玻璃)。

二、使用代码设置

如果我们想在运行时动态调整物体的透明度的话,可以通过设置材质的相关参数来实现。

两个核心方法如下:

1. SetMaterialOpaque() - 设置材质为不透明

当透明度值大于或等于 1 时,调用此方法将材质设置为不透明。

    private void SetMaterialOpaque(){targetMaterial.SetFloat("_Surface", 0); // 设置材质为不透明,0 = OpaquetargetMaterial.SetOverrideTag("RenderType", "Opaque"); // 设置渲染类型标签为不透明targetMaterial.SetInt("_Blend", 0); // 设置混合模式为不透明targetMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); // 设置源混合模式为 OnetargetMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); // 设置目标混合模式为 ZerotargetMaterial.SetInt("_ZWrite", 1); // 启用深度缓冲区写入(不透明物体需要写入深度缓冲区)targetMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; // 设置渲染队列为几何体渲染队列(不透明物体)targetMaterial.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); // 禁用透明表面类型关键字Color color = targetMaterial.GetColor("_BaseColor"); // 获取材质的基础颜色color.a = 1f; // 设置透明度为 1,完全不透明targetMaterial.SetColor("_BaseColor", color); // 更新材质的颜色}
  • 设置材质属性
    • targetMaterial.SetFloat("_Surface", 0):将材质的 _Surface 属性设置为 0,表示材质为不透明(Opaque)。

    • targetMaterial.SetOverrideTag("RenderType", "Opaque"):设置渲染类型标签为不透明。

    • targetMaterial.SetInt("_Blend", 0)targetMaterial.SetInt("_SrcBlend", 1)targetMaterial.SetInt("_DstBlend", 0):这些设置指定了混合模式为不透明(没有透明度混合)。

    • targetMaterial.SetInt("_ZWrite", 1):启用 Z 缓冲区写入(不透明物体需要写入深度缓冲区)。

    • targetMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry:设置渲染队列为几何体渲染队列(不透明物体通常在此队列中渲染)。

    • Color color = targetMaterial.GetColor("_BaseColor"); color.a = 1f; targetMaterial.SetColor("_BaseColor", color);:设置材质的颜色透明度为 1,表示完全不透明。

2. SetMaterialTransparent(float alpha) - 设置材质为透明

当透明度值小于 1 时,调用此方法将材质设置为透明,并根据透明度值调整材质的透明度。

 private void SetMaterialTransparent(float alpha){targetMaterial.SetFloat("_Surface", 1); // 设置材质为透明,1 = TransparenttargetMaterial.SetOverrideTag("RenderType", "Transparent"); // 设置渲染类型标签为透明targetMaterial.SetInt("_Blend", 1); // 设置混合模式为透明targetMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); // 设置源混合模式为源透明度targetMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); // 设置目标混合模式为 1 - 源透明度targetMaterial.SetInt("_ZWrite", 0); // 禁用深度缓冲区写入(透明物体通常不写入深度缓冲区)targetMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; // 设置渲染队列为透明物体渲染队列targetMaterial.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); // 启用透明表面类型关键字Color color = targetMaterial.GetColor("_BaseColor"); // 获取材质的基础颜色color.a = alpha; // 设置透明度为传入的 alpha 值targetMaterial.SetColor("_BaseColor", color); // 更新材质的颜色}
  • 设置材质属性

    • targetMaterial.SetFloat("_Surface", 1):将材质的 _Surface 属性设置为 1,表示材质为透明(Transparent)。
    • targetMaterial.SetOverrideTag("RenderType", "Transparent"):设置渲染类型标签为透明。
    • targetMaterial.SetInt("_Blend", 1)targetMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha)targetMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha):这些设置指定了透明物体的混合模式(使用源透明度和目标透明度的反向混合)。
    • targetMaterial.SetInt("_ZWrite", 0):禁用 Z 缓冲区写入(透明物体通常不写入深度缓冲区,以便能够看到背后的物体)。
    • targetMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent:设置渲染队列为透明物体渲染队列。
    • targetMaterial.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"):启用透明表面类型的关键词。
  • 透明度值调整

    • Color color = targetMaterial.GetColor("_BaseColor"); color.a = alpha; targetMaterial.SetColor("_BaseColor", color);:根据传入的 alpha 值(透明度)设置材质的颜色透明度。alpha 在 0 到 1 之间,0 表示完全透明,1 表示完全不透明。

动态调整的话,核心就是在触发时,通过调整color.a的值来实现。

三、完整代码

上面示例中使用滑动条来调整透明度的完整代码如下:

using UnityEngine;
using UnityEngine.UI;public class MaterialTransparencySlider : MonoBehaviour
{private Material targetMaterial; // 当前对象的材质private MeshRenderer meshRenderer; // 用于控制影子public Slider transparencySlider; // Slider 控件public Text textOpacity;void Start(){// 获取 MeshRenderermeshRenderer = GetComponent<MeshRenderer>();if (meshRenderer != null){targetMaterial = meshRenderer.material; // 获取材质实例}else{Debug.LogError("未找到 GameObject 上的 MeshRenderer。");return;}if (transparencySlider != null){// 监听 Slider 值变化事件transparencySlider.onValueChanged.AddListener(UpdateMaterialTransparency);// 初始化材质状态UpdateMaterialTransparency(transparencySlider.value);}else{Debug.LogError("未分配透明度滑动条 (Slider)。");}}/// <summary>/// 根据 Slider 的值动态更新材质透明度/// </summary>/// <param name="value">Slider 的当前值(范围 0-1)</param>public void UpdateMaterialTransparency(float value){if (targetMaterial == null || meshRenderer == null) return;if (value >= 1f){// 设置材质为完全不透明SetMaterialOpaque();}else{// 设置材质为透明,并调整透明度SetMaterialTransparent(value);}// 更新影子状态UpdateShadows(value);// 更新texttextOpacity.text = $"透明度={value * 100}";}/// <summary>/// 设置材质为完全不透明/// </summary>private void SetMaterialOpaque(){targetMaterial.SetFloat("_Surface", 0); // 设置材质为不透明,0 = OpaquetargetMaterial.SetOverrideTag("RenderType", "Opaque"); // 设置渲染类型标签为不透明targetMaterial.SetInt("_Blend", 0); // 设置混合模式为不透明targetMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); // 设置源混合模式为 OnetargetMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); // 设置目标混合模式为 ZerotargetMaterial.SetInt("_ZWrite", 1); // 启用深度缓冲区写入(不透明物体需要写入深度缓冲区)targetMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; // 设置渲染队列为几何体渲染队列(不透明物体)targetMaterial.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); // 禁用透明表面类型关键字Color color = targetMaterial.GetColor("_BaseColor"); // 获取材质的基础颜色color.a = 1f; // 设置透明度为 1,完全不透明targetMaterial.SetColor("_BaseColor", color); // 更新材质的颜色}/// <summary>/// 设置材质为透明,并动态调整透明度/// </summary>/// <param name="alpha">透明度值(0-1)</param>private void SetMaterialTransparent(float alpha){targetMaterial.SetFloat("_Surface", 1); // 设置材质为透明,1 = TransparenttargetMaterial.SetOverrideTag("RenderType", "Transparent"); // 设置渲染类型标签为透明targetMaterial.SetInt("_Blend", 1); // 设置混合模式为透明targetMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); // 设置源混合模式为源透明度targetMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); // 设置目标混合模式为 1 - 源透明度targetMaterial.SetInt("_ZWrite", 0); // 禁用深度缓冲区写入(透明物体通常不写入深度缓冲区)targetMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; // 设置渲染队列为透明物体渲染队列targetMaterial.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); // 启用透明表面类型关键字Color color = targetMaterial.GetColor("_BaseColor"); // 获取材质的基础颜色color.a = alpha; // 设置透明度为传入的 alpha 值targetMaterial.SetColor("_BaseColor", color); // 更新材质的颜色}/// <summary>/// 动态更新影子显示状态/// </summary>/// <param name="alpha">透明度值(0-1)</param>private void UpdateShadows(float alpha){if (alpha <= 0f){// 完全透明时禁用影子meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;}else{// 非完全透明时启用影子meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;}}private void OnDestroy(){// 移除监听事件以避免内存泄漏if (transparencySlider != null){transparencySlider.onValueChanged.RemoveListener(UpdateMaterialTransparency);}}
}

四、存在的问题

1. 可见问题:球1是手动设置的完全透明的材质,它与球4透明度为0时的状态还是有区别的。球1是可见的,而球4是完全不可见的。

2. 影子问题:球1和球2,是手动设置的透明材质,没有影子。球4在动态设置为透明材质时,仍然会有影子。最后透明度为0时影子消失,是在代码里处理的。

这两上问题有待进一下研究。


http://www.ppmy.cn/news/1554383.html

相关文章

石头剪子布

石头剪子布 C语言实现C实现Java实现Python实现 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 石头剪子布&#xff0c;是一种猜拳游戏。起源于中国&#xff0c;然后传到日本、朝鲜等地&#xff0c;随着亚欧贸易的不断发展它传到了欧洲&…

三、【docker】docker和docker-compose的常用命令

文章目录 一、docker常用命令1、镜像管理2、容器管理3、容器监控和调试4、网络管理5、数据卷管理6、系统维护7、实用组合命令8、常用技巧二、docker-compose常用命令1、基本命令2、构建相关3、运行维护4、常用组合命令5、实用参数 一、docker常用命令 1、镜像管理 # 查看本地…

力扣--LCR 177.撞色搭配

题目 整数数组 sockets 记录了一个袜子礼盒的颜色分布情况&#xff0c;其中 sockets[i] 表示该袜子的颜色编号。礼盒中除了一款撞色搭配的袜子&#xff0c;每种颜色的袜子均有两只。请设计一个程序&#xff0c;在时间复杂度 O(n)&#xff0c;空间复杂度O(1) 内找到这双撞色搭配…

酷柚易汛进销存系统PHP+Uniapp

移动端订货通、商品管理、库存管理、订单管理、客户管理、供应商、财务管理、经营分析 版本更新V1.6.4 1、新增供应商分类不可添加重复类别2、新增客户分类不可添加重复类别3、新增商品分类不可添加重复类别4、新增支出类别不可添加重复类别5、新增收入类别不可添加重复类别6…

21天掌握javaweb-->第13天:Docker容器化部署与微服务简介

Docker基础与Spring Boot应用的容器化部署 Docker的基本概念&#xff1a; Docker是一个开源的应用容器引擎&#xff0c;它使得应用的打包、分发和运行变得更加简单。容器是Docker使用的封装应用及其运行环境的轻量级、可移植的单元。 Docker的核心组件&#xff1a; 镜像&…

【23种设计模式】原型模式:理论剖析与Java实践

文章目录 原型模式&#xff1a;理论剖析与 Java 实践应用一、原型模式概述二、Java 实现示例&#xff08;一&#xff09;原型接口&#xff08;二&#xff09;具体原型类 三、关键步骤&#xff08;一&#xff09;创建原型对象&#xff08;二&#xff09;克隆原型对象 四、流程图…

PTL系统助力新能源汽车生产线的物料精准管理

在新能源汽车生产线蓬勃发展的当下&#xff0c;多车型混合生产模式已成为行业常态。传统的物料管理方式在面对多种型号新能源汽车生产时&#xff0c;由于缺乏精准的指引和高效的防错机制&#xff0c;常常出现物料错拿导致产品不良&#xff0c;以及因核对物料耗费大量时间而造成…

selenium常见接口函数使用

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;测试_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 1. 查找 查找方式 css_s…