Search Unity

Failing to render multiple GUIText objects

Discussion in 'Scripting' started by Beguiled, Nov 21, 2014.

  1. Beguiled

    Beguiled

    Joined:
    Mar 15, 2014
    Posts:
    14
    I am working on a simple level loading scene, and am running into some issues using GUIText objects for labels over nodes the player can select. Currently I have my scene set up like this:
    • 5 levelSelectNode game objects with a Sprite Renderer and a script (detailed below)
    • Each levelSelectNode game object has a single child titled "nameLabel" with a GUIText component
    The levelSelectNode script handles assigning a value to the child nameLabel GUIText text field. It also handles positioning the label so that it is always visible as the camera moves about the scene (to allow for panning around the level selection scene).

    levelSelectNode script:
    Code (csharp):
    1.  
    2. public string nodeName;
    3.  
    4. void Update () {
    5.   // Render name label
    6.   Camera mCam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
    7.    transform.GetChild(0).GetComponent<GUIText>().pixelOffset = mCam.WorldToScreenPoint(transform.position);
    8.   transform.GetChild(0).GetComponent<GUIText>().text = nodeName;
    9. }
    10.  
    I placed 5 of these prefab objects onto my scene, and assigned different nodeName values for each (on the parent). When I go to run the game, only the first object shows its name on the game screen. All the rest are missing their labels. However, if I inspect each of the other objects in the Scene view (while the game is running) I see the Text and Pixel Offset values are assigned correctly even though the values are not being represented in the game. Basically, they would appear to be set perfectly (when compared to the first node).

    I've checked the MainCamera and culling is set to Everything. The clipping plane is set to 0-1000. I also attempted to change the pixelOffset to a generic (100,100) value - and when I did this, the first node showed it's nameLabel at that location, but none of the others showed up (I expected them to all show up jumbled together at that location).

    Is there something fundamental I'm missing when it comes to GUIText components? Am I limited to seeing only one at a time? I'd expect not, but I feel I'm missing something important.

    Thanks in advance for any help you can provide!
     
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    If you always use the prefab without a change, it will naturally cause this problem.

    Reason: guiText takes the objects world position as screen coordinates, which range from 0 to 1.

    Example:
    One object at Position P1(0,0,0) has got a GuiText component attached to it.
    That means, moving the object in world units by 0.5 in x and 0.5 in y direction will effectively move the guiText's text by 0.5 screen coordinates. Literally, 50% of the screen size.

    If you now make a prefab out of that object and instantiate it at P1(0,0,0), P2(0,1,0), P2(0,2,0) etc, all the guiTexts of the objects will take the transforms components as the offset value for the text on the screen, causing the first to be 'shown' at the screens origin (0,0), which is the buttom left corner (don't confuse it with GUI coordinates which start off at top left corner). Usually, this won't be seen as well, because assuming the text is within an imaginary rectangle, the screen coordinates are the top left corner of that rectangle, so the text is still outside of the visible area.
    The second guiText will be shown at (0,1) screen coordinates, which is the top left corner. The third would be drawn at (0,2) which is already far outside of the screen.

    I hope that helps to understand the problem.

    Solution if you want to stick to that gui system and do not want to use the new one:

    Either calculate the buttons position in screen coordinates and then assign the result to your objects position, which holds the guiText.
    Or calculate the buttons position in screen coordinates and use the OnGUI method in order to draw a label at that point. For latter one, you'd need one more calculation which translates the screen coordinates into gui coordinates.
     
    Last edited: Nov 21, 2014
  3. Beguiled

    Beguiled

    Joined:
    Mar 15, 2014
    Posts:
    14
    You were totally right - I was relying too much on PixelOffset when I should have instead been using the transform position. I changed my code up to this:
    Code (CSharp):
    1. // Render name label
    2. Camera mCam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
    3. Vector2 labelPos = new Vector2((mCam.WorldToScreenPoint(transform.position).x / Screen.width), (mCam.WorldToScreenPoint(transform.position).y / Screen.height));
    4. transform.GetChild(0).GetComponent<GUIText>().transform.position = labelPos;
    5. transform.GetChild(0).GetComponent<GUIText>().text = nodeName;
    6.  
    And now it works. Thanks!