Unity3D: Как я могу уничтожить экземпляры префаба препятствий, когда игрок проходит их по оси Z в бесконечном раннере? - PullRequest
3 голосов
/ 03 августа 2020

Я пробовал установить разные имена для экземпляров и Destroy(this), Destroy(this.gameObject) и только Destroy(gameObject), но ни один из них, похоже, не работает ...

Вот код для экземпляров прикрепленный к пустому игровому объекту:

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

public class Spawner : MonoBehaviour
{

    public GameObject[] obstaclePatterns;
    public Transform player;
    private float timeBtwSpawn;
    public float startTimeBtwSpawn;
    public float obstacleSpawnDistance;
    public float obstacleSpDMin;
    public float obstacleSpDMax;
    public float decreaseTime;
    public float minTime = 0.65f;
    public float obstacleHeightMin = 10f;
    public float obstacleHeightMax = 15f;

// makes obstacles randomly ahead of player

    private void FixedUpdate() {
        if (timeBtwSpawn <= 0) {
            obstacleSpawnDistance = Random.Range(obstacleSpDMin, obstacleSpDMax);
            int rand = Random.Range(0, obstaclePatterns.Length);
            Instantiate(obstaclePatterns[rand], new Vector3(obstaclePatterns[rand].transform.position.x, Random.Range(obstacleHeightMin, obstacleHeightMax), player.position.z + obstacleSpawnDistance), Quaternion.identity);
            rand = Random.Range(0, obstaclePatterns.Length);
            Instantiate(obstaclePatterns[rand], new Vector3(obstaclePatterns[rand].transform.position.x, Random.Range(obstacleHeightMin, obstacleHeightMax), player.position.z + obstacleSpawnDistance), Quaternion.identity);
            rand = Random.Range(0, obstaclePatterns.Length);
            Instantiate(obstaclePatterns[rand], new Vector3(obstaclePatterns[rand].transform.position.x, Random.Range(obstacleHeightMin, obstacleHeightMax), player.position.z + obstacleSpawnDistance), Quaternion.identity);
            timeBtwSpawn = startTimeBtwSpawn;
            if (startTimeBtwSpawn > minTime) {
                startTimeBtwSpawn -= decreaseTime;
            }
        }
        else {
            timeBtwSpawn -= Time.deltaTime; 
        }
    }
}

А вот код функции уничтожения, прикрепленной к префабу препятствия:

using UnityEngine;

public class ObjectDestruction : MonoBehaviour {

    public Transform player;

    // Update is called once per frame
    void FixedUpdate()
    {
        if (transform.position.z < player.position.z) {
            Destroy(gameObject);
            Debug.Log("test");
        }
    }
}

Debug.Log работает нормально, но консоль продолжает выдавать эту ошибку: MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. Spawner.FixedUpdate () (at Assets/Scripts/Spawner.cs:26)

EDIT: Destroy(this) похоже, избавляется от сообщения об ошибке, но не уничтожает объекты.

Заранее большое спасибо!

1 Ответ

2 голосов
/ 03 августа 2020

Я не знаком с unity3d, но подозреваю, что при уничтожении объекта вам также необходимо удалить ссылки на него:

В настоящее время у вас есть массив gameObject, хранящийся в obstaclePatterns, поэтому, когда вы уничтожаете объект, он становится нулевым, но остается в массиве obstaclePatterns, и ваш код пытается его использовать.

Есть два способа исправить это:

  1. Когда вы уничтожить GameObject, вы можете удалить его из массива obstaclePatterns, например int x = IndexOf(obstaclePatterns, gameObject); obstaclePatterns[x] = null; или
  2. Сделайте так, чтобы ваша программа проверяла, является ли GameObject in obstaclePatterns нулевым, и если да, то выполните не используйте его, например if(obstaclePatterns[x] != null){do stuff here}.

Альтернативно: Вы уверены, что хотите уничтожить игровой объект? Не лучше ли снова переместить объект впереди игрока и использовать его повторно?

...