【问题标题】:If execution order at the same time如果同时执行顺序
【发布时间】:2018-04-27 10:26:50
【问题描述】:

我有一个问题..我希望每次按下箭头键时都会创建我的火球。

-它可以工作,但是:如果(例如)我按下向下箭头,然后在按下向下箭头的同时按下另一个箭头,(例如)向左箭头,它不会创建火球在左边。 但是使用右箭头,一切正常(因为它是 if 语句的第一个)。

-我知道代码从上到下工作,我无法改变这一点。但也许我可以找到一种方法来避免这种情况,让这项工作按我的意愿工作。

(我希望fireSphere的创建就像在以撒的结合中一样:如果你按左,它会向左射击,如果向右,它会向右射击,但是如果你先按左箭头,然后再按左箭头被按下,你按右箭头,它会向右射击。如果你按第一个右,同样的事情)

(英语是我的第二语言,如果你不懂我,请告诉我!我会尽力解释自己更好) 谢谢!

    if (Input.GetButton("RightArrow") && Time.time > timeToFire)
    {
        timeToFire = Time.time + 1 / fireRate;
        Instantiate(fireSphere, firePoint.position, firePoint.rotation);
    }

    if (Input.GetButton("LeftArrow") && Time.time > timeToFire)
    {
        timeToFire = Time.time + 1 / fireRate;
        Instantiate(fireSphere, firePoint.position, firePoint.rotation);
    }

    if (Input.GetButton("UpArrow") && Time.time > timeToFire)
    {
        timeToFire = Time.time + 1 / fireRate;
        Instantiate(fireSphere, firePoint.position, firePoint.rotation);
    }

    if (Input.GetButton("DownArrow") && Time.time > timeToFire)
    {
        timeToFire = Time.time + 1 / fireRate;
        Instantiate(fireSphere, firePoint.position, firePoint.rotation);
    }

【问题讨论】:

  • 也许使用一个不中断的开关
  • 我认为这是一个时间问题 - 当你按下按钮时你会做 timeToFire = Time.time + 1 /fireRate;这意味着我认为(如果您按下另一个按钮 - Time.time 不大于 timeToFire 并且它不会创建您的实例
  • 我是否理解正确,无论您在代码中按顺序优先按下多少个键,您都只想一次向一个方向射击?并且还有冷却/射速,例如每秒 1 发左右?
  • 另外,关于代码中的位置和旋转,你真的改变它们了吗?因为从该代码中,您对所有方向都使用相同的代码。
  • Gunnar B,我想要这样:如果我按下像 DownArrow 这样的按钮,同时按下另一个按钮,比如向上箭头,我希望代码最后初始化 fireSphere按下按钮(在本例中为向上箭头)

标签: c# unity3d


【解决方案1】:

此代码将允许同时按下并按住所有方向键,其中最后一个指示方向。

示例: 您按住←→↓,它将使用↓。如果你松开→然后↓,它将使用←。

(也使用Input.GetKeyKeyCode

public float FireRate;

public float NextFire;

private List<KeyCode> keysPressed;

private KeyCode right = KeyCode.RightArrow;
private KeyCode left = KeyCode.LeftArrow;
private KeyCode up = KeyCode.UpArrow;
private KeyCode down = KeyCode.DownArrow;

private void Awake()
{
    keysPressed = new List<KeyCode>();
}

private void Update()
{
    if(Input.GetKeyDown(right))
        AddKey(right);
    if(Input.GetKeyDown(left))
        AddKey(left);
    if(Input.GetKeyDown(up))
        AddKey(up);
    if(Input.GetKeyDown(down))
        AddKey(down);

    if(Input.GetKeyUp(right))
        RemoveKey(right);
    if(Input.GetKeyUp(left))
        RemoveKey(left);
    if(Input.GetKeyUp(up))
        RemoveKey(up);
    if(Input.GetKeyUp(down))
        RemoveKey(down);

    if((Time.time > NextFire) == false)
        return;

    if(Input.GetKey(right) || Input.GetKey(left) || Input.GetKey(up) || Input.GetKey(down))
    {
        NextFire = Time.time + FireRate;
        Fire();
    }
}

private void AddKey(KeyCode k)
{
    keysPressed.Add(k);
}

private void RemoveKey(KeyCode k)
{
    keysPressed.Remove(k);
}

private void Fire()
{
    if(keysPressed[keysPressed.Count - 1] == right)
        Debug.Log("right");
    else if(keysPressed[keysPressed.Count - 1] == left)
        Debug.Log("left");
    else if(keysPressed[keysPressed.Count - 1] == up)
        Debug.Log("up");
    else if(keysPressed[keysPressed.Count - 1] == down)
        Debug.Log("down");
}

唯一在顺序上仍然存在小问题的地方是您实际上同时按下了 2 个或更多键。

由于列表操作,此解决方案可能不是性能最高的,但我现在能想到的其他选项也有其缺点,或者不允许这种灵活性。

【讨论】:

  • 谢谢,但我的代码有问题: private void AddKey(KeyCode k) { keysPressed.Add(k); } private void RemoveKey(KeyCode k) { keysPressed.Remove(k);给我一个错误:NullReferenceExeption 对象引用未设置为对象的实例,我无法弄清楚这意味着什么。
  • 表示keysPressed为空
  • 这个答案需要一个 Awake () 函数,里面有这个 keysPressed = new List();
  • @ChrisH 没错,但由于某种原因,它在我的一端工作而无需初始化列表。
【解决方案2】:

查看您的代码部分:

if (Input.GetButton("LeftArrow") && Time.time > timeToFire)
{
    timeToFire = Time.time + 1 / fireRate;
    Instantiate(fireSphere, firePoint.position, firePoint.rotation);
}

if (Input.GetButton("UpArrow") && Time.time > timeToFire)
{
    timeToFire = Time.time + 1 / fireRate;
    Instantiate(fireSphere, firePoint.position, firePoint.rotation);
}

如果您按下键LeftArrowUpArrow,则满足两个 if 语句的第一个条件。

我假设一开始Time.time 大于timeToFire,所以第一个语句触发。在第一个状态中,您将 timeToFire 设置为大于 Time.time (+ (1/fireRate)) 的值。

=> 这使得第二个 if 语句无法评估为真。 就是这样

int a = 5;
if(SomeTrueStatement() && a < 10)
{
    a = 20;
}
//This never happens because a is now > 10
if(SomeOtherTrueStatement() a < 10)
{
    //Code
}

可能的解决方案: 我不知道开箱即用是否可以区分首先按下了哪个键,但是如果您保存最后按下的键时只按下了一个键,那么您知道,如果现在按下了 2 个键,它们中的哪一个是后来按下的键。

[Pseudocode]
if(OnlyOneKeyPressed())
{
    savedPressedKey = SaveKeyPressed(GetPressedKey());
    pressedKey = GetPressedKey();
}
else if(TwoKeysPressed())
    pressedKey = GetAllPressedKeys().Exclude(savedPressedKey);

if(pressedKey == "ArrowUp" && ...)
...
...

【讨论】:

    【解决方案3】:

    事实证明我的想法与@Gunnar-b 的想法非常相似:

        protected List<KeyCode> Directions = new List<KeyCode>();
    
        protected void Update()
        {
            var hasDirection = TrackKey(KeyCode.UpArrow) || TrackKey(KeyCode.DownArrow) || TrackKey(KeyCode.LeftArrow) || TrackKey(KeyCode.RightArrow);
            if (!hasDirection)
            {
                Directions.Clear();
                return;
            }
    
            // Has a direction.  Check "Last" item in list (top of stack) and proceed.
            Quaternion rotation = Quaternion.identity;
            switch (Directions[Directions.Count -1])
            {
                case KeyCode.UpArrow: // Set Rotation Here
                    break;
                case KeyCode.DownArrow: // Set Rotation Here
                    break;
                case KeyCode.LeftArrow: // Set Rotation Here
                    break;
                case KeyCode.RightArrow: // Set Rotation Here
                    break;
    
            }
    
            // Instantiate fireball using rotation from above
    
            Instantiate(prefab, position, rotation);
        }
    
        protected bool TrackKey(KeyCode key)
        {
            // if key was released, remove each item where the item equals key
            if (Input.GetKeyUp(key)) Directions.RemoveAll(item => item == key);
    
            // Always adds to end, virtual 'Stack'
            if (Input.GetKeyDown(key)) Directions.Add(key);
    
            return Input.GetKey(key);
        }
    

    【讨论】:

      猜你喜欢
      • 2015-02-10
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-17
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      相关资源
      最近更新 更多