Unity2D Отключить движение игрока на X секунд - PullRequest
0 голосов
/ 19 сентября 2019

Я пытаюсь отключить движение игрока на 1 секунду, когда оно сталкивается с конкретным объектом.Объект сталкивается, и он обнаруживает, что это нормально, однако в настоящее время вся игра зависает и не возвращается.

Я реализовал значение 0 (как было найдено в других примерах) для движений X и Y с таймером.Это полностью замораживает игру, и я должен убить процесс и открыть Unity.

public Boolean frozen = false;
    float shipDisabledTimer = 1f;
    // Start is called before the first frame update
    void Start()
    {
        SetUpMoveBoundaries();
        gameSession = FindObjectOfType<GameSession>();

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

        Move(frozen);
        Fire();

        if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("Game"))
        {
            if (Input.GetKey(KeyCode.Escape))

                SceneManager.LoadScene("Game Over");
        }
    }



    public void Move(Boolean Frozen)
    {

        UnityEngine.Debug.Log("Update1 - " + Frozen);



            var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
            var deltaY = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;

            var newXPos = Mathf.Clamp(transform.position.x + deltaX, xMin, xMax);
            var newYPos = Mathf.Clamp(transform.position.y + deltaY, yMin, yMax);
            transform.position = new Vector2(newXPos, newYPos);

        if (frozen == true)
        {
            float timer = 0f;
            timer += Time.deltaTime;
            UnityEngine.Debug.Log(frozen);
            while (timer < shipDisabledTimer)
            {
                newXPos = 0;
                newYPos = 0;

            }
            disableship(frozen = false);

        }

    }


    public Boolean disableship(Boolean frozen)
    {
        return frozen;
    }
    private void OnTriggerEnter2D(Collider2D other)
    {
        UnityEngine.Debug.Log(other.gameObject.name);
        if (other.gameObject.name.Equals("Orb Shot(Clone)"))
        {
            UnityEngine.Debug.Log("Orb hit player");
            //StartCoroutine(countdownTimer());
            disableship(frozen = true);
        }
    }

Только корабль должен замерзнуть.Никакой другой игровой объект не должен зависать.Все счета, жетоны, враги должны продолжаться.Только игрок X, Y отключен на 1 секунду.

1 Ответ

3 голосов
/ 19 сентября 2019

while (timer < shipDisabledTimer)
{
    newXPos = 0;
    newYPos = 0;
}

полностью блокирует основной поток вашей игры, так как timer и shipDisabledTime не изменяются в цикле, поэтому он никогда не закончится.

Есть несколькоспособы, которыми вы могли бы пойти сюда.

Invoke

Invoke позволяет вам вызывать метод после определенной задержки, чтобы вы могли легко сделать что-то вроде

public void Freeze()
{
    frozen = true;
    Invoke("Unfreeze"; shipDisabledTime);
}

private void Unfreeze()
{
    frozen = false;
}

сопрограмма

A сопрограмма подобна временному Update методу.В вашем случае проще всего использовать WaitForSeconds и делать что-то вроде

public void Freeze()
{
    StartCoroutine (FreezeRoutine());
}

private IEnumerator FreezeRoutine()
{
    frozen = true;

    yield return new WaitForSeconds(shipDisabledTime);

    frozen = false;
}

простой таймер

Или вы можете использовать простой таймер, но в Update (не цикл пока), как

private float timer = -1;

public void Freeze()
{
    frozen = true;
    timer = shipDisabledTime;
}

private void Update()
{
    if(timer > 0)
    {
        timer -= Time.deltaTime;
        if(timer <= 0)
        {
            timer = -1;
            frozen = false;
        }
    }

    ...
}

И в любом случае, вы просто не берете никаких движений за это время

public void Move()
{
    if(frozen) return;

    ...
}

За исключением *Решение 1040 * Вы также можете расширить их и решили, хотите ли вы, например, складывать несколько стоп-кадров, игнорировать их, когда они уже заморожены, или просто запускать таймеры заново.


Общее примечание: в c # достаточно просто использовать bool это в основном то же самое, но легче читать и писать;)


Также обратите внимание, что этот вызов

disableship(frozen = false);

...

public Boolean disableship(Boolean frozen)
{
    return frozen;
}

довольно странный ... во-первых, этот метод абсолютно ничего не делаетчем просто вернуть то же значение, которое вы передаете в качестве параметра .. вы скрываете поле frozen с таким же именованным параметром, так что это ничего не делает!

Во-вторых, ваш метод возвращает Boolean но вы не назначаете это ни на что.

Если вы хотите изменить значение, просто установите его, используя frozen = XY, но не передавайте это в качестве параметра далее.


Aa и избегайте вызова Debug.Log каждый кадр ..это замедлит работу вашего приложения даже в сборке, в которой вы даже не увидите журнал!

...