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

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

一、手动设置的方法

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

物体的透明与否是通过材质来设置的。只有我们把具有透明度的材质指给物体的渲染器(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.xdnf.cn/news/35727.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

相机动态/在线标定

图1 图2 基本原理 【原理1】平行线在射影变换后会交于一点。如图所示,A为相机光心,蓝色矩形框为归一化平面,O为平面中心。地面四条黄色直线为平行且等距的车道线。HI交其中两条车道线于H、I, 过G作HI的平行线GM交车道线于M。HI、GM在归一化平面上的投影分别为JK、PN,二者会…

通俗易懂理解:网络安全恶意节点的检测与哨兵节点的激活【论文+代码】

以下资料参考来自本文末尾的参考资料与代码&#xff1a; 在网络安全中&#xff0c;恶意节点检测和哨兵节点激活是确保网络稳定性、可靠性和安全性的关键技术&#xff0c;尤其是在分布式系统、物联网 (IoT)、区块链网络等环境中。下面将详细介绍这两个概念及其应用。 一、恶意…

python作业

1.D 2.B 3.D 4.C 5.B 6.D 7.D 8.B 9.D 10. A 11.D 12.C 13.√ 14.√ 16.√ 17.√ 18.None 19.([1,3],[2]) 20. 列表思维导图

Redis(上)

Redis 基础 什么是 Redis&#xff1f; Redis &#xff08;REmote DIctionary Server&#xff09;是一个基于 C 语言开发的开源 NoSQL 数据库&#xff08;BSD 许可&#xff09;。与传统数据库不同的是&#xff0c;Redis 的数据是保存在内存中的&#xff08;内存数据库&#xf…

LabVIEW气缸摩擦力测试系统

基于LabVIEW的气缸摩擦力测试系统实现了气缸在不同工作状态下摩擦力的快速、准确测试。系统由硬件平台和软件两大部分组成&#xff0c;具有高自动化、精确测量和用户友好等特点&#xff0c;可广泛应用于精密机械和自动化领域。 ​ 项目背景&#xff1a; 气缸作为舵机关键部件…

CentOS7.X 安装RustDesk自建服务器实现远程桌面控制

参照文章CentOS安装RustDesk自建服务器中间总有几个位置出错&#xff0c;经实践做个记录防止遗忘 一 环境&工具准备 1.1 阿里云轻量服务器、Centos7系统、目前最高1.1.11版本rustdesk-server-linux-amd64.zip 1.2 阿里云轻量服务器–安全组–开放端口&#xff1a;TCP(21…

工具篇:IDEA VFS 损害启动报错 com.intellij.util.io.CorruptedException 处理

文章目录 前言一、 idea 的 VFS是什么&#xff1f;二、解决方式&#xff1a;2.1 退出Idea 然后重新打开&#xff1a;2.2 手动清除Idea 缓存&#xff0c;让Idea 重新建立缓存&#xff1a;2.2.1 打开 Invalidate Caches / Restart 对话框:2.2.2 勾选要清除的缓存&#xff1a; 总结…

2.linux中调度kettle

一.准备转换&#xff0c;等会在linux中用 1.添加excel输入组件&#xff0c;并添加对应的文件 2.添加列拆分为多行组件 3.添加文本文件输出组件 4.保存转换 二.linux安装java 1.把jdk-8u144-linux-x64.tar.gz上传到linux的/lx目录下 2. 解压jdk包&#xff0c;然后配置环境变量…

第四节、电机定角度转动【51单片机-TB6600驱动器-步进电机教程】

摘要&#xff1a;本节介绍用电机转动角度计算步骤&#xff0c;从而控制步进电机转角 一、 计算过程 1.1 驱动器接收一个脉冲后&#xff0c;步进电机转动一步&#xff0c;根据驱动器设置的细分值 计算一个脉冲对应电机转动的角度step_x s t e p x s t e p X … … ① step_{x…

如何终身使用 100% 免费的服务器

作为开发人员,我们需要在云服务上运行和托管后端。有许多 BaaS(后端即服务)可用,但它们有一些限制。 如果我说我已经免费使用基于 Linux 的服务器超过 4-5 年了,那会怎样?是的,你没听错。我正在使用这台安装了 Ubuntu 20、24 GB RAM、4 个 CPU 和 200 GB 存储空间的 Lin…

【计算机组成原理】期末复习题库

5&#xff0e;主存储器和CPU之间增加cache的目的是 。 A&#xff0e;解决CPU和主存之间的速度匹配问题 B&#xff0e;扩大主存储器的容量 C&#xff0e;扩大CPU中通用寄存器的数量 D&#xff0e;既扩大主存容量又扩大CPU中通用寄存器的数量 在计算机系统中&#xff0c;CPU的速…

SAP中Smartforms 翻译越南语

点击打印预览 打印预览中确实是越南语 转出成PDF 成了乱码 SPAD中查询LP01其实是简体中文 换成LP02试试 显示看上去正常的 SPAD中的LP02 SU3可以设置自己的默认打印参数 查查Smartforms中的字体样式 是宋体&#xff0c;看上去不用为了越南文刻意改字体样式成TIMES 看这篇文章…

26.删除有序数组中的重复项 python

删除有序数组中的重复项 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a;题目链接 题解解题思路python实现代码解释提交结果 题目 题目描述 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现…

R语言 | 峰峦图 / 山脊图

目的&#xff1a;为展示不同数据分布的差异。 1. ggplot2 实现 # 准备数据 datmtcars[, c("mpg", "cyl")] colnames(dat)c("value", "type") head(dat) # value type #Mazda RX4 21.0 6 #Mazda RX4 Wag …

四川创新志成健康管理有限公司

四川创新志成健康管理有限公司 成都市青羊区广富路168号 公司简介 四川创新志成健康管理有限公司成立于2021年&#xff0c;公司专注体外诊断领域&#xff0c;致力为医学实验室、生产厂家、 经销商提供专业的学术、技术增值服务&#xff0c;涵盖免疫、生化、输血等检测领域&a…

系统级 I/O

Unix I/O **了解 Unix I/O 将帮助你理解其他的系统概念。**I/O 是系统操作不可或缺的一部分。我们经常遇到 I/O 和其他系统概念之间的循环依赖。例如&#xff0c;I/O 在进程的创建和执行中扮演着关键的角色。反过来&#xff0c;进程创建又在不同进程间的文件共享中扮演着关键角…

Elasticsearch:使用阿里 infererence API 及 semantic text 进行向量搜索

在之前的文章 “Elasticsearch 开放推理 API 新增阿里云 AI 搜索支持”&#xff0c;它详细描述了如何使用 Elastic inference API 来针对阿里的密集向量模型&#xff0c;稀疏向量模型&#xff0c; 重新排名及 completion 进行展示。在那篇文章里&#xff0c;它使用了很多的英文…

基于公网的无线全双工内部通话系统在演出行业可以用吗?

文旅名城再出发&#xff0c;更待“烟花”绽繁花 2024年4月将开业的扬州首个大型沉浸式剧场-《运河密城》 以运河为原点 追随河的记忆 从春秋时代的吴王夫差 到贯通南北的大运河成形 穿梭时空 探索扬州的前世今生 「运河第一锹」古运河旁 有一处新地标正在悄然兴起 如…

POSTGRESQL跟ORACLE语法区别和相同之处

跟ORACLE语法区别之处 1. Update和delete语法区别 Pg 和MySQL Update和delete的时候表名不能加别名 2. 插入数字类型不一样 ORACLE 对number类型的数据可以用’’ 字符串标记插入&#xff0c;但是PG不行&#xff0c;必须要进行正确的数据类型 3. SEQ使用不同 ORACEL的SEQ…

C++编程物联网:舵机VS步进电机

舵机和步进电机都是常见的电机类型,它们在自动化和机器人控制中有着不同的应用场景。两者的主要区别在于控制方式、运动精度、适用范围等方面。下面详细介绍它们的作用、应用场景和主要区别。 1. 舵机(Servo Motor) 工作原理 舵机是一种具有反馈控制的电动机,通常由电动…