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

Rem*_*_rm 3 shader hlsl unity-game-engine shaderlab

在 Unity Shaderlab 着色器中,您可以向编辑器中的材质检查器公开着色器属性。这可以通过将要公开的属性放置在该Properties部分中来完成,如下所示

Properties
{
    _SomeFloat("A Float", float) = 5
}
Run Code Online (Sandbox Code Playgroud)

Unity 在此处的文档中定义了属性列表。

然而,这不包括任何形式的 float2 或 vector2,只是单个FloatVector由 组成xyzw

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

_SomeFloat("A Float", float2) = (5,5)
_SomeFloat2("A Float2", Vector2) = (5,5)
Run Code Online (Sandbox Code Playgroud)

两者都返回错误Parse error: syntax error, unexpected TVAL_ID at line 7

或者试图Vector通过只设置一半的成员来将其减半

_SomeFloat("A Float", Vector) = (5,5)
Run Code Online (Sandbox Code Playgroud)

返回错误Parse error: syntax error, unexpected ')', expecting ','

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

那么有没有办法使用属性类型公开 float2 呢?或者也许有另一种选择,您可以在编辑器中将两个浮动属性彼此相邻放置,例如平铺/偏移抽屉位于标准2D属性类型中(也许类似于[EditorGUILayout.BeginHorizontal][2])?

Tom*_*das 8

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

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

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


Ahn*_*naf 8

这是@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 );

    }
}

Run Code Online (Sandbox Code Playgroud)

只需将此脚本放入编辑器文件夹中,您应该只能看到xy坐标。