В 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);
}
}
Не элегантно, но вот решение:
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());
}
}
Мне нравится рефакторинг переключателя в его собственный метод, в этом есть смысл.
@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;
}
}
Ооо, это умно! Почему я не подумал об этом... Наверное, потому что это немного сбивает с толку. Но однозначно идея!
Вероятно, потому что методы расширений и перечисления кажутся очень странной парой :/ :D
Как уже упоминалось, используйте карту, например, например.
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();
Ваш код немного грубый (метод имеет неправильный тип возвращаемого значения, Словарь на правой стороне знака равенства нуждается в типах), но это хорошая идея, спасибо!
@ Бен, да, напечатал это только по телефону, извините ^^ Спасибо, что указали на это, сейчас исправил ;)
Инициализировать
ReadOnlyDictionary<JumpDistance, double>
где-то в вашем коде и использовать его везде, где это необходимо?