Skip to content

Instantly share code, notes, and snippets.

@Angeart
Created February 8, 2021 16:26
Show Gist options
  • Select an option

  • Save Angeart/8c4434abfb8ab3d7e30f1801ae882d56 to your computer and use it in GitHub Desktop.

Select an option

Save Angeart/8c4434abfb8ab3d7e30f1801ae882d56 to your computer and use it in GitHub Desktop.
StringEnum on Unity
public enum ItemCategory
{
Consumption,
Wearable,
Event,
}
// ここ必須
[Serializable]
public class ItemCategoryStringEnum : StringEnum<ItemCategory>
{
}
public class Item : ScriptableObject
{
public ItemCategoryStringEnum Category = new ItemCategoryStringEnum();
}
using System;
using UnityEngine;
namespace Utils
{
public class StringEnumBase
{
}
public class StringEnum<T>: StringEnumBase, ISerializationCallbackReceiver where T : struct
{
[SerializeField] private string _internalValue = string.Empty;
private T m_Value = default(T);
public T Value { get; set; }
public static StringEnum<E> Create<E>(E value) where E : struct
{
StringEnum<E> instance = new StringEnum<E>();
instance.m_Value = value;
return instance;
}
public void OnBeforeSerialize()
{
this._internalValue = this.m_Value.ToString();
}
public void OnAfterDeserialize()
{
if (String.IsNullOrEmpty(this._internalValue))
{
this._internalValue = this.m_Value.ToString();
}
this.m_Value = Utils.Enum.Parse<T>(ref _internalValue);
}
}
}
using System;
using System.Linq;
using System.Reflection;
using Sirenix.Utilities;
using UnityEditor;
using UnityEngine;
namespace Utils.Editor
{
[CustomPropertyDrawer(typeof(StringEnumBase), true)]
public class StringEnumInspector : PropertyDrawer
{
private Type GetPropertyType(SerializedProperty property)
{
string[] slices = property.propertyPath.Split('.');
System.Type type = property.serializedObject.targetObject.GetType();
for(int i = 0; i < slices.Length; i++)
{
if (slices[i] == "Array")
{
i++; //skips "data[x]"
type = type.GetElementType(); //gets info on array elements
}
//gets info on field and its type
else
{
type = type.GetField(slices[i], BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance).FieldType;
}
}
return type;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
label = EditorGUI.BeginProperty(position, label, property);
var type = GetPropertyType(property);
var valuePropertyInfo = type.GetProperty("Value");
var nameList = valuePropertyInfo != null ? System.Enum.GetNames(valuePropertyInfo.PropertyType).ToList() : Enumerable.Empty<string>().ToList();
var internalValueProperty = property.FindPropertyRelative("_internalValue");
var targetObjectType = property.serializedObject.targetObject.GetType();
var referenceObjectPropertyInfo = targetObjectType.GetMember(property.propertyPath);
object referenceObject = referenceObjectPropertyInfo?.First()
.GetMemberValue(property.serializedObject.targetObject);
var internalValue = internalValueProperty.stringValue;
if (String.IsNullOrEmpty(internalValue)) internalValue = nameList.First();
var currentIndex = nameList.FindIndex(v => v == internalValue);
if (currentIndex < 0) currentIndex = 0;
int index = EditorGUI.Popup(position, label.text, currentIndex, nameList.ToArray());
if (index < 0) index = 0;
internalValueProperty.stringValue = nameList[index];
valuePropertyInfo?.SetValue(referenceObject, index);
EditorGUI.EndProperty();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment