簡體   English   中英

如何序列化HashSet以在檢查器中使用

[英]How to serialise HashSet for usage in inspector

Unity版本:2017.3.1f1

我正在嘗試在Unity檢查器中使用HashSet 具體來說,我需要一些MonoBehaviour來具有HashSet字段,可以通過檢查器修改其內容。

為了實現此目標,我創建了一個具體類,該類將HashSet子類化,並在內部使用List進行(反序列化),其方式與本指南中的Dictionary非常相似:

但是,我遇到一個列表顯示在檢查器中的問題,但是我不能在其中設置多個值。 如果我將列表的大小設置為2或更大,則立即將其設置回1。

為了調試該問題,我發現OnBeforeSerialize (而不是 OnAfterDeserialize )正在每幀執行一次,從而不斷重置該值。 我不確定為什么將它設置為1。

請注意,如果我在1個可用插槽中輸入了字符串,則不會被重置。 因此,此方法對於0或1個字符串(但不更多)的HashSet當前“可用”。 另外,如果我使用HashSet字段而不是從其繼承(如上述鏈接中所做的那樣),結果也不會改變。

這是一個最小的示例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TEST : MonoBehaviour
{
    public StringHashSet test;
}

[System.Serializable]
public class SerializableHashSet<T> : HashSet<T>, ISerializationCallbackReceiver
{
    public List<T> values = new List<T> ();

    public void OnBeforeSerialize ()
    {
        values.Clear ();

        foreach (T val in this) {
            values.Add (val);
        }
    }

    public void OnAfterDeserialize ()
    {
        this.Clear ();

        foreach (T val in values) {
            this.Add (val);
        }
    }
}

[System.Serializable]
public class StringHashSet : SerializableHashSet<string>
{
}
  1. 如何使它按預期工作(將任意大小的字符串列表反序列化為HashSet )?
  2. 另外,即使檢查器中未進行任何更改,為什么仍每幀執行一次OnBeforeSerialize

更多信息


我發現這是因為更改列表的大小時,默認情況下列表中的所有新元素都具有與前一個元素相同的值,因此在HashSet中將所有這些元素壓縮為1值。

因此,盡管問題2仍然懸而未決,但問題1已經演變為尋求一種解決方法,同時又保持了所需的HashSet功能。

考慮到問題中“ 更多信息”部分中添加的發現,這是我解決此問題的方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class SerializableHashSet<T> : HashSet<T>, ISerializationCallbackReceiver
{
    public List<T> values = new List<T> ();

    public void OnBeforeSerialize ()
    {
        var cur = new HashSet<T> (values);

        foreach (var val in this) {
            if (!cur.Contains (val)) {
                values.Add (val);
            }
        }
    }

    public void OnAfterDeserialize ()
    {
        this.Clear ();

        foreach (var val in values) {
            this.Add (val);
        }
    }
}

[System.Serializable]
public class StringHashSet : SerializableHashSet<string>
{
}

OnAfterDeserialize相同。

OnBeforeSerialize不再清除values列表。 相反,它會將HashSet中的新值添加到List -特別是HashSet中存在但List不存在的值。

當將新元素添加到檢查器中的列表時,這將使功能得以繼續:重復和空白條目將正常工作,因為列表不會在任何時候被清除,只會被添加到列表中。


關於第二個問題,我發現了有關為何如此頻繁執行OnBeforeSerialize以下信息: http : //answers.unity.com/answers/796853/view.html

相關資料:

如果在編輯器中打開了對象的檢查器,則調用每一幀

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM