Unity3D中的Attribute詳解(七)


本章我們將依然講解Unity中的Attribute,繼續命名空間在UnityEngine里的。

PropertyAttribute,這個特性主要來控制變量或者類在Inspector里面的顯示方式。和PropertyDrawer類掛鈎,具體用法我將在之后開一系列講解UnityEditor的文章中講解。

Range,這個特性很好理解。給值類型一個范圍, 代碼如下:

在監視面板里,我們將會看到10的初始值,只要一動滑條,你的值就被限制在0-2之間了。

RequireComponent,自動添加所需的component,這個用來避免一些存在依賴關系而導致的錯誤。

如代碼:

或者

在監視器里會自動產生依賴項:

 如果你想要刪除Test腳本,會報錯。這個屬性默認的構造函數,參數支持1-3個component,如果太多,可以分開寫。

我們繼續修改代碼:

如果兩個類有繼承關系,也不能添加:

不過一般情況下,我們手動也無法添加兩個有繼承關系的組件,這不難理解。

RuntimeInitializeOnLoadMethod,這個屬性時Unity5.0后新加的一個特性。如果好好利用起來,這個特性將會非常有用。

比如我們啟動游戲的時候,會寫一些數據的初始化工作,這些類不需要作為一個monobehaviour存在,但我們需要一個程序入口來驅動,所以不得不用一個GameObject來作為GameEntry。這個特性就可以做到。

首先我們寫一個普通類,沒有從Mono繼承,代碼如下:

public class RuntimeLoad 
{
    [RuntimeInitializeOnLoadMethod]
    static void OnRuntime1 () 
    {
        Debug.Log("On Run Time 1");    
    }
    
    [RuntimeInitializeOnLoadMethod]
    static void OnRuntime2()
    {
        Debug.Log("On Run Time 2");    
    }

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void OnRuntime3()
    {
        Debug.Log("On Run Time 3");
    }

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    static void OnRuntime4()
    {
        Debug.Log("On Run Time 4");
    }
}

需要注意,這個特性必須在靜態函數上面插入,否則不會生效。可以看到這是一個正常的C#類,不加特性的情況下,肯定不會自動執行。

其中OnRunTime1和2都是沒有參數的,完全一致,我們用來驗證系統的執行順序,然后3和4加了參數,可以看出一個是場景加載前,一個場景加載后。

RuntimeInitializeOnLoadMethod也可以加在monobehaviour上,為了驗證調用順序,我們在Hierarchy窗口的最上面的一個GameObject(之后統一稱為GO)和最下面的GO上分別添加了兩個腳本,這兩個腳本都會在Awake, OnEnable和Start中輸出,其次加了三個靜態函數,和上述OnRuntime2,3,4一致。這里代碼省略了。

然后運行程序,可以看到:

首先輸出的帶場景加載之前參數的,不論常規類還是unity組件的,然后是Awake和OnEnable,緊接着不加參數的特性和加了場景加載之后參數的一起輸出,最后是Start方法。

總結:

1),加了BeforeSceneLoad參數的先輸出,非Monobehaviour的類最先輸出,然后是在Hierarchy窗口中位置靠下的輸出,最后是位置靠上的輸出。

2),這時候進入了LoadScene階段,因此會調用Awake和OnEnable方法,還是位置下面的先調用。

3),這時候,加了AfterSceneLoad參數的開始輸出。順序和1)一樣。沒有加參數的同加了AfterSceneLoad的。

4),Start方法被調用。

相信看完這個實例后,對於這個特性的用法大家都了然於心了。

 SelectionBase,關於這個特性,先看操作:

新建一個GameObject1,建一個子節點GameObject2,再建一個Cube作為GO2的子節點。

注意GO1和GO2都是空的GO。

在Scene里面選擇我們剛才創建的Cube,選中后的狀態是:

系統會默認選擇Cube。現在我們在GO2上加了一個配置信息,需要經常改變,如果一直定位在Cube上就太麻煩了。有兩種解決辦法,一種是手動去選。。。還有一種就是用SelectionBase。

新建一個腳本,代碼如下:

將其附加到GO2物體上,然后再次重復選擇操作。

可以看到GO2先被選中了,再點擊的話能夠輪詢到Cube。因此SelectionBase的作用可以讓沒有實體的GO被選中。

我們在GO1上也加一個SelectionBase,再次點擊,還是只能選中GO2,多次點擊也無法選到GO1,我把GO2的腳本移除就可以點到GO1了。

我猜測,SelectionBase可能在同一根目錄物體下,只有一份會起作用。因此我修改了場景里的物件如下:

其中GO1,GO2,GO2(1)都帶有selectionbase特性。一次點擊,可以看到如下順序:

然后就跳出根目錄了,基本上驗證了我的猜想,這個點需要注意一下。

其實Unity自己封裝了一個可選組件:

這個組件基本功能是一樣的,它的功能更多一點,可以做一些交互的響應等。如果沒有特殊需求不建議用這個。

 SharedBetweenAnimators,這個特性只能作用於派生自StateMachineBehaviour的類,指定該類僅會實例化一次,並且在所有的Animator實例之間共享,可以減少每個控制器實例的內存占用。注意,如果你的StateMachineBehaviour更改了一些成員變量,它將影響所有使用它的Animator實例。

 Space,用於在Inspector面板上的參數之間加空行。

其中space的參數為高度,也可以不加。

TextArea,默認string在Inspector面板上的顯示一行

添加TextArea可以變成一塊更靈活的文本編輯區

可選參數可以設置最小和最大行數。並且不能用於非string類型。

ToolTip可以在Inspector參數上添加一個懸浮提示。修改代碼如下:

鼠標懸浮在在Inspector面板可以看到:

UnityAPICompatibilityVersion,聲明一個程序集與特定的Unity API兼容。由內部工具使用,確定程序集是否能夠使用舊的UNITY API。

一般用不到,想了解詳情的同學可以去

 https://blogs.unity3d.com/cn/2015/01/06/assemby-updater-faster-api-usage-detection/

https://blogs.unity3d.com/cn/2014/06/23/unity5-api-changes-automatic-script-updating/

這兩篇文章看一下。

至此我們在UnityEngine命名空間下的Attribute都講完了,因為實在太多,UnityEditor命名空間下的Attribute我們將在下一篇文章進行講解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM