Search code examples
unity-game-enginegameobject

Unity Update Text on Gameobject initiated from script from other Gameobject


I am developing for the HoloLens and I Made an object that follows me around. This Gameobject is actually an UI Canvas with text in it which I set like this because i want to keep the original object as well. (Just like in the MS example):

 /// <summary>
/// The object to tag along set in the unity editor
/// </summary>
public GameObject ObjectToTagAlong;

/// <summary>
/// The instantiated object to tag along that follows you around.
/// </summary>
private GameObject instantiatedObjectToTagAlong;

 this.instantiatedObjectToTagAlong = GameObject.Instantiate(this.ObjectToTagAlong);

this instantiatedObject tags along just fine but now I want to update the Text on instantiatedObjectToTagAlong but have no idea how to do this. (I can very easily update the text on the 1st object but i want to do it this way)

Does anyone know how to update the text on a gameobject that is initiated from another GameObject?


Solution

  • To build on what Serlite commented with, you need to use GetComponent in combination with another script.

    public class MyTextUpdater: MonoBehavior
    {
    public Text SuperText2;
    }
    

    Apply MyTextUpdater to your ObjectToTagAlong prefab (or GameObject if not a prefab) and, in the editor, set the value of SuperText2 to the Text object you want to update (typically this is a child of the ObjectToTagAlong GameObject).

    Now anytime you want to update that Text object on your instance, instantiatedObjectToTagAlong, you can do this:

    MyTextUpdater text = instantiatedObjectToTagAlong.GetComponent<MyTextUpdate>();
    if (text!=NULL && text.SuperText2!=NULL) { /*do whatever you need to do on the text.SuperText2 object*/ }
    

    EDIT: When Unity instantiates a copy of a GameObject, it makes a "deep" copy of sorts, meaning that the copy will have the exact same structure of child GameObjects.

    Original                                Copy
    - Child A                               - Child A (copy)
    - Child B              Instanitate =>   - Child B (copy)
    - - Grandchild A                        - - Grandchild A (copy)
    

    Each child is instantiated with it's own new copy. On top of that, if Original has a MonoBehavior script that points to one of it's children (or grandchildren etc), Copy will have a script that points to the appropriately copied child.

    MyTextUpdater [Original]                 MyTextUpdater [Copy]
    - SuperText2 = Child B           =>       - SuperText2 = Child B (copy)
    

    Regarding the question of why have the extra script (the MyTextUpdater script):

    Original is just a GameObject. In the editor you can see it has children, but that does not represent a class. You can not do something like this in a script:

    Original.ChildB.Text = "Hello World!";
    

    in the same way, you can't do this:

    Copy.ChildB.Text = "Hello Copy World!";
    

    You could create code to iterate through all the children of the GameObject looking for a child with the correct name ("ChildB"), but that is inefficient and probably bad programming. The better way is to create a script class that actually does give you access to the child as a field in that class. And that is where the MyTextUpdater script comes in.

    This would be invalid:

    GameObject Copy = Instantiate(Original);
    Copy.SuperText2.Text = "Some text here";
    

    Copy does not have a field or method called SuperText2, or ChildB, or whatever you would call it. But you could do this:

    GameObject Copy = Instantiate(Original);
    MyTextUpdater mtu = Copy.GetComponent<MyTextUpdater>();
    mtu.SuperText2.Text = "Some text here";
    

    Assuming of course that you applied the MyTextUpdater script to Original and made the right connections to the child text component.