Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 数组C的Unity自定义下拉选择_C#_Unity3d_Dropdown_Unity Editor_Unity3d Editor - Fatal编程技术网

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中的所有项中。。。