В List в инспекторе мой класс отображается как стандартный, хотя у класса есть кастомный инспектор
Мне нужно хранить длинный список классов "DataFrame". В "DataFrame" много полей, поэтому лист сильно растягивается. Я хочу создать пользовательский инспектор для "DataFrame", чтобы все его данные отображались в 3 строках.
Когда я переопределяю "OnInspectorGUI" для класса, он отображается в списке так, как будто "OnInspectorGUI" не был переопределен. В то же время, если я наследую класс от "ScriptableObject" или "MonoBehaviour", он отображается в инспекторе с переопределенным "OnInspectorGUI".
Проблема в отображении только в списке.
Вот как выглядит лист:
Вот как выглядит ScriptableObject:
Классы:
[System.Serializable]
public class DataFrame
{
public const int LINES_NUMBER = 10;
[Header("Units")]
public float UnitZombieHealthCoefficient;
public int UnitMonsterNumber;
[Space(5)]
public float UnitEnemyCountCoefficient;
[Header("Objects")]
public int ObjTrapNumber;
public int ObjCoinNumber;
[Header("Control point Chance")]
public float CpShopCoefficient;
public float CpEventCoefficient;
public float CpAbibityCoefficient;
public float CpCoinsCoefficient;
}
[CustomEditor(typeof(DataFrame))]
public class DataStageEditor : Editor
{
#region SerializedProperties
SerializedObject _serializedObject;
SerializedProperty _zombieHealthCoefficient;
SerializedProperty _monsterNumber;
SerializedProperty _enemyCountCoefficient;
SerializedProperty _trapNumber;
SerializedProperty _coinNumber;
SerializedProperty _shopCoefficient;
SerializedProperty _eventCoefficient;
SerializedProperty _abibityCoefficient;
SerializedProperty _coinsCoefficient;
#endregion
private void OnEnable() {
SetProperties();
}
private void SetProperties() {
_serializedObject = new SerializedObject(target);
_zombieHealthCoefficient = _serializedObject.FindProperty(nameof(DataFrame.UnitZombieHealthCoefficient));
_monsterNumber = _serializedObject.FindProperty(nameof(DataFrame.UnitMonsterNumber));
_enemyCountCoefficient = _serializedObject.FindProperty(nameof(DataFrame.UnitEnemyCountCoefficient));
_trapNumber = _serializedObject.FindProperty(nameof(DataFrame.ObjTrapNumber));
_coinNumber = _serializedObject.FindProperty(nameof(DataFrame.ObjCoinNumber));
_shopCoefficient = _serializedObject.FindProperty(nameof(DataFrame.CpShopCoefficient));
_eventCoefficient = _serializedObject.FindProperty(nameof(DataFrame.CpEventCoefficient));
_abibityCoefficient = _serializedObject.FindProperty(nameof(DataFrame.CpAbibityCoefficient));
_coinsCoefficient = _serializedObject.FindProperty(nameof(DataFrame.CpCoinsCoefficient));
}
public override void OnInspectorGUI() {
EditorGUILayout.LabelField("TEST");
EditorGUILayout.PropertyField(_zombieHealthCoefficient, true);
EditorGUILayout.PropertyField(_monsterNumber, true);
EditorGUILayout.PropertyField(_enemyCountCoefficient, true);
EditorGUILayout.Space(50);
EditorGUILayout.PropertyField(_trapNumber, true);
EditorGUILayout.PropertyField(_coinNumber, true);
EditorGUILayout.PropertyField(_shopCoefficient, true);
EditorGUILayout.PropertyField(_eventCoefficient, true);
EditorGUILayout.PropertyField(_abibityCoefficient, true);
EditorGUILayout.PropertyField(_coinsCoefficient, true);
}
Ответы (2 шт):
Мне порекомендовали использовать PropertyDrawer для этого.
Вот полезные видео которые быстро дадут понимание о PropertyDrawer: https://www.youtube.com/watch?v=ur-qy6SjVQw
Из документации Custom Editors, первое предложение, первого абзаца:
To speed up application development, create custom editors FOR COMPONENTS you commonly use.
На самом деле речь не только о упомянутых Component
(MonoBehaviour
от него наследуется), а о всех UnityEngine.Object
, включая ScriptableObject
.
Твой класс DataFrame
является не UnityEngine.Object
, а базовым классом C#
, object
. Инспектора он не имеет вовсе!
Для кастумной отрисовки отдельных типов, как например Vector3
, используемых в множестве инспекторов, как поле, есть PropertyDrawer. Твой DataFrame
кстати не имеет поведения, а лишь модель данных, набор полей объединённая в одну логическую сущность, как упомянутый Vector3
, для чего обычно используют struct
, а не class
.
Писать кастомные редакторы или драверы только для хедеров и пробелов, бесполезная трата времени. Более того, это явно указывает на ошибки перегруженности ответственности и необходимость дробления, например:
[Serializable]
public struct LevelData
{
public LevelOptions options;
public LevelEnemies enemy;
public LevelInteractingEnvironment environment;
}
[Serializable]
public struct LevelOptions
{
public float shopFactor;
public float eventFactor;
public float abibityFactor;
public float coinsFactor;
}
[Serializable]
public struct LevelEnemies
{
public int count;
public float countFactor;
public float healthFactor;
}
[Serializable]
public struct LevelInteractingEnvironment
{
public int trapCount;
public int coinCount;
}
И контекст типа level.enemy.count
не требует никаких комментариев и уж тем более хедеров, которые где-то там и выглядит в инспекторе хорошо, без написания дополнительного и бестолкового кода. Даже разбивать на отдельные файлы не стоит, можно всё в каком-нибудь LevelTypes.cs
или тот-же LevelData.cs
оставить.
И нужно следить за неймингом, что бы и смысл был и однозначность, а не как у тебя unit
/enemy
/monster
/zombie
и всё обозначает одно и то-же.
В struct
нельзя указывать дефолтные значения, но можно поступать так-же как Vector3.right
, через static
:
public struct LevelEnemies
{
...
public static LevelEnemies defaultValues
=> new LevelEnemies() { count = 10, countFactor = 1f, healthFactor = 1f };
}