Search Unity

Feedback Spawning/destroying objects

Discussion in 'Works In Progress - Archive' started by rex_francorum, Jun 9, 2020.

  1. rex_francorum

    rex_francorum

    Joined:
    Jun 25, 2019
    Posts:
    17
    Hi,

    I am a new student of C# and attempting to make a project where game objects (asteroids) spawn randomly. This works well for the first few cycles, but then get this error when two asteroids collide:

    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.
    UnityEngine.Object.Instantiate[T] (T original) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.bindings.cs:275)
    RockSpawner.SpawnRock () (at Assets/Scripts/RockSpawner.cs:82)
    RockSpawner.Update () (at Assets/Scripts/RockSpawner.cs:65)

    What is wrong with my code?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Rock : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     Sprite[] rockSprites;
    9.  
    10.     Sprite image;
    11.     Camera mainCamera;
    12.     public Vector2 widthThresold;
    13.     public Vector2 heightThresold;
    14.     /// <summary>
    15.     /// Use this for initialization
    16.     /// </summary>
    17.     void Start()
    18.     {
    19.         image = rockSprites[Random.Range(0, rockSprites.Length)];
    20.         GetComponent<SpriteRenderer>().sprite = image;
    21.  
    22.         // apply impulse force to get game object moving
    23.         const float MinImpulseForce = 1f;
    24.         const float MaxImpulseForce = 2f;
    25.         float angle = Random.Range(0, 2 * Mathf.PI);
    26.         Vector2 direction = new Vector2(
    27.             Mathf.Cos(angle), Mathf.Sin(angle));
    28.         float magnitude = Random.Range(MinImpulseForce, MaxImpulseForce);
    29.      
    30.         GetComponent<Rigidbody2D>().AddForce(
    31.             direction * magnitude,
    32.             ForceMode2D.Impulse);
    33.     }
    34.  
    35.  
    36.     // Update is called once per frame
    37.     void Update()
    38.     {
    39.         if (transform.position.x < -9.5f || transform.position.x > 9.5f || transform.position.y < -5.5f || transform.position.y > 5.5f)
    40.         {
    41.             Destroy(gameObject);
    42.             RockSpawner.numRocks--;
    43.         }
    44.     }
    45.  
    46.     private void OnCollisionEnter2D(Collision2D collision)
    47.     {
    48.         if(collision.gameObject.tag == "Rock")
    49.         {
    50.             Destroy(gameObject);
    51.             RockSpawner.numRocks--;
    52.         }
    53.     }
    54. }
    55.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class RockSpawner : MonoBehaviour
    6. {
    7.     //prefab to be spawned
    8.     [SerializeField]
    9.     public GameObject spawnObject;
    10.  
    11.     //time variables
    12.     Timer timer;
    13.     const float MinSpawnTime = 0.5f;
    14.     const float MaxSpawnTime = 1.25f;
    15.  
    16.     //location variables
    17.     const int SpawnBorderSize = 100, MaxRocks = 3;
    18.     int minSpawnX, maxSpawnX, minSpawnY, maxSpawnY;
    19.     public static int numRocks;
    20.  
    21.     //sprite variables
    22.     Sprite[] rockSprites;
    23.     GameObject[] obj;
    24.  
    25.     // Start is called before the first frame update
    26.     void Start()
    27.     {
    28.         //Get list of gameObjects for later
    29.         //obj = GameObject.FindGameObjectsWithTag("Rock");
    30.  
    31.         //Account for the empty Rock object in the project
    32.         numRocks = 1;
    33.  
    34.         // save spawn boundaries for efficiency
    35.         minSpawnX = SpawnBorderSize;
    36.         maxSpawnX = Screen.width - SpawnBorderSize;
    37.         minSpawnY = SpawnBorderSize;
    38.         maxSpawnY = Screen.height - SpawnBorderSize;
    39.  
    40.         // create and start timer
    41.         timer = gameObject.AddComponent<Timer>();
    42.         timer.Duration = Random.Range(MinSpawnTime, MaxSpawnTime);
    43.         timer.Run();
    44.  
    45.         //obj = GameObject.FindGameObjectsWithTag("Rock");
    46.     }
    47.  
    48.     // Update is called once per frame
    49.     void Update()
    50.     {
    51.         /*
    52.         if (obj.Length > 0)
    53.         {
    54.             foreach (GameObject x in obj)
    55.             {
    56.                 ++numRocks;
    57.             }
    58.         }
    59.         */
    60.  
    61.        
    62.         // check for time to spawn a new rock
    63.         if (timer.Finished && numRocks < MaxRocks)
    64.         {
    65.             SpawnRock();
    66.             ++numRocks;
    67.  
    68.  
    69.             // change spawn timer duration and restart
    70.             timer.Duration = Random.Range(MinSpawnTime, MaxSpawnTime);
    71.             timer.Run();
    72.         }
    73.     }
    74.  
    75.     void SpawnRock()
    76.     {
    77.         // generate random location and create new rock
    78.         Vector3 location = new Vector3(Random.Range(minSpawnX, maxSpawnX),
    79.             Random.Range(minSpawnY, maxSpawnY),
    80.             -Camera.main.transform.position.z);
    81.         Vector3 worldLocation = Camera.main.ScreenToWorldPoint(location);
    82.         GameObject rock = Instantiate(spawnObject) as GameObject;
    83.         rock.transform.position = worldLocation;
    84.     }
    85. }
    86.  
    There is also a Timer class provided by my instructor, but that doesn't seem germane to the issue
     
  2. welby

    welby

    Joined:
    Mar 22, 2011
    Posts:
    549
    Maybe Swap these two lines ,..? put the destroy under the spawner line.

    1. Destroy(gameObject);
    2. RockSpawner.numRocks--
     
  3. rex_francorum

    rex_francorum

    Joined:
    Jun 25, 2019
    Posts:
    17
    It looks like the issue has to do with my Instantiate call on line 82 of the second file