在URP中PBR的材质是Lit.shader,由于项目组需要拓展不得不仿照它的写法在写一堆C#的代码来配合面板的显示,一方面容易出BUG另一方面非常麻烦。
首先复制一个Lit.shader改成MyLit.shader放到Asset目录下,Properties属性面板中下面写入
Properties
{
//...
[ext][Foldout] _MytestName("溶解面板",Range (0,1)) = 0
[ext][if(_MytestName)] [Toggle(GAME_TEST)] _Mytest ("启动溶解宏", Float) = 0
[ext][if(_MytestName)] _Value("溶解参数1",Range (0,1)) = 0
[ext][if(_MytestName)] [SingleLine] _MainTex2 ("溶解图", 2D) = "white" {}
[ext][if(_MytestName)] [SingleLine] [Normal] _MainTex3 ("溶解图2", 2D) = "white" {}
[ext][if(_MytestName)] [PowerSlider(3.0)] _Shininess ("溶解参数3", Range (0.01, 1)) = 0.08
[ext][if(_MytestName)] [IntRange] _Alpha ("溶解参数4", Range (0, 255)) = 100
[ext][Foldout] _Mytest2Name("特殊面板",Range (0,1)) = 0
[ext][if(_Mytest2Name)] [Toggle] _Mytest2 ("启动特殊宏", Float) = 0
[ext][if(_Mytest2Name)] _FirstColor("特殊颜色", Color) = (1, 1, 1, 1)
[ext][if(_Mytest2Name)] _FirstValue("特殊向量", Vector) = (1, 1, 1, 1)
}
[ext]标签用于区分这个属性是我们新加的还是URP自带的。
[Foldout]标签用于面板展开关闭
[if(xxx)]标签表示将一种效果所用到的属性归类。
在Shader的最下面使用自己的面板
CustomEditor “LitShader”
由于原版的LitShader.cs是内部类,需要拷贝出来一份,我这里使用partial类将它们分开。如下代码所示
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
partial class LitShader : BaseShaderGUI
{
//自定义效果-单行显示图片
internal class SingleLineDrawer : MaterialPropertyDrawer
{
public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
{
editor.TexturePropertySingleLine(label, prop);
}
public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)
{
return 0;
}
}
//自定义效果-折行显示图片
internal class FoldoutDrawer : MaterialPropertyDrawer
{
bool showPosition;
public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor)
{
showPosition = EditorGUILayout.Foldout(showPosition, label);
prop.floatValue = Convert.ToSingle(showPosition);
}
public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)
{
return 0;
}
}
static Dictionary<string, MaterialProperty> s_MaterialProperty = new Dictionary<string, MaterialProperty>();
static List<MaterialData> s_List = new List<MaterialData>();
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
{
base.OnGUI(materialEditorIn, properties);
EditorGUILayout.Space();
Shader shader = (materialEditor.target as Material).shader;
s_List.Clear();
s_MaterialProperty.Clear();
for (int i = 0; i < properties.Length; i++)
{
var propertie = properties[i];
var attributes = shader.GetPropertyAttributes(i);
foreach (var item in attributes)
{
if (item.Contains("ext"))
{
if (!s_MaterialProperty.ContainsKey(propertie.name))
{
s_MaterialProperty[propertie.name] = propertie;
s_List.Add(new MaterialData() { prop = propertie, indentLevel = false });
}
}
else if (item.Contains("Toggle"))
{
//根据Toggle标签每帧启动宏
if (s_MaterialProperty.TryGetValue(propertie.name, out var __))
{
if (propertie.type == MaterialProperty.PropType.Float)
{
string keyword = "";
Match match = Regex.Match(item, @"(w+)s*((.*))");
if (match.Success)
keyword = match.Groups[2].Value.Trim();
if(string.IsNullOrEmpty(keyword))
keyword = propertie.name.ToUpperInvariant() + "_ON";
foreach (Material material in propertie.targets)
{
if (propertie.floatValue == 1.0f)
material.EnableKeyword(keyword);
else
material.DisableKeyword(keyword);
}
}
}
}
else if (item.StartsWith("if"))
{
Match match = Regex.Match(item, @"(w+)s*((.*))");
if (match.Success)
{
var name = match.Groups[2].Value.Trim();
if (s_MaterialProperty.TryGetValue(name, out var a))
{
if (a.floatValue == 0f)
{
//如果有if标签,并且Foldout没有展开不进行绘制
s_List.RemoveAt(s_List.Count - 1);
}
else
s_List[s_List.Count - 1].indentLevel = true;
}
}
}
}
}
PropertiesDefaultGUI(materialEditor, s_List);
}
public class MaterialData
{
public MaterialProperty prop;
public bool indentLevel = false;
}
public void PropertiesDefaultGUI(MaterialEditor materialEditor, List<MaterialData> props)
{
for (int i = 0; i < props.Count; i++)
{
MaterialProperty prop = props[i].prop;
bool indentLevel = props[i].indentLevel;
if ((prop.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) == MaterialProperty.PropFlags.None)
{
float propertyHeight = materialEditor.GetPropertyHeight(prop, prop.displayName);
Rect controlRect = EditorGUILayout.GetControlRect(true, propertyHeight, EditorStyles.layerMaskField);
if (indentLevel) EditorGUI.indentLevel++;
materialEditor.ShaderProperty(controlRect, prop, prop.displayName);
if (indentLevel) EditorGUI.indentLevel--;
}
}
}
}
OK,面板已经拓展在原版Lit.shader下面了,开关启动Toggle就可以不需要在写GUI面板了。
- 本文固定链接: https://www.xuanyusong.com/archives/4947
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

