Confused about Instantiation, different behavior than manually created; prefabs getting updated

I’m confused about instantiating prefabs and not finding answers in the documentation. I assumed
that an instantiated prefab would behave the same as a gameobject I created manually from a prefab.
This is not what that I am seeing.

I have a prefab called BTile which is a button. The prefab has a script which references an input text.
When I have a manually created BTile, everything works fine. I click the button and the text field
gets updated.

When I instantiate a BTile I see a number of different behaviors. If I try to access my text field via FindWithTag(), it does not find it. If I make my text field a prefab and add it as a property to my BTile script,
the script finds it. However, when I click the button, the text area prefab gets updated and not the
actual text area that is on my screen. That really surprised me that the game updates the prefab.
(I’ve seen other examples of my game updating a prefab which is definitely not what I wanted or expected.)
Not to mention my game object is not getting updated.

So, obviously, my assumptions about instantiation are incorrect. If someone can explain this to me,
I would appreciate it.

private BTile InstantiateTile() {
        print("SelectedWord. InstantiateTile cc " + transform.childCount + "\n");
        var newTile = Instantiate(tilePrefab, new Vector3(0, 0, 0), Quaternion.identity);
        newTile.transform.SetParent(transform, false);
        print("SelectedWord. InstantiateTile " + newTile + "  cc " + transform.childCount + "\n");
        return newTile;
    }

That generally means you dragged the prefab in and that’s why it’s modifying it!!

If you need dynamic UI generated, the pattern is to use an example one (in scene or as prefab) and clone it as much as you need, hooking up the listeners.

See enclosed example package.

9557998–1351300–DynamicUIDemo.unitypackage (94 KB)

Thanks for your response. I’ll look at the package once I figure out how. I’m new to this.
Still, a couple of problems/questions. Still wondering why it works when I drag the prefabs into my scene but not when I instantiate them. I did a little test dragging 3 of these prefabs into the scene and removing the instantiate code and it worked.

Also, when I try to drag my input field from the scene (rather than the prefab) onto my script, I get a type mismatch. I tried a class of TMP_InputField but that gives a type mismatch error. Really strange that you can’t get the class name from the inspector. When I create a prefab from the inputField object I am able to use the type of the prefab, in my case InputWord. But as you point out and I observe, this doesn’t work when using instantiation.

Prefabs you’ve dragged into a scene are all separate instances to one another, and separate to the instance living in your assets. The only connection is where it derives it’s data from, otherwise at runtime you can consider them to all be standalone objects, just with usually similar components and data.

If you want a prefab to have a reference to a particular text field, the object instantiating it should have a reference to said field (the one in the scene, not a prefab), and provide the reference to each instance it makes.

1 Like

Thanks for the explanation. It still doesn’t explain why I am seeing different behaviors between instantiated instances and editor instances. But I don’t want to get hung up on that.

The problem I am now seeing is that I can only assign other prefab objects to my prefab script. When I try and drag an object from my scene onto the prefab script it says it is a type mismatch even when the type is GameObject. Do you know of a way to add an object from a scene onto a prefab script? (I can see where this could be a problem and why unity might disallow it.) So I need to find some other way of locating the InputField. The FindWithTag method didn’t work (even though it does work with non-instantiated editor created instances) but maybe I can find another method. I’ll start working on that now.

You can’t reference scene objects on a prefab.

FindWithTag should work with either way of instantiating.

You are confused about scene instances vs assets. Prefab assets should not really be modified at runtime.

1 Like

That makes sense as you would not want the prefab to be tied to a particular scene. It wasn’t clear to me at first so thanks for confirming.

The FindWithTag definitely did not work for instantiated objects. I did an experiment where I created some scene assets in advance and they were able to find my InputText field. Then I used instantiated instances and they came back with a null reference. Maybe there was something else going on that I’m not aware of since I’m new to Unity but it was a pretty controlled experiment. I ended up punting on this whole thing and created a bunch of instances and set them active and inactive as needed.

FindWithTag probably failed for all the usual reason it fails: The object you’re looking for doesn’t have the right tag, or you misspelt the tag.

Either way it’s bad practice and you should avoid using it. Like I said, have the object instancing these objects provide the reference.

1 Like