C# 数组C的Unity自定义下拉选择
我试图简化波浪系统中预制件的选择C# 数组C的Unity自定义下拉选择,c#,unity3d,dropdown,unity-editor,unity3d-editor,C#,Unity3d,Dropdown,Unity Editor,Unity3d Editor,我试图简化波浪系统中预制件的选择 using System.Collections; using System.Collections.Generic; using UnityEngine; public class WaveList : MonoBehaviour { [System.Serializable] public class Wave { public int waveCount; public string[] enemi
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaveList : MonoBehaviour
{
[System.Serializable]
public class Wave
{
public int waveCount;
public string[] enemies;
public int[] enemyLVL;
public float[] delay;
}
public Wave[] waves;
}
我试图在Unity编辑器中有一个下拉菜单来选择每个敌人的值
敌人通过下拉菜单
非常感谢您的帮助
干杯通常你的问题很广泛,需要很多时间 但是,我有点喜欢统一编辑脚本,老实说,这是非常复杂的,有点难进去,所以考虑一下,这有点跳跃到编辑器脚本;p> 你想要实现的目标需要四件事: 用于存储可用值的字段 填充这些可用值的方法 用于存储当前选定值的附加字段 实施 编辑器脚本可能会变得非常复杂:因此我将只实现一个非常基本的脚本。我希望这是满足您需求的良好起点:
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;
}
现在你可以添加、编辑和删除敌人,然后通过下拉菜单选择一个特定的敌人
关于如何为所有波定义全局可用敌人的问题:
您可能应该将可用的数组移动到WaveList类中,然后像这样只定义一次
同样,这个现在可以用了,但是很脏
public class WaveList : MonoBehaviour
{
public string[] availableEnemies;
}
然后在Wave中只存储选定的索引,如
[Serializable]
public class Wave
{
public int waveCount;
public int selectedEnemy;
public int[] enemyLVL;
public float[] delay;
...
然后放在财产抽屉里,而不是
var serializedEnemies = property.FindPropertyRelative(nameof(enemies));
您更愿意使用
var serializedEnemies = property.serializedObject.FindProperty(nameof(WaveList.availableEnemies));
注意:在电话上打字,但我希望你的想法变得清晰。通常你的问题很广泛,需要很多时间 但是,我有点喜欢统一编辑脚本,老实说,这是非常复杂的,有点难进去,所以考虑一下,这有点跳跃到编辑器脚本;p> 你想要实现的目标需要四件事: 用于存储可用值的字段 填充这些可用值的方法 用于存储当前选定值的附加字段 实施 编辑器脚本可能会变得非常复杂:因此我将只实现一个非常基本的脚本。我希望这是满足您需求的良好起点:
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;
}
现在你可以添加、编辑和删除敌人,然后通过下拉菜单选择一个特定的敌人
关于如何为所有波定义全局可用敌人的问题:
您可能应该将可用的数组移动到WaveList类中,然后像这样只定义一次
同样,这个现在可以用了,但是很脏
public class WaveList : MonoBehaviour
{
public string[] availableEnemies;
}
然后在Wave中只存储选定的索引,如
[Serializable]
public class Wave
{
public int waveCount;
public int selectedEnemy;
public int[] enemyLVL;
public float[] delay;
...
然后放在财产抽屉里,而不是
var serializedEnemies = property.FindPropertyRelative(nameof(enemies));
您更愿意使用
var serializedEnemies = property.serializedObject.FindProperty(nameof(WaveList.availableEnemies));
注意:在电话上打字,但我希望这个想法变得清晰这需要你的课堂上有一个。。。您从何处获得可用值?我希望有一个可以随时间添加到的数组,,将根据解决方案进行设置这将需要为您的类设置一个。。。从何处获取可用值?我希望有一个可以随时间添加到的数组,它将基于solutionAmazing进行设置。谢谢你抽出时间。是否可以让敌人[]中的每个元素都是所有波从一个阵列中选取的下拉选项?基本上,我试图使它容易和快速地选择敌人在每波。当你有100+时,拖放到数组中会变成一场噩梦waves@CodingNoob_Help如前所述,您将需要一种方法来填充可用的敌人值。。。你从哪里拿这些取决于你自己。例如,您可以将数组本身放置在WaveList类中,还可以为该类实现一个CustomEditor,将数组注入Wave中的所有项中……太棒了。谢谢你抽出时间。是否可以让敌人[]中的每个元素都是所有波从一个阵列中选取的下拉选项?基本上,我试图使它容易和快速地选择敌人在每波。当你有100+时,拖放到数组中会变成一场噩梦waves@CodingNoob_Help如前所述,您将需要一种方法来填充可用的敌人值。。。你从哪里拿这些取决于你自己。例如,您可以将数组本身放置在WaveList类中,还可以为此类实现一个CustomEditor,将数组注入Wave中的所有项中。。。