目的
SerializeField属性でインスペクタにListを表示している場合、編集時に条件で要素をフィルターしたい。
結論
ISerializationCallbackReceiverを実装し、OnBeforeSerialize()内でListを編集する。
ScriptableObjectをインスペクタで表示した場合を想定したコードを下記に示す。
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public enum SomeEnum
{
None,
A,
B,
C
}
[Serializable]
public class SomeSerializableClass
{
[SerializeField]
SomeEnum type;
public SomeEnum Type => type;
}
public class SomeScriptableObject : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField]
List<SomeSerializableClass> list;
int prevCount;
void Awake()
{
prevCount = list.Count;
}
public void OnAfterDeserialize() { }
public void OnBeforeSerialize()
{
if (list is null)
{
return;
}
if (prevCount < list.Count)
{
list[^1] = new();
}
list = list
.GroupBy(x => x.Type)
.Select(x => x.First())
.ToList();
prevCount = list.Count;
}
}
失敗例
下記コードは、インスペクタ上で要素の追加ができなくなる。
インスペクタで要素を追加した時、最後の要素が複製されて追加されるが、それが重複とみなされ排除されてしまうためである。
public class SomeBehaviour : MonoBehaviour, ISerializationCallbackReceiver
{
[SerializeField]
List<SomeSerializableClass> list;
public void OnAfterDeserialize() { }
public void OnBeforeSerialize()
{
if (list is null)
{
return;
}
list = list
.GroupBy(x => x.Type)
.Select(x => x.First())
.ToList();
}
参考