最有效的评估类似结果的自变量的方法

本文关键字:结果 自变量 方法 有效 评估 | 更新日期: 2023-09-27 18:02:14

我正在做一个使用Unity和c#的项目,但我不觉得这与Unity有关。我有两只独立的手,它们由一个手类的2个实例来表示。

public class HandController
{//....class}
HandController LeftHand  = new HandController();
HandController RightHand = new HandController();

我经常在很多地方做两倍的工作来影响手,因为每只手都需要独立治疗。举个例子,我正在使用一个Leap运动控制器,如果其中一只手没有被检测到,我想要通知用户。我在更新方法中改变了手的颜色。

Color notDetected   = Color.red;
Color detected      = new Color(189/255.0f, 165/255.0f, 134/255.0f);
if (!LeftHandTracked)
    LeftHand.renderer.material.color = notDetected;
if (!RightHandTracked)
    RightHand.renderer.material.color = notDetected;
if (LeftHandTracked)
    LeftHand.renderer.material.color = detected;
if (RightHandTracked)
    RightHand.renderer.material.color = detected;

有更有效的方法吗?我讨厌代码中到处都是重复的if条件。我还跟踪手指,所以每个手指都需要被识别,我得到了一个更糟糕的if条件链

    if (TappedFingers[0] && !_keySpamBlock)
        LeftHand.SetSide(true, _pointer);
    if (TappedFingers[1] && !_keySpamBlock)
        LeftHand.SetSide(true, _middle);
    if (TappedFingers[2] && !_keySpamBlock)
        LeftHand.SetSide(true, _ring);
    if (TappedFingers[3] && !_keySpamBlock)
        LeftHand.SetSide(true, _pinky); 
    if (TappedFingers[4] && !_keySpamBlock)
        RightHand.SetSide(true, _pointer);
    if (TappedFingers[5] && !_keySpamBlock)
        RightHand.SetSide(true, _middle);
    if (TappedFingers[6] && !_keySpamBlock)
        RightHand.SetSide(true, _ring);
    if (TappedFingers[7] && !_keySpamBlock)
        RightHand.SetSide(true, _pinky);

_pinky和_ middle等。是我在HandController类中传递给SetSide方法的散列值,它允许我访问我在Unity中设置的animationcontroller布尔值。SetSide()基本上只是在用户轻击手指时发送true并在相应的手指上播放动画。

编辑:为了更清楚一点发生了什么

我正在通过继承一个类并建立一个事件侦听器来连接到一个API:

public class AppListener : ErghisListener {

    public delegate void onUpdate(Data d);
    public event onUpdate Updated;
    public override void OnErghisFrame(Data data)
    {
        Loom.QueueOnMainThread(() => { this.Updated(data); });
    }
}

然后我有一个MainController从API接收数据对象:

public class MainController: MonoBehaviour{
private AppListener _appListener;    
private int _pointer;
private int _middle;
private int _ring;
private int _pinky;
void Start()
{
    this._appListener = new AppListener();
    this._appListener.Updated += callback;
    this._pointer  = Animator.StringToHash("Pointer");
    this._middle   = Animator.StringToHash("Middle");
    this._ring     = Animator.StringToHash("Ring");
    this._pinky    = Animator.StringToHash("Pinky");
}
public void callback(Data d)
{
    // Here is where all my annoying if conditionals were. 
    bool[] TappedFingers = d.tappedF;
}

最有效的评估类似结果的自变量的方法

你的第一个代码片段看起来会更合乎逻辑,如果它是这样的:

class HandController : MonoBehaviour
{
    bool m_Tracked;
    Color NotDetected { get { return Color.red; } }
    Color Detected { get { return new Color(189/255.0f, 165/255.0f, 134/255.0f); } }
    public bool Tracked
    {
        if (m_Tracked == value) return;
        m_Tracked = value;
        renderer.material.color = value ? Detected : NotDetected;
    }
}
// ...
LeftHand.Tracked = LeftHandTracked;
if (TappedFingers.Length != FINGERS*2)
{
    Debug.LogError("Unexpected amount of fingers: " + TappedFingers.Length);
    return;
}
for(int i = 0; i < FINGERS; i++)
{    
    LeftHand.SetSide(TappedFingers[i], i);
}
for(int i = FINGERS; i < FINGERS*2; i++)
{    
    RightHand.SetSide(TappedFingers[i], i-FINGERS);
}

您可以在这里简单地使用else

if (LeftHandTracked)
    LeftHand.renderer.material.color = detected;
else
    LeftHand.renderer.material.color = notDetected;

我更喜欢内联条件。

LeftHand.renderer.material.color = LeftHandTracked ? detected : notDetected;
对于第二个示例,您可以将所有语句包装在单个if块中以消除视觉噪声:
if (!_keySpamBlock)
{
    if (TappedFingers[0])
        LeftHand.SetSide(true, _pointer);
    if (TappedFingers[1])
        LeftHand.SetSide(true, _middle);
}

Linq的另一个选项(不是更有效,但更漂亮):

var sides = new[] { _pointer, _middle };
if (!_keySpamBlock)
    TappedFingers.Zip(sides, (x, y) => { if (x) { LeftHand.SetSide(true, y); });

我想说这很清楚,看起来足够好。我不知道多态性在这里有什么帮助,但是您可以自己研究一下。

第一部分:

LeftHand.renderer.material.color = LeftHandTracked ? detected : notDetected; 
RightHand.renderer.material.color = RightHandTracked ? detected : notDetected;

第二部分:

if(!_keySpamBlock)
{
    int index=Array.FindLastIndex(TappedFingers.Take(8).ToArray(), i => i);
    switch (index)
    {
       case 0:  {LeftHand.SetSide(true, _pointer); break;}
       case 1:  {LeftHand.SetSide(true, _middle); break;}
       //.........
       case 7: {RightHand.SetSide(true, _pinky); break;}
    }
}