关于Unity运行时动态修改材质的小秘密

一、问题背景

在以往的Unity项目中涉及到修改材质的需求时,也只是改改材质贴图,材质颜色等,也没遇到那么多动态修改材质的坑。最近在做Unity App Demo时也遇到了要修改材质的小需求,本以为几分钟就能完成了,却花费了我大半天时间才弄完。需求:美术那边给了三个材质球,让我动态加载物体时,切换该物体的材质,最开始想的方案是,直接把三个材质球加载的内存中,直接修改物体的材质球属性不就可以了吗。转念一想,这万一给我一百个材质球,或者更多,难道我都要加载到内存中吗?这显然是不行的。我一看这三个材质球只有一个地方是不一样的,那就是颜色和透明度。我就想了,那我直接获取物体材质球,直接修改材质球相关的属性不就完事了吗,于是就出现了本文中的一系列问题。

二、解决方案

1、修改材质颜色透明度不生效

场景中新建Cube,新建脚本MaterialTest.cs,挂载到Cube物体下,写代码实现修改Cube的材质属性:

public class MaterialTest : MonoBehaviour
{private Material material;void Start(){material = GetComponent<MeshRenderer>().material;material.color = new Color(1, 0, 0, 0.5f);}
}

运行发现颜色变了,但是透明度没变
在这里插入图片描述
打开Inspector面板一看,发现材质的Rendering Mode 还是Opaque(不透明的)。

2、修改材质透明不实时刷新

基于问题一,我们要通过代码修改材质的渲染模式,于是加了一行代码:

material.SetFloat("_Mode", 3);

运行发现物体还是没有变成透明形状,但是呢,只要一打开物体的Inspector面板,点一下材质组件,Game视图中的Cube就突然刷新了,变成透明了!
在这里插入图片描述
这令我百思不得其解,我在想,打包发布之后又没有Inspector面板让我去手动点一下再刷新材质啊(苦笑),看了材质相关的api,也尝试了好几张修改材质的方法,都没能实时刷新材质透明度,应该还是方法不对。

3、参考官方修改材质的示例成功修改透明材质

在这里插入图片描述
在Unity官网中每个版本的下载列表里会有一个Built in shaders,下载解压之后打开Editor–StandardShaderGUI.cs脚本,里面有详细的官方修改shader材质示例代码。
在这里插入图片描述
最终修改材质透明度的代码如下:

public class MaterialTest : MonoBehaviour
{private Material material;void Start(){material = GetComponent<MeshRenderer>().material;material.color = new Color(1, 0, 0, 0.5f);material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);material.SetInt("_ZWrite", 0);material.DisableKeyword("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.EnableKeyword("_ALPHAPREMULTIPLY_ON");material.SetFloat("_Mode", 3);material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;}
}

运行发现正确修改材质透明度并实时刷新。其中这个关键字最重要:

_ALPHAPREMULTIPLY_ON 表示开启 “透明”透明度渲染模式

4、安卓真机物体透明度失效。

猜测是因为打包时Unity没有将Standard的透明变体打包到apk中,本来是想将整个Standard标准shader放入到Graphics中的Always Included Shaders列表中去。但是一想到会造成打包时间变成,很多冗余shader都会打包进去。本着按需打包的策略,最后还是选择新建一个材质球Material,直接挂载到物体中去,将该材质球的Rendering Mode 改为Transparent,这样Unity就能识别到该透明shader将其打包到apk包体中,这样关联的其他物体需要透明材质时也能用到。
于是,最后打包apk,真机运行透明物体渲染正确。
在这里插入图片描述

三、总结

在使用Unity引擎时,还是需要多去官方文档或官方示例中寻找解决方案,这会让你少走弯路,也能让你从坑里感觉爬上来。某些情况下,真机上的表现也会跟编辑器有所差别甚至完全不一样,需要耐心定位问题和修改解决方案以完成需求。

四、Unity修改shader材质源码官方示例

		public enum BlendMode{Opaque,Cutout,Fade, Transparent }public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode){switch (blendMode){case BlendMode.Opaque:material.SetOverrideTag("RenderType", "");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);material.SetInt("_ZWrite", 1);material.DisableKeyword("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = -1;break;case BlendMode.Cutout:material.SetOverrideTag("RenderType", "TransparentCutout");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);material.SetInt("_ZWrite", 1);material.EnableKeyword("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;break;case BlendMode.Fade:material.SetOverrideTag("RenderType", "Transparent");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);material.SetInt("_ZWrite", 0);material.DisableKeyword("_ALPHATEST_ON");material.EnableKeyword("_ALPHABLEND_ON");material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;break;case BlendMode.Transparent:material.SetOverrideTag("RenderType", "Transparent");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);material.SetInt("_ZWrite", 0);material.DisableKeyword("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.EnableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;break;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/863710.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

淘宝商品评论爬虫实战指南:基于Requests与Cookies的实现

在本指南中&#xff0c;我们将深入探讨如何使用Python的requests库结合Cookies机制&#xff0c;高效且合法地爬取淘宝网上的任意商品评论数据。此教程不仅涵盖技术细节&#xff0c;还涉及道德与合规性考量&#xff0c;旨在为读者提供一个全面且实用的爬虫开发框架。 一、前言与…

Cesium Model 中的剪裁平面 (ClippingPlane)

Cesium Model 中的剪裁平面 (ClippingPlane) 参考: https://www.cnblogs.com/webgl-angela/p/9197672.html Cesium Model 中的剪裁平面 (ClippingPlane) // 相关类: class ClippingPlaneCollection {} class ClippingPlane {}// 剪裁的整体流程: Model.prototype.update () …

牛客小白月赛97 (个人题解)(待补完)

前言&#xff1a; 前天晚上写的一场牛客上比赛&#xff0c;虽然只写出了三道&#xff0c;但比起之前的成绩感觉自己明显有了一点进步了&#xff0c;继续努力吧&#xff0c; 正文&#xff1a; 链接&#xff1a;牛客小白月赛97_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞…

如何用DCA1000持续采集雷达数据

摘要&#xff1a;本文介绍一下如何通过mmwave studio软件&#xff0c;搭配DCA1000数据采集卡&#xff0c;对AWR1843BOOST进行不间断的数据采集。本文要求读者已经掌握了有关基础知识。 本文开放获取&#xff0c;无需关注。 到SensorConfig页面下&#xff0c;一步步操作&#xf…

ubuntu 18 虚拟机安装(3)安装mysql

ubuntu 18 虚拟机安装&#xff08;3&#xff09;安装mysql 参考 https://cloud.tencent.com/developer/article/1700780 技术分享 | MySQL 设置管理员密码无法生效一例 https://cloud.tencent.com/developer/article/2014384 在Ubuntu18.04上安装MySQL &#xff5c; 超级详细…

283. 移动零【快慢指针】【C++】

题目描述 移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nu…

无人机挂载抛弹吊舱技术详解

随着无人机技术的飞速发展&#xff0c;无人机在军事、安全、农业、环保等领域的应用越来越广泛。其中&#xff0c;挂载抛弹吊舱的无人机在精确打击、应急处置等场合发挥着重要作用。抛弹吊舱技术通过将弹药、物资等有效载荷挂载在无人机下方&#xff0c;实现了无人机的远程投放…

昇思25天学习打卡营第7天|模型训练

模型训练 模型训练一般分为四个步骤&#xff1a; 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 前面几天依次学习了前面几个步骤的操作&#xff0c;今天继续学习模型训练。 数据集和神经网络模型这个前面已经有详细的介绍。准确…

JVM(13):虚拟机性能分析和故障解决工具之Visual VM

1 Visual VM作用 是到目前为止随JDK发布的功能最强大的运行监视和故障处理程序&#xff0c;并且可以遇见在未来一段时间内都是官方主力发展的虚拟机故障处理工具。官方在VisualVM的软件说明中写上了“All-in-One”的描述字样&#xff0c;预示着他除了运行监视、故障处理外&…

ConcurrentHashMap是如何保证线程安全的-put方法简要分析

简介 ConcurrentHashMap 是 Java 中并发编程中常用的线程安全的哈希表&#xff08;HashMap&#xff09;实现。它具有以下几个显著的特点和优点&#xff0c;适合在特定的并发场景中使用&#xff1a; 线程安全性&#xff1a; ConcurrentHashMap 提供了并发访问的线程安全保证&am…

左耳听风_032_31_编程范式游记2-_泛型编程

你好&#xff0c;我是陈浩网名英&#xff0c;做耳朵house.在上一节课中呢&#xff0c;我们从c语言开始说起&#xff0c;聊了聊面向过程式的辩证范式。 那相信从代码的角度呢&#xff0c;你对这种类型的语言啊已经有了一些理解。 那作为一门高级语言呢&#xff0c;c语言啊它绝…

python进阶函数

目录 函数多返回值函数多种传参方式匿名函数 函数多返回值 问&#xff1a;如果一个函数如些两个return&#xff08;如下所示&#xff09;&#xff0c;程序如何执行&#xff1f; def return_num():return 1return 2result return_num() print(result)答&#xff1a;只执行了第…

Web3 前端攻击:原因、影响及经验教训

DeFi的崛起引领了一个创新和金融自由的新时代。然而&#xff0c;这种快速增长也吸引了恶意行为者的注意&#xff0c;他们试图利用漏洞进行攻击。尽管很多焦点都集中在智能合约安全上&#xff0c;但前端攻击也正在成为一个重要的威胁向量。 前端攻击的剖析 理解攻击者利用前端漏…

DDD学习笔记三

模型的构造块&#xff1a;实体、值对象、领域服务 &#xff08;1&#xff09;实体的领域特征 在领域中&#xff0c;一个由身份而不是属性值定义的客观概念就是实体&#xff0c;这个身份可以由一个唯一标识确认。 一个概念是否是实体取决于系统的应用场景&#xff0c;一个标识是…

ORA-00903: invalid table name\nORA-06512: at line 1\n

错误信息 ORA-00903: invalid table name\nORA-06512: at line 1\n原因 ORA-00903: invalid table name 解释: 这个错误表示在 SQL 语句中使用了无效的表名。 由于在建表中出现了以数字开头的表名,所以出现以下错误 解决方案 表名不能以数字开头

RabbitMQ交换器类型

直连交换机&#xff08;Direct Exchange&#xff09; 直连交换机的工作方式是最简单的路由模式&#xff0c;它会根据消息的routing key将其精确地路由到与之绑定的队列上。每个队列通过一个特定的routing key与交换机绑定。如果一条消息的routing key与队列的绑定键完全匹配&am…

AWT的菜单组件

AWT的菜单组件 前言一、菜单组件的介绍常见的菜单相关组件常见菜单相关组件集成体系图菜单相关组件使用小要点 二、AWT菜单组件的代码示例示例一示例二实现思路 前言 推荐一个网站给想要了解或者学习人工智能知识的读者&#xff0c;这个网站里内容讲解通俗易懂且风趣幽默&…

【Python】Pickle:Python对象序列化与反序列化的利器

在Python编程中&#xff0c;我们经常需要在程序的不同运行之间保存和加载数据&#xff0c;这时候&#xff0c;Python标准库中的pickle模块就派上了用场。pickle模块可以将Python对象序列化为字节流&#xff0c;便于存储到文件或通过网络传输&#xff1b;同时&#xff0c;它也可…

CentOS 7 和 CentOS Stream 8 的主要区别

更新频率&#xff1a; CentOS 7&#xff1a;传统的稳定版本&#xff0c;主要用于生产环境&#xff0c;更新频率较低&#xff0c;主要包含安全补丁和重要修复。CentOS Stream 8&#xff1a;滚动发布版本&#xff0c;更新更频繁&#xff0c;包含最新的特性和改进。它处于 Fedora …

springboot汽车租赁管理系统-计算机毕业设计源码08754

目 录 摘 要 第 1 章 引 言 1.1 选题背景和意义 1.2 国内外研究现状 1.3 论文结构安排 第 2 章 系统的需求分析 2.1 系统可行性分析 2.1.1 技术方面可行性分析 2.1.2 经济方面可行性分析 2.1.3 法律方面可行性分析 2.1.4 操作方面可行性分析 2.2 系统功能需求分析…