Unity3d Inspector面板實現set/get訪問器


     簡單說一下屬性和字段的區別:字段就是成員變量,而屬性確實提供給外部訪問內部成員變量的接口。之所以會有屬性的出現,就是為了避免外部對類的成員的直接訪問,通俗的說就是OOP中的封裝思想。

using UnityEngine;
using System.Collections;

public class DemoTest : MonoBehaviour {


    private int _score;
    public int Score
    {
        get { return _score; }
        set
        {

            if (value > 100)
            {
                value = 100;
            }
            _score = value;
        }
    }
}

     上面的示例中_score就是字段或者叫成員變量,,而Score其實是C#語法簡化的方法,提供了私有成員_score對外部的訪問接口,當我們通過Score更改_score的值時就會觸發set{…}代碼段的代碼執行,這樣就完成了對_score的范圍限制,這里就體現了OOP中的封裝的好處啦。。。。關於屬性和字段的介紹就到此為止,下面說一下這篇文章的主題。

     在Unity中可以把字段使用[SerializeField]的方式序列化到Inspector面板(至於什么是序列化,讀者可以自行百度),當然public 訪問權限的字段是隱式添加[SerializeField],所以可以直接被序列化的,private的字段也可以手動添加[SerializeField]來實現序列化的比如上述的例子中我簡單在_score上添加[SerializeField],就可以在Inspector面板上直接對_score賦值了

using UnityEngine;
using System.Collections;

public class DemoTest : MonoBehaviour {

    [SerializeField]
    private int _score;
    public int Score
    {
        get { return _score; }
        set
        {

            if (value > 100)
            {
                value = 100;
            }
            _score = value;
        }
    }
}

此時可以在Inpector面板中看到:捕獲

之所以會顯示Score,而不是_score,這是unity3d在顯示的時候做的一些處理,不必關注。然而此時我們如果直接修改Score的值到120,那么我們其實直接修改的_score的值,而不是通過屬性Score來訪問的,所以我們限定的_score<=100,就不在起作用了,那么如果在工程中有這種需求該怎么處理呢?有兩種方案可供選擇,先說第一種寫Editor的方式實現:

using UnityEngine;
using System.Collections;

public class DemoTest : MonoBehaviour {

   // [SerializeField]
    private int _score;

    public int Score
    {
        get { return _score; }
        set
        {
           
            if (value > 100)
            {
                value = 100;
            }
            print("set _score value = " + value);
            _score = value;
        }
    }
}

自定義的Editor類源碼(當然該類必須放在Editor目錄下:

using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(DemoTest))]    //為DemoTest添加一個自定義標簽
public class EditorTest : Editor {

    public override void OnInspectorGUI()   //當DemoTest在Inspector面板上顯示改動時觸發
    {
        DemoTest demoTest = target as DemoTest; //target是Eiditor內部封裝的當前操作的對象引用
        int score = EditorGUILayout.IntField("Score", demoTest.Score);//在Inspector面板上序列化一個對象,並關聯demoTest.Score屬性
        if (demoTest.Score != score)//如果該屬性在改動后沒有觸發就手動觸發
        {
            demoTest.Score = score;
        }
        base.DrawDefaultInspector();//重回Inspector面板
    }
}

這樣當我們修改Socre時就可以在Console中看到相應的輸出了,也就解決了set、get方法封裝性問題。當然這種方式很有局限性,使用起來十分不方便,還有一種簡便的方式,使用SetProperty標簽,當然我個人由於unity版本過低,SetProperty還不支持,,應該要5.0以后的版本吧,這里附上鏈接:https://github.com/LMNRY/SetProperty


免責聲明!

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



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