Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Instantiating objects, references won't update from a destroyed object to a new object

Discussion in 'Scripting' started by Aazadan, Aug 10, 2017.

  1. Aazadan

    Aazadan

    Joined:
    Jun 21, 2014
    Posts:
    14
    So basically I'm making a VR simulation. I have an object with several children in the scene. Throughout this object is a series of Node objects that link parents and children. The basic idea is that I find a child, and then traverse the Nodes back to the root node, copy this traversal to a list, and then follow the list in sequence playing animations and turning on components making the objects grabbable.

    I have a menu that has several buttons which pass a string which is the name of a piece, and then call an Animate(string endingObject) function on my manager. Each time a button is pressed on my menu I'm destroying the current object in the scene and instantiating a new one.

    What ends up happening though is my first run through the animation plays fine and my manager properly gets the reference to the ending point of my animation sequence, and subsequently is able to build the list out to the starting point. When I instantiate a second copy of the object though (after deleting the first) and attempt to pass it a new ending component, all I get is a bunch of missing GameObjects on my manager. If I run a debug however on the components I'm able to pull the proper object names.

    My best guess as to what is happening is that my manager is updating before the old object is deleted, but when I've inserted pauses into the code to test that theory it still has the same behavior.

    I'm not quite sure what I'm doing wrong here.

    Here's the script in question (sorry for the messy code)
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Playables;
    6.  
    7. public class AnimationPathfinder : MonoBehaviour {
    8.     public GameObject startingPoint;
    9.     public GameObject endingPoint;
    10.     public List<GameObject> path = new List<GameObject>();
    11.     public GameObject currentObject;
    12.     public int spawned = 0;
    13.     public GameObject iBrightPrefab;
    14.     public GameObject iBright = null;
    15.  
    16.     IEnumerator playAnimationPath() {
    17. //        Debug.Log ("Playing animation path");
    18.         for (int i = 0; i < path.Count; i++) {
    19.             //Debug.Log (path [i].name);
    20.             path [i].GetComponent<PlayableDirector> ().Play ();
    21.             float timeToWait = (float)path [i].GetComponent<PlayableDirector> ().duration;
    22.             yield return new WaitForSeconds (timeToWait);
    23.         }
    24.         yield return null;
    25.     }
    26.  
    27.     public void Animate(string ending) {
    28.         //Debug.Log ("Building animation path");
    29.         StopCoroutine(playAnimationPath());
    30.         resetUnit ();
    31.         endingPoint = GameObject.Find (ending);
    32.         currentObject = endingPoint;
    33.         path = new List<GameObject> ();
    34.  
    35.         //Debug.Log ("ending point is active " + endingPoint.activeSelf);
    36.         while (currentObject.GetComponent<Node> ().parent != null) {
    37.             //Debug.Log ("Current Point is " + currentObject.name);
    38.             path.Insert (0, currentObject);
    39.             //currentObject.GetComponent<PlayableDirector> ().timeUpdateMode = DirectorUpdateMode.Manual;
    40.             currentObject = currentObject.GetComponent<Node> ().parent;
    41.         }
    42.         //Debug.Log ("Path built");
    43.         //Debug.Log ("Current Point is " + currentObject.name);
    44.         startingPoint = currentObject;
    45.         path.Insert (0, startingPoint);
    46.         StartCoroutine (playAnimationPath ());
    47.     }
    48.  
    49.     public void resetUnit() {
    50.         if (iBrightPrefab == null) {
    51.             iBrightPrefab = Resources.Load ("Prefabs/Animation IBright") as GameObject;
    52.         }
    53.         if (spawned == 1) {
    54.             Debug.Log ("Attempting to destroy");
    55.             GameObject target = GameObject.Find ("Animation IBright(Clone)");
    56.             Destroy (target);
    57.             spawned = 0;
    58.         }
    59.         if (spawned == 0) {
    60.             iBright = GameObject.Instantiate (iBrightPrefab, new Vector3 (-2.136f, .199f, .620f), Quaternion.identity);
    61.             spawned = 1;
    62.         }
    63.     }
    64. }
    65.  
    66.  
     
    Last edited: Aug 10, 2017
  2. Bantaru

    Bantaru

    Joined:
    May 11, 2016
    Posts:
    59
    My best guess is that Your list of nodes is not cleared and there are references to old objects that no longer exist in the scene but they still exist in the list. This is my best guess as I had such issue in the past where List had non existing game objects. This is why You can pull names of objects but You are getting reference error.

    Try adding path.Clear() when You destroying old object so that You are 100% sure there are no references to objects that do not exist anymore and populate list again.
     
  3. Aazadan

    Aazadan

    Joined:
    Jun 21, 2014
    Posts:
    14
    I've tried path.Clear() and it wasn't working, the result is still the same. You can see on line 33 where I tried to declare a new list instead of clear (that's where clear previously was) wondering if I needed to allocate some new memory for it but that isn't working either.

    Interestingly enough, because of the nature of the scene and the fact that it's fairly resource light, I can actually just reload the scene once things are done playing. If I do that, it all works correctly though I pay a bit of an overhead cost (some of which I can mitigate by persisting items across scenes if they're spawned). Unfortunately, that seems to be the only thing that's actually working. This morning I tried clear and it didn't work. Here's the section of code I adjusted. Adding clear as well as placing it above the unit reset.
    Code (csharp):
    1.  
    2.     public void Animate(string ending) {
    3.         //Debug.Log ("Building animation path");
    4.         StopCoroutine(playAnimationPath());
    5.         path = new List<GameObject> ();
    6.         path.Clear ();
    7.         resetUnit ();
    8.         endingPoint = GameObject.Find (ending);
    9.         currentObject = endingPoint;
    10.  
     
    Last edited: Aug 11, 2017