查看: 19043|回复: 123

[在unity中制作] Property Drawers

  [复制链接]

2

主题

2

帖子

52

积分

vip会员

Rank: 1

积分
52
发表于 2016-7-15 01:02:57 | 显示全部楼层 |阅读模式
产权的抽屉可用于自定义控件的外观在一定检视窗通过使用属性在您的脚本,或通过控制一个特定的序列化类应该。

抽屉里有两个用途物业:

自定义一个序列化类的每个实例的GUI。
自定义脚本成员界面定制财产属性。
自定义序列化类的GUI

如果你有一个自定义序列化类,你可以使用一个产权的抽屉控制如何看起来在检查员。考虑下面的例子可序列化类成分(笔记:这些都不是编辑脚本。属性类应该被放置在一个常规的脚本文件):

JavaScript(例):

enum IngredientUnit { Spoon, Cup, Bowl, Piece }

// Custom serializable class
class Ingredient extends System.Object {
    var name : String;
    var amount : int = 1;
    var unit : IngredientUnit;
}

var potionResult : Ingredient;
var potionIngredients : Ingredient[];

function Update () {
    // Update logic here...
}
C #(例):


using UnityEngine;
using System.Collections;

public enum IngredientUnit { Spoon, Cup, Bowl, Piece }

// Custom serializable class
[System.Serializable]
public class Ingredient : System.Object {
    string name;
    int amount = 1;
    IngredientUnit unit;
}

public class Recipe : MonoBehaviour {
    Ingredient potionResult;
    Ingredient[] potionIngredients;

    void Update() {
        // Update logic here...
    }
}

using UnityEngine;
using System.IO;

class Testing : MonoBehaviour{

    enum IngredientUnit { Spoon, Cup, Bowl, Piece }

    // Custom serializable class
    [System.Serializable]
    class Ingredient{
        string name;
        int amount = 1;
        IngredientUnit unit;
    }

    Ingredient potionResult;
    Ingredient[] potionIngredients;

    void Update () {
    // Update logic here...
    }
}
使用自定义属性的抽屉,在检查员的成分班所有的外观是可以改变的。比较在检查员的成分特性看没有和一个自定义属性的抽屉:
Property Drawers
你可以把财产抽屉可序列化类的使用custompropertydrawer属性通过在可序列化类的类型,这是一个抽屉。

JavaScript(例):

@CustomPropertyDrawer(Ingredient)
class IngredientDrawer extends PropertyDrawer {
   
    // Draw the property inside the given rect
    function OnGUI (position : Rect, property : SerializedProperty, label : GUIContent) {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty (position, label, property);
        
        // Draw label
        position = EditorGUI.PrefixLabel (position, GUIUtility.GetControlID (FocusType.Passive), label);
        
        // Don't make child fields be indented
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
        
        // Calculate rects
        var amountRect = new Rect (position.x, position.y, 30, position.height);
        var unitRect = new Rect (position.x+35, position.y, 50, position.height);
        var nameRect = new Rect (position.x+90, position.y, position.width-90, position.height);
        
        // Draw fields - passs GUIContent.none to each so they are drawn without labels
        EditorGUI.PropertyField (amountRect, property.FindPropertyRelative ("amount"), GUIContent.none);
        EditorGUI.PropertyField (unitRect, property.FindPropertyRelative ("unit"), GUIContent.none);
        EditorGUI.PropertyField (nameRect, property.FindPropertyRelative ("name"), GUIContent.none);
        
        // Set indent back to what it was
        EditorGUI.indentLevel = indent;
        
        EditorGUI.EndProperty ();
    }
}
C #(实例):

using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomPropertyDrawer(typeof(Ingredient))]
public class IngredientDrawer : PropertyDrawer {

    // Draw the property inside the given rect
    void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);

        // Draw label
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        // Don't make child fields be indented
        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // Calculate rects
        Rect amountRect = new Rect(position.x, position.y, 30, position.height);
        Rect unitRect = new Rect(position.x+35, position.y, 50, position.height);
        Rect nameRect = new Rect(position.x+90, position.y, position.width-90, position.height);

        // Draw fields - passs GUIContent.none to each so they are drawn without labels
        EditorGUI.PropertyField(amountRect, property.FindPropertyRelative ("amount"), GUIContent.none);
        EditorGUI.PropertyField(unitRect, property.FindPropertyRelative ("unit"), GUIContent.none);
        EditorGUI.PropertyField(nameRect, property.FindPropertyRelative ("name"), GUIContent.none);

        // Set indent back to what it was
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

using UnityEngine;
using UnityEditor;
using System.Collections;


[CustomPropertyDrawer (Ingredient)]
class IngredientDrawer : PropertyDrawer {
   
    // Draw the property inside the given rect
    void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty (position, label, property);
        
        // Draw label
        position = EditorGUI.PrefixLabel (position, GUIUtility.GetControlID (FocusType.Passive), label);
        
        // Don't make child fields be indented
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
        
        // Calculate rects
        Rect amountRect = new Rect (position.x, position.y, 30, position.height);
        Rect unitRect = new Rect (position.x+35, position.y, 50, position.height);
        Rect nameRect = new Rect (position.x+90, position.y, position.width-90, position.height);
        
        // Draw fields - passs GUIContent.none to each so they are drawn without labels
        EditorGUI.PropertyField (amountRect, property.FindPropertyRelative ("amount"), GUIContent.none);
        EditorGUI.PropertyField (unitRect, property.FindPropertyRelative ("unit"), GUIContent.none);
        EditorGUI.PropertyField (nameRect, property.FindPropertyRelative ("name"), GUIContent.none);
        
        // Set indent back to what it was
        EditorGUI.indentLevel = indent;
        
        EditorGUI.EndProperty ();
    }
}
自定义的GUI脚本成员使用属性

其他使用产权的抽屉是改变的成员出现在一个脚本,自定义财产属性。说你想限制漂浮或整数在您的脚本一定范围和显示他们的滑块在检查员。使用内置的propertyattribute打电话rangeattribute你可以这样做:

JavaScript(例):

// Show this float in the Inspector as a slider between 0 and 10
@Range (0.0, 10.0)
var myFloat = 0.0;

//C# example.
[Range(0.0f, 10.0f)]
public float myFloat = 0.0f;

C #(例):

// Show this float in the Inspector as a slider between 0 and 10
[Range(0.0f, 10.0f)]
float myFloat = 0.0f;

你可以做你自己propertyattribute也.我们将使用代码为rangeattribute作为一个例子。属性必须扩展propertyattribute类如果你想的话,你的财产可以带参数和存储他们的公共成员变量。

JavaScript(例):

class RangeAttribute extends PropertyAttribute {
    var min : float;
    var max : float;
   
    function RangeAttribute (min : float, max : float) {
        this.min = min;
        this.max = max;
    }
}

C #(实例):

using UnityEngine;
using System.Collections;


public class RangeAttribute : PropertyAttribute {
    public float min;
    public float max;

    public RangeAttribute (float min, float max) {
        this.min = min;
        this.max = max;
    }
}
using UnityEngine;
using System.Collections;

public class Testing : PropertyAttribute
{
        float min;
        float max;
        
        void RangeAttribute (float min, float max) {
            this.min = min;
            this.max = max;
        }
}
现在你的属性,你需要做一个产权的抽屉得出有属性。抽屉必须扩展propertydrawer类,它必须有一个custompropertydrawer属性告诉它的属性是一个抽屉。

房地产类应该放在抽屉里的编辑脚本,一个文件夹里面称为编辑。

JavaScript(例):

// Tell the RangeDrawer that it is a drawer for properties with the RangeAttribute.
@CustomPropertyDrawer (RangeAttribute)
class RangeDrawer extends PropertyDrawer {
   
    // Draw the property inside the given rect
    function OnGUI (position : Rect, property : SerializedProperty, label : GUIContent) {
        
        // First get the attribute since it contains the range for the slider
        var range : RangeAttribute = attribute as RangeAttribute;
        
        // Now draw the property as a Slider or an IntSlider based on whether it's a float or integer.
        if (property.propertyType == SerializedPropertyType.Float)
            EditorGUI.Slider (position, property, range.min, range.max, label);
        else if (property.propertyType == SerializedPropertyType.Integer)
            EditorGUI.IntSlider (position, property, range.min, range.max, label);
        else
            EditorGUI.LabelField (position, label.text, "Use Range with float or int.");
    }
}
C #(实例):

using UnityEngine;
using UnityEditor;
using System.Collections;

// Tell the RangeDrawer that it is a drawer for properties with the RangeAttribute.

[CustomPropertyDrawer(typeof(RangeAttribute))]
public class RangeDrawer : PropertyDrawer {

    // Draw the property inside the given rect
    void OnGUI (Rect position, SerializedProperty property, GUIContent label) {

        // First get the attribute since it contains the range for the slider
        RangeAttribute range  = attribute as RangeAttribute;

        // Now draw the property as a Slider or an IntSlider based on whether it's a float or integer.
        if (property.propertyType == SerializedPropertyType.Float)
            EditorGUI.Slider(position, property, range.min, range.max, label);
        else if (property.propertyType == SerializedPropertyType.Integer)
            EditorGUI.IntSlider(position, property, (int) range.min, (int) range.max, label);
        else
            EditorGUI.LabelField(position, label.text, "Use Range with float or int.");
    }
}

注意:由于性能原因,EditorGUILayout功能不可用性的抽屉。




回复

使用道具 举报

0

主题

874

帖子

2913

积分

vip会员

Rank: 1

积分
2913
发表于 2016-7-15 01:02:58 来自手机 | 显示全部楼层
我一天来看一回,看看能不能打折。
回复 支持 反对

使用道具 举报

0

主题

854

帖子

2816

积分

vip会员

Rank: 1

积分
2816
发表于 2016-7-15 01:33:50 来自手机 | 显示全部楼层
合集看着不错。
回复 支持 反对

使用道具 举报

濮真 该用户已被删除
发表于 2016-7-15 01:47:52 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

0

主题

843

帖子

2735

积分

vip会员

Rank: 1

积分
2735
发表于 2016-7-15 02:34:46 | 显示全部楼层
谢谢楼主分享
回复 支持 反对

使用道具 举报

0

主题

836

帖子

2772

积分

vip会员

Rank: 1

积分
2772
发表于 2016-7-15 03:01:55 来自手机 | 显示全部楼层
谢谢楼主分享
回复 支持 反对

使用道具 举报

0

主题

897

帖子

2951

积分

vip会员

Rank: 1

积分
2951
发表于 2016-7-15 03:50:59 来自手机 | 显示全部楼层
谢谢分享,顶一个
回复 支持 反对

使用道具 举报

0

主题

890

帖子

2912

积分

vip会员

Rank: 1

积分
2912
发表于 2016-7-15 04:17:48 来自手机 | 显示全部楼层
好东西,所噶
回复 支持 反对

使用道具 举报

0

主题

846

帖子

2784

积分

vip会员

Rank: 1

积分
2784
发表于 2016-7-15 04:38:24 | 显示全部楼层
加油摸摸大,感谢楼主分享
回复 支持 反对

使用道具 举报

0

主题

863

帖子

2835

积分

vip会员

Rank: 1

积分
2835
发表于 2016-7-15 05:17:58 来自手机 | 显示全部楼层
这个必须顶,,,,
回复 支持 反对

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | enginedx注册

本版积分规则

 
 



邮件留言:


 
返回顶部