(Unity)如何传递没有一堆 If Else 语句的变量
(Unity)How to pass variables, that are variable without a bunch of If Else Statements
for (int m = 0; m < materialObjects.Length; m++)
{
for (int i = 0; i < materialModifiers.Count; i++)
{
if(materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float)
{
if (materialModifiers[i].valueFloat[0] != materialModifiers[i].oldValueFloat[0])
{
materialObjects[m].material.SetFloat(materialModifiers[i].identifier, materialModifiers[i].valueFloat[0]);
materialModifiers[i].valueFloat = materialModifiers[i].oldValueFloat;
}
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float2 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float3 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float4)
{
if (materialModifiers[i].valueFloat != materialModifiers[i].oldValueFloat)
{
materialObjects[m].material.SetFloatArray(materialModifiers[i].identifier, materialModifiers[i].valueFloat);
materialModifiers[i].valueFloat = materialModifiers[i].oldValueFloat;
}
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int)
{
if (materialModifiers[i].valueInt != materialModifiers[i].oldValueInt)
{
materialObjects[m].material.SetInt(materialModifiers[i].identifier, materialModifiers[i].valueInt[0]);
materialModifiers[i].valueFloat = materialModifiers[i].oldValueFloat;
}
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int2 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int3 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int4)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Bool)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.ColorField)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Vector2)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Vector3)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Vector4)
{
}
}
}
我现在正在制作一个工具,用户可以选择一个变量类型,用户可以在检查器中编辑该变量类型 window。
为了选择变量,我使用了一个枚举,但是为了检查他们选择了哪种类型的变量,我使用了一堆 Else Ifs。现在选择变量,可以使用 Else If 来完成,但是当需要更改值时,我不能在每次添加字母或更改数字时都执行 10 个 else ifs。
所以我的问题是,我如何才能传递所选的变量类型,而无需找出他们选择的内容,而无需其他条件?如果我可以使用 var 就好了,但是它正在从另一个脚本更改。
抱歉这么长的草率post,我真的不知道这个叫什么,怎么问。
编辑:这是我的代码,执行此操作的更好方法是什么?
Edit2:对 Robyn 的回应 - 我只是为示例编写了该代码,这基本上是我知道如何执行此操作的唯一方法。抱歉,我会尽力解释。
在我 posted 的图像中,有一个标识符文本框,其中不透明。
然后下拉所有变量类型。然后它有一个文本框。您点击按钮添加 Mod,然后弹出一行。您可以选择变量类型,输入材料标识符(例如不透明度)。所以要改变不透明度,它需要是一个浮点数。所以当你改变浮动框的值时,它会改变材质的不透明度。
我基本上需要一个值,可以用作 float、int、bool 等...
我从来没有使用过 Switch 或 Case,所以我真的不知道它到底做了什么。但我会查一下试试!那谢谢啦。
我刚刚上传了 2 张图片,试图从视觉上更好地解释它。
Tool
Code
你只需要在选择的元素发生变化时检查类型。
enum SupportedTypes
{
Color,
Int
}
SupportedTypes selectedType;
void OnEnable()
{
// If the user still didn't select anything, select Int
selectedType = SupportedTypes.Int;
// See below to know what this is
methodUsedToDrawTheLastPart = DrawIntChooser;
}
// One field for each type
// Not elegant but we don't know the type beforehand
Color colorValue;
int intValue;
// ...
// Delegate defining a method signature: in this case "void XXX(string)"
delegate void SetValue(string propertyId);
// Instance of the delegate: think of it as a pointer to a method
// with the signature defined earlier
// You can set this field to any method being "void XXX(string)"
SetValue methodUsedToDrawTheLastPart;
// Then One method to draw each property chooser
// They will just draw the last part of the modifier
void DrawColorChooser(string propertyId)
{
Color newColorValue = EditorGUILayout.ColorField(colorValue);
if (newColorValue != colorValue)
{
colorValue = newColorValue;
// Replace this with a call to the renderer
Debug.Log("Set color to " + colorValue);
}
}
void DrawIntChooser(string propertyId)
{
int newIntValue = EditorGUILayout.IntField(intValue);
if (newIntValue != intValue)
{
intValue = newIntValue;
Debug.Log("Set int to " + intValue);
}
}
// All the other types choosers ...
// Finally, the method to put pieces together
void DrawModifier()
{
EditorGUILayout.BeginHorizontal();
string propertyId = "propId";
EditorGUILayout.TextField(propertyId);
SupportedTypes newModifierType = (SupportedTypes)EditorGUILayout.EnumPopup(selectedType);
// We only do if-else statements if the type changed
// So when the user changes only the value, this will be skipped
if (newModifierType != selectedType)
{
// Here, based on the chosen type, we set the delegate
if (newModifierType == SupportedTypes.Int)
{
methodUsedToDrawTheLastPart = DrawIntChooser;
}
else if (newModifierType == SupportedTypes.Color)
{
methodUsedToDrawTheLastPart = DrawColorChooser;
}
selectedType = newModifierType;
}
// And then we call it
methodUsedToDrawTheLastPart(propertyId);
EditorGUILayout.EndHorizontal();
}
public override void OnInspectorGUI()
{
DrawModifier();
}
您可以使用 Switch 和 Foreach 语句而不是 If 和 For 语句来使代码更易于阅读,例如:
foreach (var materialObject in materialObjects)
{
foreach (var materialModifier in materialModifiers)
{
switch (materialModifier.valueType)
{
case LittleSubstanceModifier.ValueType.Float:
if (materialModifier.valueFloat[0] != materialModifier.oldValueFloat[0])
{
materialObject.material.SetFloat(materialModifier.identifier, materialModifier.valueFloat[0]);
materialModifier.valueFloat = materialModifier.oldValueFloat;
}
break;
case LittleSubstanceModifier.ValueType.Float2:
case LittleSubstanceModifier.ValueType.Float3:
case LittleSubstanceModifier.ValueType.Float4:
if (materialModifier.valueFloat != materialModifier.oldValueFloat)
{
materialObject.material.SetFloatArray(materialModifier.identifier, materialModifier.valueFloat);
materialModifier.valueFloat = materialModifier.oldValueFloat;
}
break;
等等等等
}
}
}
(另外,您的代码看起来可能无法完全满足您的要求...但我没有更改它的功能,因为我不知道您希望它做什么)
for (int m = 0; m < materialObjects.Length; m++)
{
for (int i = 0; i < materialModifiers.Count; i++)
{
if(materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float)
{
if (materialModifiers[i].valueFloat[0] != materialModifiers[i].oldValueFloat[0])
{
materialObjects[m].material.SetFloat(materialModifiers[i].identifier, materialModifiers[i].valueFloat[0]);
materialModifiers[i].valueFloat = materialModifiers[i].oldValueFloat;
}
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float2 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float3 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Float4)
{
if (materialModifiers[i].valueFloat != materialModifiers[i].oldValueFloat)
{
materialObjects[m].material.SetFloatArray(materialModifiers[i].identifier, materialModifiers[i].valueFloat);
materialModifiers[i].valueFloat = materialModifiers[i].oldValueFloat;
}
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int)
{
if (materialModifiers[i].valueInt != materialModifiers[i].oldValueInt)
{
materialObjects[m].material.SetInt(materialModifiers[i].identifier, materialModifiers[i].valueInt[0]);
materialModifiers[i].valueFloat = materialModifiers[i].oldValueFloat;
}
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int2 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int3 || materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Int4)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Bool)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.ColorField)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Vector2)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Vector3)
{
}
else if (materialModifiers[i].valueType == LittleSubstanceModifier.ValueType.Vector4)
{
}
}
}
我现在正在制作一个工具,用户可以选择一个变量类型,用户可以在检查器中编辑该变量类型 window。
为了选择变量,我使用了一个枚举,但是为了检查他们选择了哪种类型的变量,我使用了一堆 Else Ifs。现在选择变量,可以使用 Else If 来完成,但是当需要更改值时,我不能在每次添加字母或更改数字时都执行 10 个 else ifs。
所以我的问题是,我如何才能传递所选的变量类型,而无需找出他们选择的内容,而无需其他条件?如果我可以使用 var 就好了,但是它正在从另一个脚本更改。
抱歉这么长的草率post,我真的不知道这个叫什么,怎么问。
编辑:这是我的代码,执行此操作的更好方法是什么?
Edit2:对 Robyn 的回应 - 我只是为示例编写了该代码,这基本上是我知道如何执行此操作的唯一方法。抱歉,我会尽力解释。 在我 posted 的图像中,有一个标识符文本框,其中不透明。 然后下拉所有变量类型。然后它有一个文本框。您点击按钮添加 Mod,然后弹出一行。您可以选择变量类型,输入材料标识符(例如不透明度)。所以要改变不透明度,它需要是一个浮点数。所以当你改变浮动框的值时,它会改变材质的不透明度。 我基本上需要一个值,可以用作 float、int、bool 等... 我从来没有使用过 Switch 或 Case,所以我真的不知道它到底做了什么。但我会查一下试试!那谢谢啦。 我刚刚上传了 2 张图片,试图从视觉上更好地解释它。
Tool
Code
你只需要在选择的元素发生变化时检查类型。
enum SupportedTypes
{
Color,
Int
}
SupportedTypes selectedType;
void OnEnable()
{
// If the user still didn't select anything, select Int
selectedType = SupportedTypes.Int;
// See below to know what this is
methodUsedToDrawTheLastPart = DrawIntChooser;
}
// One field for each type
// Not elegant but we don't know the type beforehand
Color colorValue;
int intValue;
// ...
// Delegate defining a method signature: in this case "void XXX(string)"
delegate void SetValue(string propertyId);
// Instance of the delegate: think of it as a pointer to a method
// with the signature defined earlier
// You can set this field to any method being "void XXX(string)"
SetValue methodUsedToDrawTheLastPart;
// Then One method to draw each property chooser
// They will just draw the last part of the modifier
void DrawColorChooser(string propertyId)
{
Color newColorValue = EditorGUILayout.ColorField(colorValue);
if (newColorValue != colorValue)
{
colorValue = newColorValue;
// Replace this with a call to the renderer
Debug.Log("Set color to " + colorValue);
}
}
void DrawIntChooser(string propertyId)
{
int newIntValue = EditorGUILayout.IntField(intValue);
if (newIntValue != intValue)
{
intValue = newIntValue;
Debug.Log("Set int to " + intValue);
}
}
// All the other types choosers ...
// Finally, the method to put pieces together
void DrawModifier()
{
EditorGUILayout.BeginHorizontal();
string propertyId = "propId";
EditorGUILayout.TextField(propertyId);
SupportedTypes newModifierType = (SupportedTypes)EditorGUILayout.EnumPopup(selectedType);
// We only do if-else statements if the type changed
// So when the user changes only the value, this will be skipped
if (newModifierType != selectedType)
{
// Here, based on the chosen type, we set the delegate
if (newModifierType == SupportedTypes.Int)
{
methodUsedToDrawTheLastPart = DrawIntChooser;
}
else if (newModifierType == SupportedTypes.Color)
{
methodUsedToDrawTheLastPart = DrawColorChooser;
}
selectedType = newModifierType;
}
// And then we call it
methodUsedToDrawTheLastPart(propertyId);
EditorGUILayout.EndHorizontal();
}
public override void OnInspectorGUI()
{
DrawModifier();
}
您可以使用 Switch 和 Foreach 语句而不是 If 和 For 语句来使代码更易于阅读,例如:
foreach (var materialObject in materialObjects)
{
foreach (var materialModifier in materialModifiers)
{
switch (materialModifier.valueType)
{
case LittleSubstanceModifier.ValueType.Float:
if (materialModifier.valueFloat[0] != materialModifier.oldValueFloat[0])
{
materialObject.material.SetFloat(materialModifier.identifier, materialModifier.valueFloat[0]);
materialModifier.valueFloat = materialModifier.oldValueFloat;
}
break;
case LittleSubstanceModifier.ValueType.Float2:
case LittleSubstanceModifier.ValueType.Float3:
case LittleSubstanceModifier.ValueType.Float4:
if (materialModifier.valueFloat != materialModifier.oldValueFloat)
{
materialObject.material.SetFloatArray(materialModifier.identifier, materialModifier.valueFloat);
materialModifier.valueFloat = materialModifier.oldValueFloat;
}
break;
等等等等
}
}
}
(另外,您的代码看起来可能无法完全满足您的要求...但我没有更改它的功能,因为我不知道您希望它做什么)