【问题标题】:Get input from two keys in unity统一从两个键获取输入
【发布时间】:2018-03-21 17:05:58
【问题描述】:

在我的代码中,我试图检测一个键(例如“A”)是单独按下还是组合按下。我对每个都有不同的 if 语句。但是当我把它们压在一起时,会发生一些奇怪的事情。我认为问题与Input.Getkey 有关,当我尝试使用Input.GeyKeyDown 时,几乎不可能同时按下它们。如何改进我的代码?

这似乎是一个常见问题,但我无法理解。我希望我的变换在仅按下 A 时移动到不同的位置,并在按下 A 和 W 或 S 时移动到另一个不同的位置。我想要的结果在图像中。当我单击 a&&w 然后在这样的范围之间生成一个随机 Vector3:

new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(4.5f, 6f));

生成随机位置效果很好,但唯一的问题是当我尝试按下组合键时,首先运行

if (Input.GetKeyUp(KeyCode.W))
    {
        activePos = new Vector3(Random.Range(0.95f, -0.95f), 0, Random.Range(4.5f, 6f));

        return activePos;
    }

然后这个

if (Input.GetKey(KeyCode.A) || (Input.GetKey(KeyCode.Q) && Input.GetKey(KeyCode.A)))
    {
        activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(2f, 4.5f));

        return activePos;
    }

还有这个

if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))
    {
        activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(4.5f, 6f));

        return activePos;
    }

而我只想运行最后一个。 我只想在 w&&a 被按下时运行这段代码

if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))
        {
            activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(4.5f, 6f));

            return activePos;
        }

这是完整的方法:

public static Vector3 GetTargetPosition()
{
    /*
     * near z = 1 - 2.5, key  = s
     * center z = 2 - 4.5, key  = q
     * far z = 4.5 - 6, key  = w
     * very far possibly outside z = 6 - 7.5
     * left x = (-2.7) to -0.95, key  = a
     * center x = -0.95 to 0.95, key  = q
     * right x = 0.95 to 2.7, key  = d
     */

    if (Input.GetKeyUp(KeyCode.S))
    {
        activePos = new Vector3(Random.Range(0.95f, -0.95f), 0, Random.Range(1f, 2.5f));

        return activePos;
    }
    else if (Input.GetKeyUp(KeyCode.W))
    {
        activePos = new Vector3(Random.Range(0.95f, -0.95f), 0, Random.Range(4.5f, 6f));

        return activePos;
    }
    else if (Input.GetKeyUp(KeyCode.Q))
    {
        activePos = new Vector3(Random.Range(0.95f, -0.95f), 0, Random.Range(2f, 4.5f));

        return activePos;
    }
    else if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.A))
    {
        activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(1f, 2.5f));

        return activePos;
    }
    else if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.D))
    {
        activePos = new Vector3(Random.Range(0.95f, 2.7f), 0, Random.Range(1f, 2.5f));

        return activePos;
    }
    else if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))
    {
        activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(4.5f, 6f));

        return activePos;
    }
    else if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D))
    {
        activePos = new Vector3(Random.Range(0.95f, 2.7f), 0, Random.Range(4.5f, 6f));

        return activePos;
    }
    else if (Input.GetKey(KeyCode.A) || (Input.GetKey(KeyCode.Q) && Input.GetKey(KeyCode.A)))
    {
        activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(2f, 4.5f));

        return activePos;
    }
    else if (Input.GetKey(KeyCode.D) || (Input.GetKey(KeyCode.Q) && Input.GetKey(KeyCode.D)))
    {
        activePos = new Vector3(Random.Range(0.95f, 2.7f), 0, Random.Range(2f, 4.5f));
        return activePos;
    }
    else
    {
        return new Vector3(0, 0, 0);
    }
}

【问题讨论】:

  • 注意:if/else 语句选择第一个匹配选项,而不是最佳匹配选项。它总是在有机会匹配 S&&A 或 S&&D 之前匹配 S。
  • 关闭对话框中的模糊:寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误以及在问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建minimal reproducible example

标签: c# unity3d input


【解决方案1】:

问题不在于

if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))

因为这非常适合您尝试做的事情。

问题在于您使用了很多 if-else 语句。

您的代码是按顺序运行的,即从上到下。如果您同时按下 A 和 W 键,它将通过您的代码,并且找到的第一个匹配项将是

else if (Input.GetKeyUp(KeyCode.W)) { activePos = new Vector3(Random.Range(0.95f, -0.95f), 0, Random.Range(4.5f, 6f));

  return activePos;
}

因为您确实按下了 W,它将执行此 if 语句中的代码并中断所有其他情况。永远达不到

 else if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))
{
    activePos = new Vector3(Random.Range(-2.7f, -0.95f), 0, Random.Range(4.5f, 6f));

    return activePos;
}

有多种方法可以解决这个问题,每种方法都有自己的优缺点。

我个人可能会做的是嵌套你的 if 语句。这意味着您将首先检查是否按下了键 A,然后在该 if 语句中您可以再次检查是否也按下了 W,例如:

if(Input.GetKey(KeyCode.A))
{
    //some logic goes here for when A is pressed
    if(Input.GetKey(KeyCode.W))
    {
       //some logic for when both A and W are pressed
    }
}

这样做的好处是您可以在同一个 if 语句中同时执行 A 和 W 检查。

或者你可以这样做:

 if(Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A))
 {
     //logic for both A And W pressed
 }

 if(Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.A))
 {
     //by checking if A is NOT pressed you will prevent this code from 
     //running if you press both A and W
     //Logic for just W pressed
 }

简而言之;摆脱整个 if-else 结构并坚持使用 if,如果出于某种原因您真的想坚持使用 if-else 结构,颠倒您检查所有内容的顺序也可以(例如检查双键按下首先,然后单键按下,因为你在第一次正面命中后打破了 if-else)但我不推荐这种方法。

您也不必返回活动位置。只需将其设置为 = new Vector3 即可!

抱歉,如果帖子的格式有点乱,请在手机上快速输入!

【讨论】:

  • 感谢您的宝贵回答。你帮了我很多。
【解决方案2】:

我假设该函数将在 Update() 函数中调用,该函数在每一帧上执行。

对于同时按下两个键的情况,不必使用逻辑和A && B,只需分别定义A和B的情况,当两者都被调用时,更改会按顺序应用 ,但是非常快,快到没人能检测到这样的序列,满足你的要求。

if (Input.GetKeyUp(KeyCode.A)) {...}
if (Input.GetKeyUp(KeyCode.B)) {...}
// if (Input.GetKeyUp(KeyCode.A) && Input.GetKeyUp(KeyCode.A)) {...} //Avoid this!

更新:

if (Input.GetKeyUp(KeyCode.A)) {
     activePos += ... //Let activePos to be class level variable, no need to return;
}

【讨论】:

    【解决方案3】:

    您可以尝试在每次按键时设置一个值,因此当您按下 a 键时,它会设置 bool a = true。稍后您可以通过if (a && d) 或类似的方式进行检查。

    【讨论】:

      【解决方案4】:

      试试这个:

      if ((Input.GetKey(KeyCode.S) && Input.GetKeyUp(KeyCode.Q)) || (Input.GetKey(KeyCode.Q) && Input.GetKeyUp(KeyCode.S)))
      {
          DoCode();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 2021-09-18
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        相关资源
        最近更新 更多