(Unity)如何传递变量,没有一堆If Else语句的变量

Posted

技术标签:

【中文标题】(Unity)如何传递变量,没有一堆If Else语句的变量【英文标题】:(Unity)How to pass variables, that are variable without a bunch of If Else Statements 【发布时间】:2017-08-10 08:52:06 【问题描述】:

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)
                    

                    
                
            

我现在正在制作一个工具,用户可以选择一个用户可以在检查器窗口中编辑的变量类型。

要选择我使用 Enum 的变量,然后检查他们选择的变量类型,我使用了一堆 Else If。现在选择变量,使用 Else If 可以,但是当需要更改值时,我不能每次添加字母或更改数字时都执行 10 个 else if。

所以我的问题是,我怎样才能传递选择的变量类型,而无需找出他们选择的内容而没有一堆 else if?如果我可以使用 var 那就太好了,但它是从另一个脚本更改的。

抱歉这么长的草率帖子,我真的不知道该怎么称呼它以及如何问。

编辑:这是我的代码,有什么更好的方法?

Edit2:对 Robyn 的回应 - 我只是为示例编写了该代码,这基本上是我知道如何执行此操作的唯一方法。对不起,我会尽力解释。 在我发布的图像中,有一个标识符文本框,其中包含不透明度。 然后是所有变量类型的下拉列表。然后它有一个文本框。您点击按钮添加 Mod,然后弹出一排。您选择您的变量类型,放入材料标识符(例如不透明度)。所以要改变不透明度,它需要是一个浮点数。所以当你改变浮动框的值时,它会改变材质的不透明度。 我基本上需要一个值,可以用作浮点数、整数、布尔值等...... 我从来没有使用过 Switch 或 Case,所以我真的不知道它到底是做什么的。但是我会查一下试试!那谢谢啦。 我刚刚又上传了 2 张图片,试图在视觉上更好地解释它。

Tool

Code

【问题讨论】:

你的问题太宽泛了。您需要尝试something,如果您有一些特定问题,请发布一个问题,其中包含一个很好的minimal reproducible example,准确显示您尝试了什么,并准确解释该代码是什么确实,您希望它做什么,以及您无法自己解决的问题的哪一部分。根据您模糊的描述,我建议使用多态性,即类型层次结构,其中基本抽象类型(如接口)描述编辑器需要什么,然后具体实现处理用户输入和显示。 真的很抱歉,不知道我想做什么。我刚刚添加了代码,也许这会有所帮助。我只是需要一个更好的方法来做到这一点。 您可以尝试使用工厂模式。通过这种方式,您可以描述传递到工厂的对象中的逻辑。这是我在 if else 逻辑变得更难管理时使用的模式。 dofactory.com/net/factory-method-design-pattern 【参考方案1】:

只需要在选中元素发生变化时检查类型即可。

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();

【讨论】:

我有一个列表,其中包含与上述代码相同的脚本中的自定义类。当我单击添加模块时,它会添加所有这些下拉菜单和文本框。不过我会尝试,我想我将不得不放弃自定义类,但它可能会更好。编辑:等等,我可以得到一个包含不同类型变量的列表吗?或者我应该为浮点数、布尔值等创建一个列表...谢谢。 我在上面的脚本中有一个列表,其中包含一个自定义类。该类包含浮点数、float2.34...,然后它包含一个 bool、int 等...当我单击添加 mod 时,它会添加所有这些下拉菜单和文本框。用户选择哪种类型的变量,float,int bool,但现在是棘手的部分,当他更改变量(不是类型,值)时,我需要它来调用 Renderer.material.SetFloat 或 SetBool 等。 .取决于什么类型的变量,我只是不知道如何在for循环中不做一堆Ifs/else。抱歉,我在 5 分钟内不允许编辑。 好的,谢谢,是我不理解 FindTypeByIndex,在网上找不到任何关于它的信息。那会起作用的,所以再次感谢。有点希望有一种方法可以使用 var 之类的东西,但要公开。但我想这只会编译,你不能在运行时改变它。 FindTypeByIndex 我基本上是指您在问题中粘贴的功能。一堆 if-else 语句。您知道它们的顺序(因为您将数组传递给EditorGuiLayout.Popup),因此您可以通过弹出索引提取类型。无论如何,如果当前答案中的代码符合您的要求,请将问题标记为已回答:) 你不知道我怎样才能让它发挥作用吗?相反,我会为每个类设置一个单独的类,这样,你点击一个按钮,添加浮点数,添加颜色。它创建了与我上面相同的东西,但是它让 GUI 布局从脚本中绘制?公共 EditorGUILayout DrawMe() valueColor = EditorGUILayout.ColorField(valueColor);返回值颜色;有没有办法将代码键入字符串,然后让它播放该字符串?【参考方案2】:

您可以使用 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;

等等等等

        
    

(此外,您的代码看起来可能无法完全按照您的意愿行事......但我没有更改它的功能,因为我不知道您想要它做什么)

【讨论】:

我在主帖中留下了回复,没有足够的空间。不过感谢您的回复,我不确定 Switch/Case 是做什么的,但我会调查一下。 是的,在网上阅读有关 switch/case 的信息是个好主意。它的工作原理很像一堆 if/else 语句,它们都检查相同的值。如果它真的很长,它有时也会跑得快一点。 查了一下,很简单。使代码正常工作,但仍然可以减慢所有 Ifs/else 的原因。感谢您的帮助。

以上是关于(Unity)如何传递变量,没有一堆If Else语句的变量的主要内容,如果未能解决你的问题,请参考以下文章

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

在javascript中对一堆if()else if()使用switch语句是不是有任何性能提升? [复制]

当我使用 if else 然后将值传递给设置 onClick 时,如何获取微调器值?

在 Spring Boot 中,如何干掉 if else!

如何在没有错误的情况下制作if-else语句?

php if else条件在变量中作为字符串[重复]