将 float2/vector2 属性 从着色器公开到 Unity 材质检查器

Expose float2/vector2 property from shader to Unity material inspector

在 Unity shaderlab 着色器中,您可以将着色器属性公开给编辑器中的材质检查器。这可以通过将要公开的属性放在 Properties 部分中来完成,就像这样

Properties
{
    _SomeFloat("A Float", float) = 5
}

Unity 在 documentation here.

中定义了一个属性列表

然而,这不包括任何形式的 float2 或 vector2,仅包含 FloatVector,其中包含 xyzw.

我尝试将 属性 类型设置为 float2 和 Vector2

_SomeFloat("A Float", float2) = (5,5)
_SomeFloat2("A Float2", Vector2) = (5,5)

这两个return错误Parse error: syntax error, unexpected TVAL_ID at line 7

或尝试通过仅设置一半成员

来将 Vector 减半
_SomeFloat("A Float", Vector) = (5,5)

哪个return错误Parse error: syntax error, unexpected ')', expecting ','

我可以只使用 Vector 类型,并且只使用它的 xy,但这会导致不清楚 UI,因为检查器中现在有两个未使用的元素,并且找不到 属性 属性或抽屉(例如 HideInInspector)允许您对检查器隐藏 zw 值。

那么有没有办法使用 属性 类型公开 float2?或者,您可以在编辑器中将两个浮动属性彼此相邻放置,例如 Tiling/Offset 抽屉是标准 2D 属性 类型(可能类似于 [EditorGUILayout.BeginHorizontal][2] )?

通过快速搜索,我发现有 MaterialPropertyDrawer 可以扩展以在着色器检查器中添加自定义标签(参考:https://docs.unity3d.com/ScriptReference/MaterialPropertyDrawer.html)。

因此,您可以在着色器中使用 Vector 属性,创建自定义属性,比方说,[ShowAsVector2] 并为其制作 MaterialPropertyDrawer,这只会显示两个输入字段,并将它们的值分配给向量的 xy 值。这将导致着色器 属性 写为:

[ShowAsVector2] _Position2D("Position", Vector) = (0, 0, 0, 0)

这是@tsvedas 回答的扩展。

using UnityEngine;
using UnityEditor;


/// <summary>
/// Draws a vector2 field for vector properties.
/// Usage: [ShowAsVector2] _Vector2("Vector 2", Vector) = (0,0,0,0)
/// </summary>
public class ShowAsVector2Drawer : MaterialPropertyDrawer
{
    public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
    {
        if( prop.type == MaterialProperty.PropType.Vector )
        {
            EditorGUIUtility.labelWidth = 0f;
            EditorGUIUtility.fieldWidth = 0f;

            if (!EditorGUIUtility.wideMode)
            {
                EditorGUIUtility.wideMode = true;
                EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212;
            }

            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = prop.hasMixedValue;
            Vector4 vec = EditorGUI.Vector2Field(position, label, prop.vectorValue);
            if (EditorGUI.EndChangeCheck()) {
                prop.vectorValue = vec;
            }
        }
        else
            editor.DefaultShaderProperty( prop, label.text );

    }
}

只需将此脚本放在 Editor 文件夹中,您应该只能看到 x 和 y 坐标。