Losing references with instantiate

If the steering wheel of my car references its wheels, I want the copy of the car to have a steering wheel that references its own wheels. This would be easy with a prefab, but I want users to be able to edit the car model in game and make copies of that. So how do I save a carbon copy of an object hierarchy and preserve all the internal references?

// as we save the prefab...
savedPrefab = Instantiate(modifiedCar);

// Having a parent with DontDestroyOnLoad on but
//with children that don't have it on will cause
// unity to crash. 
DontDestroyOnLoadRecurse(savedPrefab);

//hide the prefab
savedPrefab.SetActiveRecursively(false);



// as we recreate the prefab...
newCar = Instantiate(savedPrefab); // ready to roll!


// helper function 
function DontDestroyOnLoadRecurse (parent : GameObject)
{
    DontDestroyOnLoad(parent);
    i = 0;
    while(i < parent.transform.childCount)
    {
        newParent = parent.transform.GetChild(i).gameObject;
        DontDestroyOnLoadRecurse(newParent);
        i ++;
    }

}

I wish it were that simple. Thing is that some of the children have scripts that reference other children. The steering wheel can be connected to a power system, improving maneuverability, the engine connected to an rocket to improve thrust, and so on.

The user does all this, but then when I use Instantiate to copy the whole thing like in your example, the engine no longer knows it’s connected to the rocket. All the variables with references are empty.

That really shouldn’t happen if all of the references and referencers are limited to children of the object you are instantiating.

If you can’t fix the refs, make it so that when missing they are recreated by the names of game objects or types of objects, ie GetComponentInChildren().

Okay… it appears to only happen with private variables. (??)

If I duplicate an object with this script:

var reference : GameObject;

reference = GameObject.Find("myReferencedObject");

the reference is preserved. But in this one the variable is cleared:

private var reference : GameObject;

reference = GameObject.Find("myReferencedObject");

It’s no big deal to change the scope of my vars, but these aren’t properties that should really be public…

It also seems that if the public variable is not explicitly given a type (i.e. var myVar : float) when it is first declared, the value is reset to null when the object is copied.

Whatever. :wink:

Sorry for the necro, but this is still very true in 2023 (first Google result! I didn’t even notice the thread was from 2007, and took some time recognizing Javascript!).

Just adding that serialization is the key here. So a private field marked [SerializeField] will also be copied properly by Instantiate().

In my case I have a bunch of non-serialized private fields, so changing all the fields is too complicated. Fortunately, all those fields were setup via some custom Init() method, so I just had to call Init() on the copy returned by Instantiate().

This necro really wasn’t necessary. It is well known that Unity can only serialize serializable fields. This means fields that are either public or marked with [SerializeField] and are also of a serializable type.

It is known for intermediate and advanced users yet, but for considering Marble’s comment “It’s no big deal to change the scope of my vars, but these aren’t properties that should really be public…” or the accepted answer in https://answers.unity.com/questions/61480/objectinstantiate-not-copying-fields-from-a-compon.html, it’s not obvious for everyone (I wasn’t sure which page searchers would find so I commented on both; and one of the page just happened to be older, and on the forum, hence the necro).

I admit I didn’t notice there was already another answer in the top list though: https://answers.unity.com/questions/1507597/prefab-loses-reference-when-instantiated.html which already explained about [SerializedField], so I suppose anybody looking at the first 3-4 results would find it eventually.


Now, for the actual issue of search vs necroing: it’s a real problem, you want to help users who legitimately find a given forum page via a search engine to get the definitive answer (and I’m not just talking about this one, where I’m just adding extra information; there are other old threads that may be truly unsolved, but solved in more recent Q&A and just need a little reminder with a redirection to the final answer). But that has the side effect of bumping the post to the top when you don’t really want to.

To me, the solution to this particular issue is to add a checkbox “Do not bump to top of threads (check this when adding minor information to old threads)” or something similar.

In fact, some people started giving suggestions to either warn:
https://discussions.unity.com/t/548582
(not great in my case, it will just make me hesitate more between helping a minority of people and avoid slightly annoying a majority of people, and honestly I was already hesitating)
or even mark thread as resolved to prevent further bump:
https://discussions.unity.com/t/552953

I suppose we could combine all these ideas, so if a. the thread is old or b. the thread is resolved, ask the user whether they really want to bump the post in an opt-in way.

And my favorite:
https://answers.unity.com/questions/1158780/prevent-unity-answers-from-bumping-thread-on-post.html

I discovered that Unity Answers also has a bump system. But probably few people care, because most search specific topics via some search. On Q&A hubs, you generally only check fresh posts where you’re specifically looking for unanswered questions to help people (like the StackOverflow “new question queue”). So yes, specific questions like these should probably be on Unity Answers, so we have a. a centralized place for comments and answers and b. no worries about necro. I’d recommend using Unity Answers a lot more if it wasn’t plagued with weird text bugs these days…

But since that’s not the topic of this thread, we should continue discussion on one of the threads I mentioned above. In fact, I’m going to post my suggestions there.