UnityShader自定义属性特性

前言:

在编写UnityShader时,我们常常会使用特性来更换材质球面板的属性外观,除此之外,还可以使用自定义的扩展脚本来实现自定义的材质球界面,参考我之前的文章UnityShaderUI编辑器扩展

但是自定义扩展每次都要单独写一个Editor脚本来扩展对应的Shader,而不能像特性那样,只要加一个[HDR],[Range]就能更改材质面板的界面。

那么我们如何方便又快速的创建自定义的特性,方便我们只要写一个全功能脚本,就能快速自定义扩展不同的Shader呢?

原理:

如图,只需要编写脚本,类继承MaterialPropertyDrawer就可以了,类名的命名方式是特性名+Drawer,如:SingleLineTextureDrawer,或者不加Drawer也可以Unity会自动添加并识别。

在Shader中使用:

写法:[特性类名(不加Drawer)]

材质面板显示:

自定义Group自动分组功能:

构想:一个特性Group,在Shader属性前添加时,作为折叠栏功能,如[Group]_group1表示一个折叠栏,如[Group(_MainTex,_IntTest)]_group2表示group2折叠栏下包含属性_MainTex与_IntTest属性的绘制或者不绘制。

如图:

效果:

实现:

在我们的构想中,Group可以包含子属性,也可以不包含,包含的子属性的数量不定,所以构建构造函数:

启用keys数组用来存放传递的命名,这些命名作为我们用来分组和查询属性的必要条件。

重写OnGUI函数:

这其中有一个GUIData调用,这是用来存放Shader的属性是否应该被绘制的数据类,如果不这样做,你就会发现就算使用了自定义的特性,这个属性还会被绘制一次,因为我们的实现逻辑需要在Group中处理其子属性的可见性。

GUIData类与自定义方法:

很简单,立面有一个字典,这个字典存放了属性的可见性,同样有两个方法,一个方法设置属性的可见性,一个方法获取属性的可见性。

然后,需要写一个自定义脚本,继承ShaderGUI并且在Shader中使用CustomEditor调用,我们自主实现Shader的OnGUI逻辑,如图:

为什么还要这样自定义ShaderGUI呢?因为上述说过,为了实现Group分组效果,需要避免其子属性不管有没有特性,都应该被Group折叠栏决定显影,若是不自主实现,你就会发现你自定义绘制了一遍,这些子属性不管有没有特性,也会再被绘制一遍,因为没有处理Unity默认的绘制逻辑,所以需要我们自定义一个ShaderGUI实现。

全部代码:

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;namespace CustomShaderPropertyDrawer
{#region Datapublic class GUIData{private static Dictionary<string, bool> propertyShow = new Dictionary<string, bool>();public static void SetPropertyVisible(string property, bool visiable){if (propertyShow.ContainsKey(property))propertyShow[property] = visiable;elsepropertyShow.Add(property, visiable);}public static bool GetPropertyVisible(string property){if (propertyShow.ContainsKey(property))return propertyShow[property];elsereturn false;}}#endregionpublic class GUIShow : ShaderGUI{internal MaterialProperty[] Pops { get; private set; }public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties){Pops = properties;var material = materialEditor.target as Material;var shader = material.shader;for (int i = 0; i < properties.Length; i++){if (System.String.Concat(shader.GetPropertyAttributes(i)).Contains("Group")){materialEditor.ShaderProperty(properties[i], properties[i].displayName);}else{if (GUIData.GetPropertyVisible(properties[i].name))materialEditor.ShaderProperty(properties[i], properties[i].displayName);}}}}#region MaterialPropertyDrawer/// <summary>/// Group分组,采样Flodout形式,可使用自定义GUIStyle/// </summary>public class GroupDrawer : MaterialPropertyDrawer{readonly string[] keys;public GroupDrawer() { }public GroupDrawer(params string[] keys){this.keys = keys;}public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor){if (editor.customShaderGUI == null || !(editor.customShaderGUI is GUIShow))editor.DefaultShaderProperty(prop, prop.displayName);else{if (prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Int){bool group_foldout = false;switch (prop.type){case MaterialProperty.PropType.Float:group_foldout = prop.floatValue == 1.0f ? true : false;EditorGUI.BeginChangeCheck();group_foldout = EditorGUI.Foldout(position, group_foldout, prop.displayName);if (EditorGUI.EndChangeCheck()){prop.floatValue = group_foldout ? 1f : 0f;if (keys != null && keys.Length > 0){foreach (var key in keys){GUIData.SetPropertyVisible(key, group_foldout);}}}break;case MaterialProperty.PropType.Int:group_foldout = prop.intValue == 1 ? true : false;EditorGUI.BeginChangeCheck();group_foldout = EditorGUI.Foldout(position, group_foldout, prop.displayName);if (EditorGUI.EndChangeCheck()){prop.intValue = group_foldout ? 1 : 0;if (keys != null && keys.Length > 0){foreach (var key in keys){GUIData.SetPropertyVisible(key, group_foldout);}}}break;}}}}}/// <summary>/// 单线贴图样式/// </summary>public class SingleLineTexture : MaterialPropertyDrawer{public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor){return 0;}public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor){if (prop.type == MaterialProperty.PropType.Texture){editor.TexturePropertySingleLine(label, prop);}}}#endregion
}

注意:官方说明,为了性能,EditorGUILayout不能和MaterialPropertyDrawers一起使用,所以最好还是使用EditorGUI

更多内容可以参考官方MaterialEditor,MaterialPropertyDrawer,ShaderOnGUI,EditorGUI等编辑器内容,同时可以阅读我的编辑器扩展基础知识:Unity拓展编辑器基础知识

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

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

相关文章

性能测试经典案例解析——远程培训系统

各位好&#xff0c;我是 道普云 一站式云测试SaaS平台。一个在软件测试道路上不断折腾十余年的萌新。 欢迎关注我的专栏和我的主页 道普云 文章内容具有一定门槛&#xff0c;建议先赞再收藏慢慢学习&#xff0c;有不懂的问题欢迎私聊我。 希望这篇文章对想提高软件测试水平…

5.sklearn-朴素贝叶斯算法、决策树、随机森林

文章目录 环境配置&#xff08;必看&#xff09;头文件引用1.朴素贝叶斯算法代码运行结果优缺点 2.决策树代码运行结果决策树可视化图片优缺点 3.随机森林代码RandomForestClassifier()运行结果总结 本章学习资源 环境配置&#xff08;必看&#xff09; Anaconda-创建虚拟环境…

Keil下载烧录程序到单片机提示flash outtime超时

Flash Timeout.Reset the Target and try it again. Error:Flash Download failed - “Cortex-M4” 解决方法&#xff1a; 1.检查杜邦线 2.RESET按键按一下再下载(或者一直按着下载)&#xff0c;这样能让单片机进入烧录模式。 3.有外部看门狗&#xff0c;外部看门狗用跳帽屏…

『功能项目』DOTween动态文字【26】

打开上一篇25协程生成怪物模型的项目&#xff0c; 本章要做的事情是用DOTween插件做一个动态文字效果 首先在资源商店中免费下载一个DOTween插件 新建脚本&#xff1a;DowteenFlicker.cs 编写脚本&#xff1a; using DG.Tweening; using UnityEngine; using UnityEngine.UI;pu…

2024 年高教社杯全国大学生数学建模竞赛题目-C 题 农作物的种植策略

根据乡村的实际情况&#xff0c;充分利用有限的耕地资源&#xff0c;因地制宜&#xff0c;发展有机种植产业&#xff0c;对乡村经济 的可持续发展具有重要的现实意义。选择适宜的农作物&#xff0c;优化种植策略&#xff0c;有利于方便田间管理&#xff0c;提 高生产效益&#…

在模板中使用 Django 会话

在 Django 中使用会话&#xff08;session&#xff09;可以让你在用户访问网站的过程中存储和访问临时数据。我们可以利用会话在速度计算器的例子中存储和显示上次计算的结果。 1、问题背景 在 Django 中&#xff0c;可以使用会话来存储用户数据。在某些情况下&#xff0c;我们…

Python实战项目:天气数据爬取+数据可视化(完整代码)_python爬虫实战

一、选题的背景 随着人们对天气的关注逐渐增加&#xff0c;天气预报数据的获取与可视化成为了当今的热门话题&#xff0c;天气预报我们每天都会关注&#xff0c;天气情况会影响到我们日常的增减衣物、出行安排等。每天的气温、相对湿度、降水量以及风向风速是关注的焦点。通过…

[数据集][目标检测]翻越栏杆行为检测数据集VOC+YOLO格式512张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;512 标注数量(xml文件个数)&#xff1a;512 标注数量(txt文件个数)&#xff1a;512 标注类别…

datagrip链接sql server2005报错

错误信息 第一次报 DBMS: Microsoft SQL Server (no ver.) Case sensitivity: plainmixed, delimitedexact [08S01] 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client pr…

iPhone无法充电?别急,这几招帮你轻松解决充电难题!

在这个智能手机不离手的时代&#xff0c;iPhone作为众多用户的首选&#xff0c;其续航能力和充电效率自然成为了大家关注的焦点。然而&#xff0c;偶尔遇到iPhone无法充电的情况&#xff0c;确实让人头疼不已。别担心&#xff0c;今天我们就来聊聊iPhone无法充电的几大常见原因…

LeetCode:快乐数(202)

目录 题目 代码思路 双指针 代码实现 题目 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 编写一个算法来判断一个数 n 是不是快乐数。 [ 快乐数 ] 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程…

echarts地图绘制并实现下钻功能

本文参考网址 使用echarts地图需要先准备好echarts地图渲染需要的json数据&#xff0c;数据可以从阿里云地址中下载自己需要的&#xff0c;下载之后直接引入即可使用&#xff0c;本文针对全国地图做一个简单的demo 阿里云界面如图 // 1、准备echarts地图容器<div class&…

【python面向对象】

一、魔术函数 在Python中&#xff0c;xx()的函数叫做魔法函数&#xff0c;指的是具有特殊功能或者有特殊含义的函数&#xff0c;而且这些函数都是在某种情况下自动调用的。 eg: init函数 __init__() :对象的初始化函数&#xff0c;在创建一个对象的时默认被调用&#xff0c;…

RabbitMQ本地Ubuntu系统环境部署与无公网IP远程连接服务端实战演示

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 安装内网穿透工具3.1 安装cpolar内网穿透3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&am…

基于飞桨paddle2.6.1+cuda11.7+paddleRS开发版的目标提取-道路数据集训练和预测代码

基于飞桨paddle2.6.1cuda11.7paddleRS开发版的目标提取-道路数据集训练和预测代码 预测结果&#xff1a; 预测影像&#xff1a; &#xff08;一&#xff09;准备道路数据集 下载数据集地址&#xff1a; https://aistudio.baidu.com/datasetdetail/56961 mass_road.zip …

通过 pnpm 安装依赖包会发生什么

通过 pnpm 安装依赖包会发生什么 通过 pnpm 下载的包都是放在一个全局目录&#xff08;.pnpm-store&#xff09;下&#xff0c;默认是在 ${os.homedir}/v3/.pnpm-store&#xff0c;如果我们不确定在哪里&#xff0c;可以输入下面的命令手动配置&#xff1a; pnpm set store-d…

若依 Vue3的前后端分离系统管理 创建 使用

RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|开源后台系统|RuoYi|RuoYi-Vue|RuoYi-Cloud|RuoYi框架|RuoYi开源|RuoYi视频|若依视频|RuoYi开发文档|若依开发文档|Java开源框架|Java|SpringBoot|SrpingBoot2.0…

IP/TCP/UDP协议的关键知识点

导语&#xff1a;网络协议是理解网络情况的基础&#xff0c;当遇到网络问题时&#xff0c;首先可以从网络协议入手&#xff0c;熟悉的网络协议可以有效帮助小伙伴们排查或者说定位大概的问题方面。本文整理了目前最常用的网络通信协议&#xff0c;相信对小伙伴们肯定都有帮助。…

cookie实战案例-自动登录网站

在写爬虫的时候&#xff0c;要伪装成真实用户请求。可能需要大量的IP地址&#xff0c;那么大量的IP地址从哪里来呢&#xff1f;这里就需要用代理IP来解决了&#xff0c;有的网站专门通过提供代理IP池服务作为主要的经营业务&#xff0c;只要注册相关网站开通对应套餐就可以了。…

Java笔试面试题AI答之JDBC(1)

文章目录 1. 什么是JDBC&#xff1f;2. 驱动(Driver)在JDBC中的角色&#xff1f;3. JDBC PreparedStatement比Statement有什么优势&#xff1f;1. 预编译和性能提升2. 参数化查询和安全性3. 更好的可读性和可维护性4. 支持批量操作5. 缓存机制&#xff08;特定数据库环境&#…