Unity - Space Shooter 2D - игнорировать OnTriggerEnter, когда игровой объект уничтожается - PullRequest
0 голосов
/ 23 апреля 2020

Я новичок в Unity и создал небольшую космическую стрелялку в 2D.

Когда игрок стреляет в противника с помощью болта, вражеский объект уничтожается, и игрок получает 1 очко.

Когда игрок собирает бонусы, он может выстрелить 2 болта одновременно. Если эти 2 удара попали в противника, игрок получает 2 очка вместо 1 очка, к сожалению. Метод OnTriggerEnter в прилагаемом скрипте «DestroyByContact» противника вызывается дважды.

Как я могу игнорировать OnTriggerEnter, если игровой объект разрушается? Может быть, кто-то может мне помочь.

Я добавил код для метода OnTriggerEnter ниже.

private void OnTriggerEnter(Collider other)
{
    switch (gameObject.tag)
    {
        case "Player":
            {
                if (other.CompareTag("Asteroid"))
                {
                    if (playerController.HasShield())
                    {
                        Destroy(other.gameObject); // Asteroid

                        Instantiate(asteroidExplosion, other.transform.position, other.transform.rotation);
                        playerController.RemoveShield();
                    }
                    else
                    {
                        Destroy(other.gameObject); // Asteroid
                        Destroy(gameObject); // Player

                        Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
                        gameController.GameOver();
                    }
                }
                if (other.CompareTag("Enemy"))
                {
                    if (playerController.HasShield())
                    {
                        Destroy(other.gameObject); // Enemy

                        Instantiate(enemyExplosion, other.transform.position, other.transform.rotation);
                        playerController.RemoveShield();
                    }
                    else
                    {
                        Destroy(other.gameObject); // Enemy
                        Destroy(gameObject); // Player

                        Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
                        gameController.GameOver();
                    }
                }
                if (other.CompareTag("BoltEnemy"))
                {
                    if (playerController.HasShield())
                    {
                        Destroy(other.gameObject); // BoltEnemy

                        playerController.RemoveShield();
                    }
                    else
                    {
                        Destroy(other.gameObject); // BoltEnemy
                        Destroy(gameObject); // Player

                        Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
                        gameController.GameOver();
                    }
                }
                if (other.CompareTag("Boss"))
                {
                    // if player ship hits the boss, player gets destroyed, no matter if he has a shield left or not
                    if (playerController.HasShield())
                    {
                        playerController.RemoveShield();
                    }
                    Destroy(gameObject); // Player

                    Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
                    gameController.GameOver();
                }
                if (other.CompareTag("PowerUpBolt"))
                {
                    Destroy(other.gameObject); // PowerUpBolt

                    audioPowerUp.Play();
                    playerController.IncreaseShotSpawns();
                }
                if (other.CompareTag("PowerUpHealth"))
                {
                    Destroy(other.gameObject); // PowerUpHealth

                    audioPowerUp.Play();
                    if (!playerController.HasShield())
                    {
                        playerController.AddShield();
                    }
                }
            }
            break;
        case "Asteroid":
            {
                if (other.CompareTag("BoltPlayer"))
                {
                    Destroy(other.gameObject); // BoltPlayer
                    Destroy(gameObject); // Asteroid

                    Instantiate(asteroidExplosion, other.transform.position, other.transform.rotation);
                    gameController.AddScore(scoreValueAsteroid);
                }
            }
            break;
        case "Enemy":
            {
                if (other.CompareTag("BoltPlayer"))
                {
                    Destroy(other.gameObject); // BoltPlayer
                    Destroy(gameObject); // Enemy

                    Instantiate(enemyExplosion, other.transform.position, other.transform.rotation);
                    gameController.AddScore(scoreValueEnemy);
                    gameController.SpawnPowerUp(other.transform);
                }
            }
            break;
        case "Boss":
            {
                if (other.CompareTag("BoltPlayer"))
                {
                    Destroy(other.gameObject); // BoltPlayer
                    bossController.GotHit();

                    if (bossController.IsDefeated())
                    {
                        Destroy(gameObject); // Boss

                        Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
                        gameController.Success();
                    }
                }
            }
            break;
    }
}

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

После вызова Destroy Unity помечает данный объект для уничтожения, но он не уничтожается до следующего кадра. Чтобы не вызывать ваш метод дважды, просто добавьте переменную bool к классу врага и отметьте ее внутри OnTriggerEnter

Это может выглядеть так

bool isDestroyed = false;

void OnTriggerEnter(Collider other)
{
    if (isDestroyed) return;
    else
    {
        isDestroyed = true;
        Destoy(gameObject);
        // whatever else should happen
    }
}
0 голосов
/ 23 апреля 2020

Как уже упоминалось в других ответах, Destroy() уничтожит объект в конце текущего кадра, и, так как ваш скрипт вызывается дважды в одном кадре, вы получите два очка.
К счастью, Unity имеет особенность, позволяющая избежать этого: если вы увеличиваете свой счет на OnDestroy(), это гарантированно произойдет только один раз.

void OnDestroy(){
    player.IncrementScore();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...