Unity - GetKeyDown和GetKey使用相同的KeyCode来抑制输入延迟

时间:2018-05-28 16:47:50

标签: unity3d

我试图让用户输入使用相同的输入键执行两种不同的行为。

像这样:

 if (Input.GetKeyDown(KeyCode.D) || Input.GetKey(KeyCode.D)) 

制作俄罗斯方块游戏:目标是,轻敲“D”一次,我希望tetromino每次移动一个世界单位。并且当按住相同的键“D”时,我希望块连续向右移动直到它到达游戏板的边缘,而不必点击。

这种方法适用于上面的代码但是,我遇到的问题是点击一次移动2或3个世界单位而不是一次,因为在团结意识到我按住键之前没有延迟。

我希望Unity在激活“Input.GetKey(KeyCode.D)”之前等待.5秒,以便我可以保持行为“Input.GetKeyDown(KeyCode.D)”

底线,

  • 我希望能够点按“D”以每次点按一个世界单位
  • 如果我按住“D”但是,只有在按住它0.5秒后,我希望块一直向右移动直到它到达游戏板的边缘

我该怎么做?

Tetromino.cs的完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tetromino : MonoBehaviour {
    //#####################################################################################################
    //#####################################################################################################
    float fallTimer = 0f;                 // timer counting the seconds to check if mino needs to fall
    public float fallSpeed = 1f;          // variable to determine how fast the mino needs to fall
    public bool allowRotation = true;
    public bool limitRotation = false;
    //#####################################################################################################
    //#####################################################################################################

    // Use this for initialization
    void Start () {

    }
    //#####################################################################################################
    //#####################################################################################################
    // Update is called once per frame
    void Update ()
    {
        CheckUserInput();  // --------------------------- // Checks the user input every frames
        FallBehavior();   // checks if the block needs to fall and increments the timer 
    }
    //#####################################################################################################
    //#####################################################################################################
    void CheckUserInput()  
    {
        if (Input.GetKeyDown(KeyCode.D))                  // moves the mino to the right
        {
            transform.position += new Vector3(1,0,0);
            if (CheckIsValidPosition()) // if minos is not in a valid position, the transform pushes the minos
            {                           // back to the left, to keep it inside the grid

            }
            else
            {
                transform.position += new Vector3(-1, 0, 0); // this counters the first attempt to move
            }
        }
        else if (Input.GetKeyDown(KeyCode.A))             // moves the mino to the left
        {
            transform.position += new Vector3(-1, 0, 0);
            if (CheckIsValidPosition())
            {

            }
            else
            {
                transform.position += new Vector3(1, 0, 0);
            }
        }
        else if (Input.GetKeyDown(KeyCode.W))             // rotates the mino
        {
            if (allowRotation)
            {
                if (limitRotation)                                //limited rotation ON, to prevent rotating outside the grid
                {                                                 // after the tetromino landed at the bottom
                    if (transform.rotation.eulerAngles.z >= 90)
                    {
                        transform.Rotate(0, 0, -90);
                    }
                    else
                    {
                        transform.Rotate(0, 0, 90);
                    }
                }
                else
                {
                    transform.Rotate(0, 0, 90);                   // 90 degrees rotation on the mino
                }
                if (CheckIsValidPosition())
                {

                }
                else
                {
                    if (limitRotation)
                    {
                        if (transform.rotation.eulerAngles.z >= 90)
                        {
                            transform.Rotate(0, 0, -90);
                        }
                        else
                        {
                            transform.Rotate(0, 0, 90);
                        }
                    }
                    else
                    {
                        transform.Rotate(0, 0, -90);
                    }


                }

            }


        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            transform.position += new Vector3(0, -1, 0);  // makes the mino go down when pressing 
            if (CheckIsValidPosition())
            {

            }
            else
            {
                transform.position += new Vector3(0, 1, 0);
            }
        }
    }
    //#####################################################################################################
    //#####################################################################################################
    /// <summary>
    /// Makes the block fall by 1 unit and checks how fast it needs to fall
    /// </summary>
    void FallBehavior()
    {
        if (Time.time - fallTimer >= fallSpeed)  // on the first frame, Time.time = 0 & fallTimer = 0
                                                 // so 0 - 0 = 0, is it >= then fallSpeed = 1? no
                                                 // so the if statement does not exectute, block dont fall
                                                 // after 1 sec, Time.time = 1 & fallTimer = 0
                                                 // so 1 - 0 = 1, is it >= then fallSpeed = 1? yes
                                                 // so block falls after 1 sec, because we increment it
                                                 // in the if statment also
        {
            transform.position += new Vector3(0, -1, 0); // moves the mino down 

            fallTimer = Time.time;   // Time.time check the time since game started and is assigned
        }                            // to fallTimer so that the timer updates every frame 
                                     // when called in the Update method. fallTimer = 0, 1, 2, 3 ... 

        if (CheckIsValidPosition()) // also helps checking if the Y is invalid, which tells the game to spawn 
        {                            // the next tetromino when Y is less <= to the bottom of the grid 

        }
        else
        {
            transform.position += new Vector3(0, 1, 0);
            enabled = false; // disables the current piece, because it is at the bottom. So that the controls are not still
                             // attached to the current piece, after the next one spawned
            FindObjectOfType<Game>().SpawnNextTetromino(); // spawns the next tetromino after the last one reached the bottom
        }
    }

    //#####################################################################################################
    //#####################################################################################################
    /// <summary>
    /// check the position of the individual tiles of the minos (children of the prefab)
    /
    /// </summary>
    /// <returns></returns>
    bool CheckIsValidPosition()
    {
        foreach (Transform mino in transform)
        {
            Vector2 pos = FindObjectOfType<Game>().RoundingTheMinoPosition (mino.position);
            if (FindObjectOfType<Game>().CheckIsInsideGrid(pos) == false)
            {
                return false;
            }

        }
        return true;
    }
}

Game.cs的完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Game : MonoBehaviour {

    public static int gridWidth = 10;  // fixed grid size varibles
    public static int gridHeight = 20; // for the blocks to fall in

    // the grid need to be in a 2d array and we want to store all the x and y values for each world unit of the grid
    // so that we can know which point on the grid are beind occupied by tetrominos that fell in.
    // 
    // the array is gonna store the transforms so we use "gridWidth" and "gridHeight" to define the size of the array.
    public static Transform[,] grid = new Transform[gridWidth, gridHeight];

    // Use this for initialization
    void Start () {
        SpawnNextTetromino();  // spawns the first tetromino in the game

    }

    // Update is called once per frame
    void Update () {

    }

    public void SpawnNextTetromino() // the Resources folder is included when the game compiles, we placed our prefabs  
    {                               // in "Assets\Resources\Prefabs" to allow instantiation in the code.

        // we cast a gameobject -> "(GameObject)" to let "Instantiate" know what we want to instantiate.
        GameObject nextTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), new Vector2(5.0f, 20.0f), Quaternion.identity);
    }


    //gonna pass in the mino position in this method to see 
    // if it is still in the grid
    public bool CheckIsInsideGrid(Vector2 pos) 
    {                                          
        return ((int)pos.x >= 0 && (int)pos.x < gridWidth && (int)pos.y >= 0);
    }

    public Vector2 RoundingTheMinoPosition(Vector2 pos)
    {
        return new Vector2(Mathf.Round(pos.x), Mathf.Round(pos.y));
    }

    /// <summary>
    /// Genreates a random int and assings a teromino prefab to the outcome 
    /// </summary>
    /// <returns></returns>
    string GetRandomTetromino()
    {
        int randomTetromino = Random.Range(1, 8); //
        string randomTetrominoName = null;
        switch (randomTetromino)
        {
            case 1:
                randomTetrominoName = "Prefabs/Tetromino_T";
                break;

            case 2:
                randomTetrominoName = "Prefabs/Tetromino_Long";
                break;

            case 3:
                randomTetrominoName = "Prefabs/Tetromino_Square";
                break;

            case 4:
                randomTetrominoName = "Prefabs/Tetromino_J";
                break;

            case 5:
                randomTetrominoName = "Prefabs/Tetromino_L";
                break;

            case 6:
                randomTetrominoName = "Prefabs/Tetromino_S";
                break;

            case 7:
                randomTetrominoName = "Prefabs/Tetromino_Z";
                break;
        }
        return randomTetrominoName;
    }

}

1 个答案:

答案 0 :(得分:0)

看起来我误解了原来的问题。您只想按下“D”键,但按住“D”键时移动到达到Edge。按住键时需要一个计时器,这可以通过{{{ 1}}。使用- (UIViewController *)viewController { for (UIView* next = [self superview]; next; next = next.superview) { UIResponder *nextResponder = [next nextResponder]; if ([nextResponder isKindOfClass:[UIViewController class]]) { return (UIViewController *)nextResponder; } } return nil; } 按住键时检查,如果计时器达到您认为按下的值的数量,那么您就知道按键已被按下。

另外,检查密钥是否随Time.deltaTime一起发布。如果钥匙被释放但是计时器没有达到您认为的值,那么它只是一个按键。值得在协程函数中执行此操作而不是Input.GetKey函数来简化它,并减少执行此操作所需的变量数量。

Input.GetKeyUp(KeyCode.D)
相关问题