程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 【Unity C#編程】自定義數據

【Unity C#編程】自定義數據

編輯:C#入門知識

譯林軍 灰魅|2014-03-04 10:52|10589次浏覽|Unity(315)移動應用(31)技術開發(16)0

在這篇Unity C#的文章中,你將會創建一個簡單的數據結構,然後寫下它的屬性抽屜。

下面你將會學到如何創建。

  • 使用一個序列化的類
  • 創建一個自定義的屬性抽屜
  • 使用序列化屬性
  • 在編輯器裡面使用Unity的立即窗口GUI模式

在此之前,你需要了解Unity的編輯器,以及Uinty C#的一些腳本。如果你已經學習了一些其它的課程,這將會讓你更加容易上手。

這篇文章適合Unity 4.3或者以上的版本。老版本仍然可以在這裡找到。

被壓縮的色點

色點

Unity有很多種類的的數據類型,你可以用這些數據去制作很多自定義組件。但是有時我們需要一些小的自定義數據,它可以在很多地方使用。與其重復寫同樣的代碼,倒不如選擇一些可以重復使用,而且十分簡單的封裝數據類,例如一些內置的數據類型。

我們將要創建一些色點,這個數據結構是同時包括顏色和位置。

我們首先創建一個新的空項目工程,然後添加一個名為ColorPoint的新的C#腳本,同時添加所需的變量。

1 2 3 4 5 6 7 using UnityEngine;   public class ColorPoint {       public Color color;     public Vector3 position; } 然後我們再創建一個叫ColorPointTester的類來測試我們剛剛創建的數據類型。我們給它一個單獨的點向量和一個數組向量,同時也比較單獨的點向量和數組向量。接著我們創建一個空的游戲物體,把它添加到裡面。 1 2 3 4 5 6 7 8 9 10 11 12 using UnityEngine;   public class ColorPointTester : MonoBehaviour {           public ColorPoint point;           public ColorPoint[] points;           public Vector3 vector;           public Vector3[] vectors; }

色點和空測試器。

新的數據類型不能在inspector中看到,因為他的內容還不能被保存。我們要解決這個問題就要把這個數據類型添加到系統中。被序列化後屬於我們的類.在執行這步是,這個類可能要在所有公共地方的數據流可以序列化,然後才能被存儲起來。

1 2 3 4 5 6 7 8 9 using UnityEngine; using System;   [Serializable] public class ColorPoint {           public Color color;     public Vector3 position; } 現在我們剛自定義的數據可以再inspector中顯示了,我們可以再任何地方編輯、保存。同樣的,把我們的測試對象通過拖拽到項目視圖的預設中,然後在場景中改變一些變量的實例。這可以證明這類數據可以在預設中正常運行。

正常的對象和一個調整的實例預設。inspector看起來很混亂。這可以有所修改,讓它通過拖動變寬一些,但如果它的寬度過大,向量將會崩潰。

一個充實的inspector。

繪圖屬性

很可惜,即使有較寬的inspector,我們仍需要多行色點。

幸運的是,我們可以用自定義的變量在編輯中替換Unity的默認繪圖屬性。這可以通過擴展UnityEditor.PropertyDrawer來創建一個類,同時用 UnityEditor.CustomPropertyDrawer來匹配我們想要繪制的相關內容。然後,命名一個叫ColorPointDrawer的類,因為這是一個編輯的類,我們會把它放在一個叫Editor新的文件夾裡面。

1 2 3 4 5 6 using UnityEditor; using UnityEngine;   [CustomPropertyDrawer(typeof(ColorPoint))] public class ColorPointDrawer : PropertyDrawer { }

這是不做任何處理的屬性抽屜。

現在inspector不再顯示任何有用的東西,但是我們可以改變,通過覆蓋在OnGUI上,來默認自定義版本的屬性抽屜。

這個OnGUI方法有三個參數。第一個是一個巨型,它是告訴我們那些窗口的區域是應該使用什麼來繪制屬性。第二個是自身的屬性,由一個SerializedProperty來表示。第三個是GUIContent,定義了我們應該使用的屬性標簽。

讓我們首先用GUIEditor.PropertyField的方法找准位置,然後繪制GUIEditor.PrefixLabel。

1 2 3 4 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {         EditorGUI.PrefixLabel(position, label);         EditorGUI.PropertyField(position, property.FindPropertyRelative("position"));     }

屬性抽屜的重疊標簽。

當我們鎖定位置後,它的標簽就是重疊標簽的色點。接下來,我們要通過用GUIContent.none.來重寫它。

1 2 3 4 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {     EditorGUI.PrefixLabel(position, label);     EditorGUI.PropertyField(position, property.FindPropertyRelative("position"), GUIContent.none); }

一個依舊重疊的標簽

向量仍然是重疊標簽,因為我們使用的是同樣的位置矩形,接下來,我們將用這個矩形進行替換。

1 2 3 4 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {     Rect contentPosition = EditorGUI.PrefixLabel(position, label);     EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none); }

即使不正確的定位,也不再重疊。

這看起來好了很多,但放置位置向量的數組元素太過於偏右。導致這個發生的原因是PropertyField方法調整當前的編輯器縮進級別。

通過靜態初始化EditorGUI.indentLevel的方法,設置縮進的級別。為了暫時的消除自動縮進,我們只要將其設置為零即可。

1 2 3 4 5 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {     Rect contentPosition = EditorGUI.PrefixLabel(position, label);     EditorGUI.indentLevel = 0;     EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none); }

正確定位

原文鏈接:http://catlikecoding.com/unity/tutorials/editor/custom-data/

修改Prefix

當prefix標簽變成粗體,顯示調整過的預制值時,它就無法進行任何操作。所以我們既不能立即恢復整個彈辨色點(color point),也不能輕易刪除或復制prefix標簽的數組元素。

我們需要在編輯器中設定屬性生效的起始位置,因為目前我們僅僅展示了一部分內容。我們可以使用EditorGUI。利用BeginProperty類函數創建一個新標簽,並標志著一個屬性的出現,然後使用EditorGUI。利用EndProperty類函數表示屬性的終止。這樣我們就可以通過上下文菜單(context menu)獲得擁有預期功能的標簽。

 

1 2 3 4 5 6 7 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {         label = EditorGUI.BeginProperty(position, label, property);         Rect contentPosition = EditorGUI.PrefixLabel(position, label);         EditorGUI.indentLevel = 0;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none);         EditorGUI.EndProperty();     }

 

恢復及數組功能支持

添加顏色

現在該設定顏色屬性了。為了使其在一條線上,我們必須減少矢量所占空間。由於矢量由三部分組成而顏色作為其第四部分,我們將把向量置於前75%的水平空間,把顏色置於其余的25%空間中。我們也使用單字母命名顏色標簽。

 

1 2 3 4 5 6 7 8 9 10 11 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {         label = EditorGUI.BeginProperty(position, label, property);         Rect contentPosition = EditorGUI.PrefixLabel(position, label);         contentPosition.width *= 0.75f;         EditorGUI.indentLevel = 0;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none);         contentPosition.x += contentPosition.width;         contentPosition.width /= 3f;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("color"), new GUIContent("C"));         EditorGUI.EndProperty();     }

帶顏色,但有誤。

盡管我們的標簽很短,但是它依然占據較多空間,導致顏色數據被擠到右側。這是因為無論內容長短,標簽寬度都是固定的。你可以通過調整EditorGUIUtility.labelWidth.改變標簽寬度。設置14個像素的寬度效果更佳。

 

1 2 3 4 5 6 7 8 9 10 11 12 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {         label = EditorGUI.BeginProperty(position, label, property);         Rect contentPosition = EditorGUI.PrefixLabel(position, label);         contentPosition.width *= 0.75f;         EditorGUI.indentLevel = 0;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none);         contentPosition.x += contentPosition.width;         contentPosition.width /= 3f;         EditorGUIUtility.labelWidth = 14f;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("color"), new GUIContent("C"));         EditorGUI.EndProperty();     }

 

尺寸正好的顏色標簽。

索取額外一行

默認像素可以在單行與雙行之間轉變,這取決於inspector的寬度。我們也可以這麼做。

我們必須覆蓋GetPropertyHeight method,爭取更多的垂直空間。一行的默認值是16個像素。再添加一行需要另外18個像素(包括第二行自身的16個像素及兩行間距的2個像素)。

當我們使用inspector面板時,屏幕寬度實際上就包含它的寬度,所以我們可以利用這一點。當寬度減小到333以下時,像素會轉換至多行,因此我們也要這麼做。

 

1 2 3 public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {         return Screen.width < 333 ? (16f + 18f) : 16f;     }

 

索取更多空間。

當我們把inspector寬度調小到一定程度時,就能獲得更多的垂直空間。然而,我們尚且還不能這麼做。為了實現這一目標,我們必須注意以下四點內容。

第一,通過檢查position長方形的高度,可以發現我們正在使用雙行。第二,我們需要將高度調回到16個像素,以便顏色屬性能夠保留在同一行。第三,畫完屬性標簽後,我們必須將其下移一行。第四,通過利用EditorGUI IndentedRect method,我們必須增加一級縮進級別,將其應用至position。

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {         label = EditorGUI.BeginProperty(position, label, property);         Rect contentPosition = EditorGUI.PrefixLabel(position, label);         if (position.height > 16f) {             position.height = 16f;             EditorGUI.indentLevel += 1;             contentPosition = EditorGUI.IndentedRect(position);             contentPosition.y += 18f;         }         contentPosition.width *= 0.75f;         EditorGUI.indentLevel = 0;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none);         contentPosition.x += contentPosition.width;         contentPosition.width /= 3f;         EditorGUIUtility.labelWidth = 14f;         EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("color"), new GUIContent("C"));         EditorGUI.EndProperty();     }

 

利用更多空間。

現在,我們對彈辨色點(color point)有了一個精彩簡短的描述。它支持取消(undo),重寫(redo),預制(prefabs)以及多目標編輯。如果inspector足夠寬,它只占一行,否則,占兩行。

接下來的editor教程涉及自定義列表(Custom List)。

已下載的數據資料

custom-data.unitypackage

已完成的項目。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved