Unity中的SerializeReference使用簡介

来源:https://www.cnblogs.com/liougouren/p/18023731
-Advertisement-
Play Games

Unity 預設可以序列化值類型, Serializable屬性修飾的類型, 派生自UnityEngine.Object的類型, 通常這些類型已經足以供日常使用了. 但是有時我們希望在編輯器面板上序列化一個介面或者抽象類, 則需要用到 SerializeReference屬性. 假定我們有一個介面I ...


Unity 預設可以序列化值類型, Serializable屬性修飾的類型, 派生自UnityEngine.Object的類型, 通常這些類型已經足以供日常使用了.
但是有時我們希望在編輯器面板上序列化一個介面或者抽象類, 則需要用到 SerializeReference屬性.

假定我們有一個介面IEatable, 並實現了兩個類BreadBun:

public interface IEatable
{
    int Calorie { get; }
}

public class Bread : IEatable
{
    [field: SerializeField]
    public int Calorie { get; private set; } = 100;
}

public class Bun : IEatable
{
    public enum Fillings
    {
        [InspectorName("肉餡")]
        Meat,

        [InspectorName("韭菜雞蛋")]
        LeekAndAgg,
    }

    [field: SerializeField]
    public int Calorie { get; private set; } = 200;

    [field: SerializeField]
    public Fillings Filling { get; private set; }
}

相應的, 我們定義了一個餐盤類去盛放食物Plate:

[CreateAssetMenu(menuName = "Plate for Food")]
public class Plate : ScriptableObject
{
    private IEatable _eatable;

    public IEatable Eatable { get => _eatable; set => _eatable = value; }
}

在Unity編輯器內右鍵新建一個Plate, 可見Inspector面板上沒有顯示Eatable欄位.

預設檢視面板

此時我們為_eatable欄位添加SerializeReference屬性.

註意, 添加SerializeReference後, 即使欄位是私有的, 也無需添加SerializeField屬性, 二者同有將私有欄位序列化的能力.

[CreateAssetMenu(menuName = "Plate for Food")]
public class Plate : ScriptableObject
{
    [SerializeReference]
    private IEatable _eatable;

    public IEatable Eatable { get => _eatable; set => _eatable = value; }
}

添加SerializeReference屬性後, Inspector面板上已經可以顯示Eatable欄位了, 但是由於此時_eatable欄位的值為null, 所以並沒有顯示其他信息.

SerializeReference屬性允許欄位為null, 這點與預設序列化行為不同, 預設序列化會自動實例化一個值

添加SerializeReference屬性後的檢視面板

接下來我們在Plate中定義一個方法ServeBread, 將_eatable欄位設置為Bread實例, 並使用ContextMenuItem屬性將此方法設置為_eatable欄位的上下文菜單:


    [ContextMenuItem("盛放麵包", "ServeBread", order = 0)]
    [ContextMenuItem("盛放包子", "ServeBun", order = 1)]
    [SerializeReference]
    private IEatable _eatable;

    ...
    
    private void ServeBread() => _eatable = new Bread();

    private void ServeBun() => _eatable = new Bun();

    ...

回到Unity編輯器, 此時我們就可以右鍵點擊Eatable欄位併在彈出菜單中選擇一項來為_eatable欄位賦值了.

添加[field: SerializeField]後, 屬性也可以像欄位一樣被序列化, 但是其label會顯示為<屬性名>k__BackingField, 如果不希望這種現象,可以將屬性轉化為完整屬性併為對應的私有欄位添加SerializeField.

設置ContextMenuItem屬性後的檢視面板

用文本編輯器打開Plate.asset文件, 可以看到使用SerializeReference屬性進行序列化後的內容, 可以對比一下普通的序列化方式.

序列化內容

其中, type記錄了欄位內容的具體類型class, 所在命名空間ns, 所在的程式集asm. 而data則記錄了實例的可序列化欄位及內容.

ContextMenuItem方式只是為了演示, 合理的做法應該是自行實現對應的PropertyDrawer.

SerializeReference還可以修飾List<T>T[], 具體情況可以查看Unity官方文檔, 這裡就不贅述了.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先,跨域的域是什麼? 跨域的英文是:Cross-Origin。 Origin 中文含義為:起源,源頭,出生地。 在跨域中,"域"指的是一個 Web 資源(比如網頁、腳本、圖片等)的源頭。 包括該資源的協議、主機名、埠號。 在同源策略中,如果兩個資源的域相同,則它們屬於同一域,可以自由進行交互和共 ...
  • 通過使用Python編程語言,編寫腳本來自動化Excel和CSV之間的轉換過程,可以批量處理大量文件,定期更新數據,並集成轉換過程到自動化工作流程中。本文將介紹如何使用第三方庫Spire.XLS for Python 實現: 使用Python將Excel轉為CSV 使用Python 將CSV轉為Ex ...
  • 多年不用PageHelper了,最近新入職的公司,採用了此工具集成的框架,作為一個獨立緊急項目開發的基礎。項目開發起來,還是手到擒來的,但是沒想到,最終測試的時候,深深的給我上了一課。 我的項目發生了哪些奇葩現象? 一切的問題都要從我接受的項目開始說起, 在開發這個項目的過程中,發生了各種奇葩的事情 ...
  • OOM 幾乎是筆者工作中遇到的線上 bug 中最常見的,一旦平時正常的頁面線上上出現頁面崩潰或者服務無法調用,查看伺服器日誌後你很可能會看到“Caused by: java.lang.OutOfMlemoryError: Java heap space” 這樣的提示,那麼毫無疑問表示的是 Java ... ...
  • 引入依賴 <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.8.7</version> </dependency> 基本用法 try (Entry ent ...
  • 一、程式計數器 程式計數器記憶體很小,可以看作是當前線程所執行位元組碼的行號指示器。 有了它,程式就能被正確的執行。 因為有線程切換的存在,則每個線程必須有各自獨立的程式計數器,即線程私有的記憶體。 這裡再解釋一下什麼是線程切換,線程切換指的是: 單處理器在執行多線程時所進行的線程切換,多線程的交替運行會 ...
  • 常見內置序列類型(Sequence Type) 類型 英文名 對應關鍵字 構造函數 是否可變 列表 list list list() 可變 元組 tuple tuple tuple() 不可變 數字序列:range range range range() 不可變 文本序列:字元串 string st ...
  • 最近看幾個老項目的SQL條件中使用了1=1,想想自己也曾經這樣寫過,略有感觸,特別拿出來說道說道。編寫SQL語句就像炒菜,每一種調料的使用都會影響菜品的最終味道,每一個SQL條件的加入也會影響查詢的執行效率。那麼 1=1 存在什麼樣的問題呢?為什麼又會使用呢? ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...