Unity Destroy и другой код не работает? - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь сделать игру Snake, и я пытаюсь заставить функционировать яблоко работать. Этот сценарий предназначен для того, чтобы всякий раз, когда моя Снейк перебирала Apple, яблоко исчезало и появлялось в случайном месте на экране. Но вместо этого он ничего не делает, есть идеи о том, почему?

PS: камера имеет размер 10, а соотношение сторон составляет 16: 9, поэтому у меня есть некоторые странные значения Random.Range. Также я использовал Debug.Log в Update, чтобы убедиться, что переменная работала, и да, она работает, когда моя змея перемещает, отображаются ее координаты.

public class Apple_RandomSpawn : MonoBehaviour
{
    private Vector2 foodPos;
    private Snake_Move snakeMove;

    void Start()
    {
        SpawnApple();
    }

    public void Update()
    {
        transform.position = new Vector2(foodPos.x, foodPos.y);
        SnakeAte();
    }

    public void SpawnApple()
    {
        foodPos = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
    }

    public void SnakeAte()
    {
        if (Mathf.Approximately(foodPos.x, snakeMove.pos.x) && Mathf.Approximately(foodPos.y, snakeMove.pos.y))
        {
            SpawnApple();
        }
    }
}

Ответы [ 2 ]

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

Прежде всего, он не имеет прямого отношения к вашей проблеме, но НЕ ставьте GetComponent() или GameObject.Find() в функцию Update(). Эти две функции, особенно GameObject.Find(), сверхтяжелые , поэтому рекомендуется вызывать эти виды функций внутри Start() или Awake() или при инициализации класса. Это может напрямую и сильно повлиять на производительность вашей игры, поэтому вот мое предложение:

[SerializeField]
private Snake_Move snakeMove;

И перетащите ваш игровой объект (к которому подключен компонент Snake_Head) через Инспектора. Во-первых, всегда следует учитывать этот способ, а не использовать GameObject.Find() и GetComponent().

Во-вторых, Float не рекомендуется сравнивать равенство напрямую через =, поскольку должно быть округление ошибка . Существует функция справки для сравнения двух значений с плавающей запятой в Unity, например Mathf.Approximately(float a, float b). Прямое сравнение двух значений float через = почти всегда не будет работать, как вы думаете.

В-третьих, не похоже, что в вашем коде нет функции Instantiate(), но вы попробуйте использовать один яблочный объект, и каждый раз, когда вы его потребляете, просто меняйте его положение. Тогда почему Object.Destroy(gameObject) существует? То, что вы делаете, просто уничтожаете яблоко, когда получаете его в первый раз. Я думаю, что вам нужно удалить функцию Destroy(), а SpawnApple() изменит целевую координату яблока, и позиция будет обновлена ​​в функции Update().

И нет необходимости косвенно устанавливать цель и обновите его в функции Update(). Вы можете напрямую установить положение яблока, например:

// assuming you followed my suggestio aboven about snakeMove.

public void Update()
    {
        SnakeAte();

        Debug.Log(snakeMove.pos);
    }

public void SpawnApple()
    {
        transform.position = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
    }

public void SnakeAte()
    {
        if (foodPos == snakeMove.pos)
        {
            SpawnApple();
        }
    }
0 голосов
/ 03 апреля 2020

Прежде всего ваш нулевой ref в вашем последнем комментарии происходит от: private Snake_Move snakeMove; Это частная переменная, которая никогда не назначается. Вам нужно либо сделать его публичным / [SerialistField] и назначить его в inspect, либо иметь какую-то функцию инициализации, которая присваивает ему значение.

Для обнаружения попаданий Mathf.Approximately хорошо, если вы хотите проверить, если 2 поплавка точно такие же. Если вы проверяете 2 позиции движущихся объектов, вероятность того, что они будут одинаковыми, очень мала и может зависеть от частоты кадров и тому подобного. Сохраняя свою реализацию, вы можете проверить минимальное расстояние между двумя позициями. Вы можете настроить DISTANCE_THRESHOLD на значение, которое подходит вам лучше.

public class Apple_RandomSpawn : MonoBehaviour
        {
            private const float DISTANCE_THRESHOLD = 0.1f;
            private Vector2 foodPos;
            private Snake_Move snakeMove;

            void Start()
            {
                SpawnApple();
            }

            public void Update()
            {                   
                SnakeAte();
            }

            public void SpawnApple()
            {
                foodPos = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
                transform.position = new Vector2(foodPos.x, foodPos.y);
            }

            public void SnakeAte()
            {
                if (Vector3.Distance(foodPos, snakeMove) < DISTANCE_THRESHOLD)
                {
                    SpawnApple();
                }
            }
        }

Теперь помните, что, поскольку вы телепортируете яблоко в совершенно случайное место, оно может телепортироваться прямо на вашу змею :).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...