Выпадающий список перечисления Unity со значениями с плавающей запятой

В Unity/C# есть ли лучший способ сделать следующее, в настоящее время включающее enum и оператор switch?

Я хочу иметь возможность выбрать «Расстояние перехода» из раскрывающегося списка в инспекторе Unity, но я хочу, чтобы каждое из значений было числом с плавающей запятой, а не целым числом. Есть ли лучшая структура данных или другой подход для достижения этой цели?

    public enum JumpDistance
    {
        Short,
        Medium,
        Long
    }

    public class JumpTrigger : MonoBehaviour
    {
        [SerializeField] private JumpDistance jumpDistance = JumpDistance.Short;
        private float jumpDistanceF;

        private void Awake()
        {
            switch (jumpDistance)
            {
                case JumpDistance.Short:
                    jumpDistanceF = 1;
                    break;
                case JumpDistance.Medium:
                    jumpDistanceF = 1.5f;
                    break;
                case JumpDistance.Long:
                    jumpDistanceF = 2;
                    break;
                default:
                    break;
            }

            Debug.Log("I need to jump:" + jumpDistanceF);
        }
    }

Инициализировать ReadOnlyDictionary<JumpDistance, double> где-то в вашем коде и использовать его везде, где это необходимо?

dbc 25.12.2020 23:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
1 870
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Не элегантно, но вот решение:

public enum JumpDistance
{
    Short = 100,
    Medium = 150,
    Long = 200
}

public class JumpTrigger : MonoBehaviour
{
    [SerializeField] private JumpDistance jumpDistance;
    private float jumpDistanceF;

    private void Awake()
    {
         jumpDistanceF = ((float)(int)jumpDistance) / 100f;

         Debug.Log("I need to jump:" + jumpDistanceF);
    }
}

... что делает это очевидным. Но из-за неявного продвижения int-to-float его можно упростить до

jumpDistanceF = (int)jumpDistance / 100f;

Мне нравится думать, что ваш способ хорош, но вы должны абстрагировать этот «переключатель», чтобы его можно было использовать везде.

Поэтому, даже если вы используете способ @MrUnbelievable92, который работает на 100%, но кажется склонным к тому, что кто-то сделает какую-то ошибку, если он не знает, как работают значения перечисления, или каким-либо другим способом, вы должны абстрагировать метод, чтобы справиться с этим , что-то вроде:

public enum JumpDistance
{
    Short,
    Medium,
    Long
}
public float GetJumpDistanceFloatValue(JumpDistance jumpDistance)
{
    switch (jumpDistance)
    {
        case JumpDistance.Short:
            return 1;            
        case JumpDistance.Medium:
            return 1.5f;
        case JumpDistance.Long:
            return 2;            
        default:
            Debug.Log("Error: this JumpDistance enum value is invalid");
            return 0;
    }
}

Но если вам нравится способ @MrUnbelievable92, вы всегда можете сделать следующее, чтобы немного абстрагироваться:

public enum JumpDistance
{
    Short = 100,
    Medium = 150,
    Long = 200
}
public float GetJumpDistanceFloatValue(JumpDistance jumpDistance)
{
    return (int)jumpDistance / 100f;
}

В своем финальном классе вы будете использовать его следующим образом:

public class JumpTrigger : MonoBehaviour
{

    public enum JumpDistance
    {
        Short = 100,
        Medium = 150,
        Long = 200
    }
    public float GetJumpDistanceFloatValue(JumpDistance jumpDistance)
    {
        return (int)jumpDistance / 100f;
    }

    [SerializeField] private JumpDistance jumpDistance = JumpDistance.Short;

    private void Awake()
    {           
        Debug.Log("I need to jump:" + GetJumpDistanceFloatValue(jumpDistance));
    }
}

Имея это ясно, вы всегда можете играть со статическими классами и методами расширений, достигая таких вещей, как:

public static class ExtensionMethods
{
    public enum JumpDistance
    {
        Short = 100,
        Medium = 150,
        Long = 200
    }
    public float GetJumpDistanceFloatValue(this JumpDistance jumpDistance)
    {
        return (int)jumpDistance / 100f;
    }    
}

public class JumpTrigger : MonoBehaviour
{
    [SerializeField] private JumpDistance jumpDistance = JumpDistance.Short;

    private void Awake()
    {        
        Debug.Log("I need to jump:" + jumpDistance.GetJumpDistanceFloatValue());
    }
}

Мне нравится рефакторинг переключателя в его собственный метод, в этом есть смысл.

Ben 26.12.2020 00:20

@Lotan: Да, ты можешь сойти с ума. Самая нечитаемая версия, вероятно, будет такой:

public class JumpTrigger : MonoBehaviour
{
    [SerializeField] private JumpDistance jumpDistance;
    private float jumpDistanceF;


    private void Awake()
    {
        jumpDistanceF = jumpDistance.ToFloat();

        Debug.Log("I need to jump:" + jumpDistanceF);
    }
}

public enum JumpDistance
{
    // NOTE TO DEVELOPER : This will be divided by 100
    Short = 100,
    Medium = 150,
    Long = 200
}
    
static class JumpDistanceExtensions
{
    public const float JUMP_DISTANCE_FACTOR = 100f;
    
    public static float ToFloat(this JumpDistance jumpDistance)
    {
        return (int)jumpDistance / JUMP_DISTANCE_FACTOR;
    }
}

Ооо, это умно! Почему я не подумал об этом... Наверное, потому что это немного сбивает с толку. Но однозначно идея!

Ben 26.12.2020 00:16

Вероятно, потому что методы расширений и перечисления кажутся очень странной парой :/ :D

MrUnbelievable92 26.12.2020 00:28
Ответ принят как подходящий

Как уже упоминалось, используйте карту, например, например.

public static class JumpDistanceConverter
{
    public static readonly ReadOnlyDictionary<JumpDistance, float> JumpDistanceToFloat = new ReadOnlyDictionary<JumpDistance, float>(new Dictionary<JumpDistance, float>
    {
        {JumpDistance.Short, 1.0f},
        {JumpDistance.Medium, 1.5f},
        {JumpDistance.Long, 2.0f}
    });

    // And then an extension method makes actually sense without changing the values of the enum itself ;)
    public static float ToFloat(this enum jumpDistance)
    {
        return JumpDistanceToFloat[jumpDistance];
    }
}

и получить к нему доступ, как

var jumpDistanceF = JumpDistanceConverter.JumpDistanceToFloat[jumpDistance];

или

var jumpDistanceF = jumpDistance.ToFloat();

Ваш код немного грубый (метод имеет неправильный тип возвращаемого значения, Словарь на правой стороне знака равенства нуждается в типах), но это хорошая идея, спасибо!

Ben 26.12.2020 12:42

@ Бен, да, напечатал это только по телефону, извините ^^ Спасибо, что указали на это, сейчас исправил ;)

derHugo 26.12.2020 13:01

Другие вопросы по теме