通常你的问题很宽泛,需要很多时间。
不过,我有点喜欢 Unity 编辑器脚本,老实说,它非常复杂,而且有点难以入门,所以考虑一下这是一个进入编辑器脚本的小起点 ;)
你想要达到的目标需要四件事:
编辑器脚本可以随心所欲地变得复杂:D 所以我只会实现一个非常基本的脚本。我希望这是满足您需求的良好起点:
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class WaveList : MonoBehaviour
{
[Serializable]
public class Wave
{
public int waveCount;
public string[] enemies;
// Additional field for storing the currently selected enemy index
public int selectedEnemy;
public int[] enemyLVL;
public float[] delay;
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(Wave))]
private class WavePropertyDrawer : PropertyDrawer
{
// This will be generated during the OnGUI call
// Maybe not the cleanest way but it works for now ;)
private float height;
private string[] availableEnemies;
// This method is required so other property drawers (like the Wave[] waves)
// know how much space to reserve for drawing this property
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return height + EditorGUIUtility.singleLineHeight;
}
// Draw the property inside the given rect
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// reset the height
height = 0;
// Using BeginProperty / EndProperty on the parent property means that
// prefab override logic works on the entire property.
EditorGUI.BeginProperty(position, label, property);
{
// Get the rect for where to draw the label/foldout
var labelRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
position.y += EditorGUIUtility.singleLineHeight;
height += EditorGUIUtility.singleLineHeight;
// Draw the foldout
property.isExpanded = EditorGUI.Foldout(labelRect, property.isExpanded, property.displayName);
if (property.isExpanded)
{
// indent children for better readability
EditorGUI.indentLevel++;
{
// Get serialized Properties
var serializedWaveCount = property.FindPropertyRelative(nameof(waveCount));
var serializedEnemies = property.FindPropertyRelative(nameof(enemies));
var serializedSelectedEnemy = property.FindPropertyRelative(nameof(selectedEnemy));
var serializedEnemyLVL = property.FindPropertyRelative(nameof(enemyLVL));
var serializedDelay = property.FindPropertyRelative(nameof(delay));
// Calculate rects
var waveCountHeight = EditorGUI.GetPropertyHeight(serializedWaveCount);
var waveCountRect = new Rect(position.x, position.y, position.width, waveCountHeight);
position.y += waveCountHeight;
height += waveCountHeight;
var enemiesHeight = EditorGUI.GetPropertyHeight(serializedEnemies, true);
var enemiesRect = new Rect(position.x, position.y, position.width, enemiesHeight);
position.y += enemiesHeight;
height += enemiesHeight;
var selectedEnemyRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
position.y += EditorGUIUtility.singleLineHeight;
height += EditorGUIUtility.singleLineHeight;
var enemeiesLevelHeight = EditorGUI.GetPropertyHeight(serializedEnemyLVL, true);
var enemeiesLVLRect = new Rect(position.x, position.y, position.width, enemeiesLevelHeight);
position.y += enemeiesLevelHeight;
height += enemeiesLevelHeight;
var delayHeight = EditorGUI.GetPropertyHeight(serializedDelay, true);
var delayRect = new Rect(position.x, position.y, position.width, delayHeight);
position.y += delayHeight;
height += delayHeight;
// Draw Fields
availableEnemies = new string[serializedEnemies.arraySize];
for (var i = 0; i < serializedEnemies.arraySize; i++)
{
availableEnemies[i] = serializedEnemies.GetArrayElementAtIndex(i).stringValue;
}
EditorGUI.PropertyField(waveCountRect, serializedWaveCount);
EditorGUI.PropertyField(enemiesRect, serializedEnemies, true);
if (serializedEnemies.arraySize == 0)
{
serializedSelectedEnemy.intValue = -1;
}
serializedSelectedEnemy.intValue = EditorGUI.Popup(selectedEnemyRect, serializedSelectedEnemy.displayName, serializedSelectedEnemy.intValue, availableEnemies);
EditorGUI.PropertyField(enemeiesLVLRect, serializedEnemyLVL, true);
EditorGUI.PropertyField(delayRect, serializedDelay, true);
}
EditorGUI.indentLevel--;
}
}
EditorGUI.EndProperty();
}
}
#endif
}
public Wave[] waves;
}
所以稍后为了得到你要访问的实际选定的敌人
var enemy = someWave.enemies[someWave.selectedEnemy];
现在您可以添加、编辑和删除enemies,然后通过下拉菜单选择特定的
关于如何为所有波全局定义可用的enemies 的问题:
您可能应该将可用数组移动到 WaveList 类中,并且只在其中定义一次。
同样,这里现在可以工作,但很脏
public class WaveList : MonoBehaviour
{
public string[] availableEnemies;
}
然后在Wave中只存储选中的index like
[Serializable]
public class Wave
{
public int waveCount;
public int selectedEnemy;
public int[] enemyLVL;
public float[] delay;
...
然后在属性抽屉中而不是
var serializedEnemies = property.FindPropertyRelative(nameof(enemies));
您宁愿直接从WaveList 类使用
var serializedEnemies = property.serializedObject.FindProperty(nameof(WaveList.availableEnemies));
注意:在手机上打字,但我希望思路清晰