当前位置: 首页 > 编程笔记 >

unity3d Custom Property Drawer

皇甫礼骞
2023-03-14
本文向大家介绍unity3d Custom Property Drawer,包括了unity3d Custom Property Drawer的使用技巧和注意事项,需要的朋友参考一下

示例

有时,您有包含数据但不从MonoBehaviour派生的自定义对象。除非您为对象类型编写自己的自定义属性抽屉,否则将这些对象添加为MonoBehaviour类中的字段不会产生视觉效果。

下面是添加到MonoBehaviour的自定义对象的简单示例,以及该自定义对象的自定义属性抽屉。

public enum Gender {
    Male,
    Female,
    Other
}

// 需要Serializable属性,否则将不使用CustomPropertyDrawer
[Serializable]
public class UserInfo {
    public string Name;
    public int Age;
    public Gender Gender;
}

// 您可以附加到GameObject的类
public class PropertyDrawerExample : MonoBehaviour {
    public UserInfo UInfo;
}

[CustomPropertyDrawer( typeof( UserInfo ) )]
public class UserInfoDrawer : PropertyDrawer {

    public override float GetPropertyHeight( SerializedProperty property, GUIContent label ) {
        // 6来自字段之间的额外间距(每个2px)
        returnEditorGUIUtility.singleLineHeight* 4 + 6;
    }

    public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) {
        EditorGUI.BeginProperty( position, label, property );

        EditorGUI.LabelField( position, label );

        var nameRect = new Rect( position.x,position.y+ 18, position.width, 16 );
        var ageRect = new Rect( position.x,position.y+ 36, position.width, 16 );
        var genderRect = new Rect( position.x,position.y+ 54, position.width, 16 );

        EditorGUI.indentLevel++;

        EditorGUI.PropertyField( nameRect, property.FindPropertyRelative( "Name" ) );
        EditorGUI.PropertyField( ageRect, property.FindPropertyRelative( "Age" ) );
        EditorGUI.PropertyField( genderRect, property.FindPropertyRelative( "Gender" ) );

        EditorGUI.indentLevel--;

        EditorGUI.EndProperty();
    }
}

首先,我们定义具有所有要求的自定义对象。只是描述用户的简单类。该类在我们的PropertyDrawerExample类中使用,可以将其添加到GameObject中。

public enum Gender {
    Male,
    Female,
    Other
}

[Serializable]
public class UserInfo {
    public string Name;
    public int Age;
    public Gender Gender;
}

public class PropertyDrawerExample : MonoBehaviour {
    public UserInfo UInfo;
}

自定义类需要Serializable属性,否则将不使用CustomPropertyDrawer

接下来是CustomPropertyDrawer

首先,我们必须定义一个从PropertyDrawer派生的类。类定义还需要CustomPropertyDrawer属性。传递的参数是您希望此抽屉用于的对象的类型。

[CustomPropertyDrawer( typeof( UserInfo ) )]
public class UserInfoDrawer : PropertyDrawer {

接下来,我们重写GetPropertyHeight函数。这使我们可以为属性定义自定义高度。在这种情况下,我们知道我们的财产将分为四个部分:标签,姓名,年龄和性别。因此,我们使用EditorGUIUtility.singleLineHeight * 4,我们又添加了6个像素,因为我们希望每个字段之间用两个像素隔开

public override float GetPropertyHeight( SerializedProperty property, GUIContent label ) {
    returnEditorGUIUtility.singleLineHeight* 4 + 6;
}

接下来是实际的OnGUI方法。我们从EditorGUI.BeginProperty([...])开始,然后以结束函数。我们这样做是为了如果此属性成为预制件的一部分,则实际的预制件覆盖逻辑将适用于这两种方法之间的所有内容。EditorGUI.EndProperty()

public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) {
    EditorGUI.BeginProperty( position, label, property );

之后,我们显示一个包含字段名称的标签,并且我们已经为字段定义了矩形。

EditorGUI.LabelField( position, label );

var nameRect = new Rect( position.x,position.y+ 18, position.width, 16 );
var ageRect = new Rect( position.x,position.y+ 36, position.width, 16 );
var genderRect = new Rect( position.x,position.y+ 54, position.width, 16 );

每个字段间隔为16 + 2像素,高度为16(与EditorGUIUtility.singleLineHeight相同)

接下来,我们使用一个选项卡对UI进行缩进,以获得更好的布局,显示属性,取消对GUI的缩进,并以EditorGUI.EndProperty结尾

EditorGUI.indentLevel++;

EditorGUI.PropertyField( nameRect, property.FindPropertyRelative( "Name" ) );
EditorGUI.PropertyField( ageRect, property.FindPropertyRelative( "Age" ) );
EditorGUI.PropertyField( genderRect, property.FindPropertyRelative( "Gender" ) );

EditorGUI.indentLevel--;

EditorGUI.EndProperty();

我们使用EditorGUI.PropertyField来显示字段,该字段需要一个矩形作为位置,并需要SerializedProperty作为显示的属性。我们通过在OnGUI函数中传递的属性上调用FindPropertyRelative(“ ...”)来获取属性。请注意,这些是区分大小写的,并且找不到非公共属性!

对于此示例,我没有保存从property.FindPropertyRelative(“ ...”)返回的属性。您应该将它们保存在类的私有字段中,以防止不必要的调用

结果

之前

 类似资料:

相关阅读

相关文章

相关问答