Search Unity

Make 3D text always face camera?

Discussion in 'Editor & General Support' started by rhianu, Jan 15, 2011.

  1. rhianu

    rhianu

    Joined:
    Feb 25, 2010
    Posts:
    93
    Hey, I was wondering if there was a way to make 3D text always face the camera? I just wanted to display names above the heads of NPCs like you see in some online games, which I accomplished easily by simply attaching a 3D text game object to the NPC, but the problem is the 3D text always faces in one direction, and I wanted to make it always face the camera so it's always readable, regardless of the angle you view it from.
     
    Last edited: Jan 16, 2011
  2. col000r

    col000r

    Joined:
    Mar 27, 2008
    Posts:
    699
    transform.LookAt(Camera.main.transform)
     
    G-vo, mgbckr, leozhang1 and 2 others like this.
  3. Axel-F

    Axel-F

    Joined:
    Mar 20, 2009
    Posts:
    224
    Correct...plus make it a child object of the camera. So you dont have to do this every frame.
     
    rakkarage likes this.
  4. rhianu

    rhianu

    Joined:
    Feb 25, 2010
    Posts:
    93
    Thanks! That got the text to face the camera like I wanted, but unfortunately the text is now always facing backwards. Any way to fix that?
     
  5. Axel-F

    Axel-F

    Joined:
    Mar 20, 2009
    Posts:
    224
    You need to write the text backwards.

    Just kidding...could not resist. ;) I suggest you change the rotation of the text's gameobject until it fits. Like:

    text.gameobject.transform.localEulerAngles = new Vector3(180, 0, 0)
     
    renatop7 and puzzledpenguin2 like this.
  6. rhianu

    rhianu

    Joined:
    Feb 25, 2010
    Posts:
    93
    ^Thanks, but that line gives me the following error:

    Assets/scripts/face camera.js(5,9): BCE0005: Unknown identifier: 'text'.

    But if I remove the "text.gameobject" part of the line, the error goes away, but the text flips upside down instead of flipping horizontally. However, if I switch the numbers from (180, 0, 0) to (0, 180, 0), it flips correctly, but stops facing the camera. :(
     
  7. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I can't remember how the text mesh is oriented in local space, but in any case, you can orient it however you need to by making the text mesh game object a child of the object that tracks the camera, and then assigning to localEulerAngles as you're doing currently.
     
    SimRuJ likes this.
  8. rhianu

    rhianu

    Joined:
    Feb 25, 2010
    Posts:
    93
    ^Yeah, I was able to get it working by just making the 3D text a child of an empty game object, rotating the text 180 degrees within that empty game object, and then making the empty game object face the camera. So it's actually working pretty well now. However, I think it could work better.

    See, I've noticed that when I spin the camera around, the axis of the 3D text is sometimes skewed on an angle, and I'd like for it to always remain perfectly parallel with the sides of the screen. That is, I want the text to ignore the Z axis when facing the camera, and only rotate along the X and Y axis. Unfortunately, I have no idea how to accomplish this. Any help?
     
    Last edited: Jan 16, 2011
    AndresQAndroid and SimRuJ like this.
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
  10. rhianu

    rhianu

    Joined:
    Feb 25, 2010
    Posts:
    93
    Wow, thanks! That works a lot better than the 3D text method!

    But now I'm running into one tiny other issue with the GUI text that wasn't happening before: if I turn around and face away from the NPC and walk far enough away, the NPC's name comes around, sliding onto the screen in front of me, even though the NPC himself is still in his original location behind me. Any idea what's causing this? Cuz' I obviously can't have the names flying off NPCs like that. It'd be very distracting when trying to play the game.
     
  11. AyphixCEO

    AyphixCEO

    Joined:
    Jun 4, 2011
    Posts:
    1
    This might be necro posting but I figured it out.

    Code (csharp):
    1.  
    2.         if (transform.renderer.isVisible == false) {
    3.             transform.GetChild(0).active = false;
    4.         } else {
    5.             transform.GetChild(0).active = true;
    6.         }
    7.  
    Keep in mind that my GuiText element is a child of the NPC that I am having it follow.
     
  12. woodygoody

    woodygoody

    Joined:
    Aug 23, 2011
    Posts:
    164
    ok, now 3d text always face camera, but 3d text flipped !!!
    how can correct it ?
     
  13. GeorgeRigato

    GeorgeRigato

    Joined:
    Jul 5, 2012
    Posts:
    58
    I got this solution elsewere, but to make your 3D text face the camera, user lookAt function as usual, passing the camera transform position and the magic here is to change the X scale of your 3D text to -1, so itself is already flipped.
     
    Zokylum, Da_Gryk, Tobydoo2 and 3 others like this.
  14. eweeparker

    eweeparker

    Joined:
    Dec 6, 2012
    Posts:
    5
    transform.Rotate(Vector3.up - Vector3(0,180,0));
     
    nguyenlamlll likes this.
  15. mayank047

    mayank047

    Joined:
    Jun 7, 2017
    Posts:
    1
    Hi for Text asset this will definitely work as you all wanted

    public Camera m_Camera;
    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
    transform.LookAt(transform.position + m_Camera.transform.rotation * Vector3.forward,
    m_Camera.transform.rotation * Vector3.up);
    }
     
  16. SimRuJ

    SimRuJ

    Joined:
    Apr 7, 2016
    Posts:
    247
    Thanks for the tip @Jesse Anders and @rhianu, making the 3D text a child of an empty GameObject and then rotating it by 180°, while making the GameObject face the camera worked.
    Is there a way though to make a 3D text ignore the up/down movement of the camera and just turn around the y (z) axis?
     
    Last edited: Sep 18, 2018
  17. zhool

    zhool

    Joined:
    Nov 28, 2016
    Posts:
    3
    Four ways to get your text to face the camera (pick one of 1-4, here 1-3 are commented out):

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5.  
    6. public class ActorScript : MonoBehaviour
    7. {
    8.  
    9.     // Set these in the editor, or in code.
    10.     //transforms
    11.     public Transform bannerLookTarget;
    12.     public Transform bannerDolly;
    13.     //banner text component
    14.     public TMP_Text tmp_text_banner;
    15.  
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         bannerLookTarget = Camera.main.transform;  
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update()
    24.     {
    25.         //1
    26.         //here a canvas rotated 180 about Y is a child of an empty gameobject (here called bannerDolly), bannerDolly rotates to face camera.
    27.         //note: make sure parent gameobject has transform not rect transform
    28.         //bannerDolly.transform.LookAt(bannerLookTarget);
    29.  
    30.         //2
    31.         //tmp_text_banner.transform.rotation = Quaternion.LookRotation(tmp_text_banner.transform.position - bannerLookTarget.position);
    32.         //3
    33.         //tmp_text_banner.transform.LookAt(2 * tmp_text_banner.transform.position - bannerLookTarget.position);
    34.  
    35.         //4
    36.         //locks up/down (x) rotation/tilt by removing the height difference (y);
    37.         Vector3 lookDir = tmp_text_banner.transform.position - bannerLookTarget.position * 2;
    38.         lookDir.y = 0;
    39.         tmp_text_banner.transform.rotation = Quaternion.LookRotation(lookDir);
    40.  
    41.     }
    42. }
    You can put the code into a method instead of update(); calling the method will instantly rotate the transform.
     
    michaelgatesdev likes this.
  18. clamum

    clamum

    Joined:
    May 14, 2017
    Posts:
    61
    EDIT: I decided to see if I could do something a little less "hard coded" and this actually works perfectly too (use the Camera.main.transform.rotation for the Quaternion in the Instantiate call):

    Code (CSharp):
    1. Transform plopDistanceTransform = Instantiate(gameManager.plopDistancePopup, spawnPosition, Camera.main.transform.rotation);
    ORIGINAL POST: I was just having this problem in my 3D mobile game where when an object gets hit, I spawn a little "hit distance" popup that spawns at the collision point and then slowly disappears after a couple seconds (I followed this CodeMonkey video on YouTube, mostly:
    ).

    The text was spawning jacked up using my default of Quaternion.identity (the tutorial was for a 2D game, too) so I then tried using Quaternion.LookRotation(Camera.main.transform) but that wasn't quite right either, though it seemed close.

    Finally, I paused my game and went into the Scene view and clicked on the Camera, and copied down the X/Y/Z values for its Rotation.

    I then used those values in a Quaternion.Euler() call and that worked perfectly:

    Code (CSharp):
    1. Quaternion facingCameraRotation = Quaternion.Euler(new Vector3(30.542f, 275.125f, 1.156f));
    2.  
    3. Transform plopDistanceTransform = Instantiate(gameManager.plopDistancePopup, spawnPosition, facingCameraRotation);
    Side note that my Camera always faces the same direction (it follows a flying game object but stays looking in the same direction), so if yours changes direction/rotation, then this probably won't work.
     
    Last edited: May 13, 2020
  19. roycefernandes3

    roycefernandes3

    Joined:
    Jan 21, 2019
    Posts:
    4
    I approached the problem where the text appears inverted along the y axis like this:

    score++;
    GameObject point = Instantiate(PointPrefab, scorePosition + offset, Quaternion.identity);
    Destroy(point, 2);
    point.transform.LookAt(GameObject.FindGameObjectWithTag("Player").transform);
    Quaternion q = point.transform.rotation;
    point.transform.rotation = Quaternion.Euler(q.eulerAngles.x, q.eulerAngles.y + 180, q.eulerAngles.z);
    point.GetComponent<TextMeshPro>().text = score.ToString();