Hello there,
So, I’m working on my game Swords and Souls 2 (#ShamelessPromo), and I have this CombatData class which contains an array of CombatWave, and each of this CombatWave contains an array of enum EnemyType. Here is the code, just to be clear:
public class CombatData : MonoBehaviour {
[SerializeField]
private string title;
[SerializeField]
private CombatWave[] waves;
}
[System.Serializable]
public class CombatWave {
[SerializeField]
public EnemyType[] enemyList;
}
public enum EnemyType {
Orc,
Goblin,
Gnobul
}
So, here is what I have in the Inspector:

… And here is what I would like to have, more or less:

The “+” button would add a row, (I’d need a “-” button as well). Each row represents a CombatWave with the 3 EnemyType it contains. (I won’t ever have more than 3 enemies per wave, so no worry). That would be the most convenient way for me to handle my CombatData, I think.
I’ve look around for custom Class serialization or Array serialization, etc. but it’s always unclear or too complicated, or doesn’t fit my needs. I know I’d have to deal with Editor stuff and all, but I’m terrible with Editor related stuff, I’m just not a coding God, I need to work from a good model, or with solid leads.
If someone can help by providing code, ideas, leads, or examples of similar customized Component, I would greatly appreciate!
Thanks for your help and time
using UnityEngine;
using System;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(WaveStarter))]
public class Wave2DArrayPropDrawer : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
WaveStarter ws = target as WaveStarter;
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("Waves");
GUILayout.FlexibleSpace();
if (GUILayout.Button("+"))
{
Undo.RecordObject(ws, "Add Wave");
WaveStarter.Wave wave = new WaveStarter.Wave();
wave.wave = new WaveStarter.Type[0];
ArrayUtility.Add(ref ws.waves, wave);
}
}
EditorGUILayout.EndHorizontal();
EditorGUI.indentLevel++;
{
const float labelWidth = 20;
const float minusWidth = 20;
GUILayoutOption enumWidth = GUILayout.Width((EditorGUIUtility.currentViewWidth - labelWidth - minusWidth) / 3f - 20); // -20 because EnumPopup seems to add some padding that I don't know where it comes from...
GUILayoutOption minusWidthOp = GUILayout.Width(minusWidth);
Undo.RecordObject(ws, "Edit Wave");
for (int wave = 0; wave < ws.waves.Length; wave++)
{
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label(wave.ToString(), GUILayout.Width(labelWidth));
for (int enemy = 0; enemy < ws.waves[wave].wave.Length; enemy++)
{
ws.waves[wave].wave[enemy] = (WaveStarter.Type)EditorGUILayout.EnumPopup(ws.waves[wave].wave[enemy], enumWidth);
if (ws.waves[wave].wave[enemy] == WaveStarter.Type.None)
{
ArrayUtility.RemoveAt(ref ws.waves[wave].wave, enemy);
enemy--; // to compensate for next j++
}
}
if (ws.waves[wave].wave.Length < 3)
{
WaveStarter.Type add = WaveStarter.Type.None;
add = (WaveStarter.Type)EditorGUILayout.EnumPopup(add, enumWidth);
if (add != WaveStarter.Type.None)
ArrayUtility.Add(ref ws.waves[wave].wave, add);
}
GUILayout.FlexibleSpace();
if (GUILayout.Button("-", minusWidthOp))
{
ArrayUtility.RemoveAt(ref ws.waves, wave);
wave--; // to compensate for next i++;
}
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUI.indentLevel--;
}
}
#endif
public class WaveStarter : MonoBehaviour
{
public enum Type
{
Orc, Gnobul, JeanLouis, None
};
[Serializable]
public struct Wave
{
public Type[] wave; // max 3 by tacit contract!
}
[HideInInspector] // we are going to draw it ourselves so useless
public Wave[] waves = new Wave[0];
}
Quick hack, gives me this :

1 Like