- Home /
Dialog text above player's head?
I am trying to get my GUI Label to appear above my player but can't get it quite right! Now before you suggest the ObjectLabel on the unify wiki, I need it to do the opposite of that, where instead of attaching the gameobject to the text the text needs to be applied relative to the gameobject
heres what i have at the moment, but its awful!
Vector3 coords = Camera.main.WorldToScreenPoint(transform.position);
GUI.Label(new Rect(coords.x * Screen.width, (1 - coords.y )* Screen.height - 100,100,50), dialog);
although when you move on the y axis it goes a bit funny? Also I wouldn't know for the life of me where to begin on working out how to clamp it to the screen!
This is infact how I would like to do it, using a GUI Text would not work for me.
Thanks in advance
Your code looks fine (though I'd use WorldToScreenPoint for simplicity). Exactly what goes wrong? (i.e. what is "a bit funny"?)
In order to clamp the label to the screen, you can calculate the rect size then adjust its position. There's a function in the GUI system to calculate the size:
http://unity3d.com/support/documentation/ScriptReference/GUIStyle.CalcSize.html
@Warwick Allison I've used WorldToScreenPoint which is working a lot better now, thanks! Any idea on clamping is to screen?
@aldonaletto I took a look at calcsize but couldnt get it working in c#? :/
ObjectLabel on the wiki does attach text to the game object. Why would a GUIText not work for you?
Because im outputting a GUI Area not just text (that is dynamically created depending on certain factors)
Answer by CarlLawl · Jun 28, 2011 at 01:32 AM
Ok so first I get the position of my character in relation to the camera
Vector3 characterPos = Camera.main.WorldToScreenPoint(characterObject.transform.position);
then i clamp the position inside the screen
characterPos = new Vector3(Mathf.Clamp(characterPos.x,0 + (windowWidth / 2),Screen.width - (windowWidth / 2)),
Mathf.Clamp(characterPos.y,50,Screen.height),
characterPos.z);
then i add my BeginArea positioned in relation to my character
GUILayout.BeginArea(new Rect((characterPos.x + offsetX) - (windowWidth / 2), (Screen.height - characterPos.y) + offsetY, windowWidth, windowHeight));
Whole code:
void OnGUI () {
Vector3 characterPos = Camera.main.WorldToScreenPoint(characterObject.transform.position);
characterPos = new Vector3(Mathf.Clamp(characterPos.x,0 + (windowWidth / 2),Screen.width - (windowWidth / 2)),
Mathf.Clamp(characterPos.y,50,Screen.height),
characterPos.z);
GUILayout.BeginArea(new Rect((characterPos.x + offsetX) - (windowWidth / 2), (Screen.height - characterPos.y) + offsetY, windowWidth, windowHeight));
// GUI CODE GOES HERE
GUILayout.EndArea();
}
obviously this would need tweaking to make it perfect but this is just pseudo code to help anyone with this problem good luck, i hope this helps
Excellent! I was getting annoyed with using just WorldToSceenPoint as it isnt always about the object.
Answer by kamran-bigdely · Sep 14, 2017 at 12:09 AM
Here is shorter way to do so (with less mathematics). First you create a new gameObject and add a TextMesh component and configure it with your desired text and fonts and style. You can do it in the Editor or write code to do so:
void Start() {
GameObject sign = new GameObject("player_label");
sign.transform.rotation = Camera.main.transform.rotation; // Causes the text faces camera.
TextMesh tm = sign.AddComponent<TextMesh>();
tm.text = "put your text here. You can use some of the html attributes";
tm.color = new Color(0.8f, 0.8f, 0.8f);
tm.fontStyle = FontStyle.Bold;
tm.alignment = TextAlignment.Center;
tm.anchor = TextAnchor.MiddleCenter;
tm.characterSize = 0.065f;
tm.fontSize = 60;
}
Then, in the Update() method, place it above the player gameObject:
void Update() {
sign.transform.position = player.position + Vector3.up * 3f;
}
You may ask why we didn't made the sign gameObject a child of player gameObject instead of placing it above the player. The quick answer is that if the player rotates then the sign would rotate with it too because it's a child of player gameObject. This is unwanted. We want the text to always facing the camera.
Works great, thank you! Do you know how can I disable the scaling and always keep it the same size?
This is the best answer, very simple and straight forward. Just one thing, you can do add the "sign" gameObject as a child to the player and then add this line to the the update function so the text will always face the camera :)
sign.transform.rotation = Camera.main.transform.rotation; // Causes the text faces camera
Answer by Reavenk · Jun 27, 2011 at 05:32 PM
I've had problems with the Y being inverted before.
Vector3 coords = Camera.main.WorldToScreenPoint(transform.position);
coords.y = Screen.height - coords.y;
GUI.Label(new Rect(coords.x * Screen.width, (1 - coords.y )* Screen.height - 100,100,50), dialog);
You should be able to use Screen.width and Screen.height to clamp the position.
Answer by Waz · Jun 27, 2011 at 09:15 PM
So you're good now by using WorldToScreenPoint
, all you need now is clamping? All you need do for that is:
Vector3 coords = Camera.main.WorldToScreenPoint(transform.position);
Rect r = new Rect(coords.x, Screen.height - coords.y - 100,100,50);
if (r.x < 0)
r.x = 0;
else if (r.xMax >= Screen.width)
r.x = Screen.width - r.width;
if (r.y < 0)
r.y = 0;
else if (r.yMax >= Screen.height)
r.y = Screen.height - r.height;
After doing some more research i decided to use $$anonymous$$athf.Clamp() Thanks though!
Your answer
Follow this Question
Related Questions
gui creation over an object 0 Answers
Camera rotation around player while following. 6 Answers
Instantiate a GameObject at the position of one of its child objects 1 Answer
Instantiate Name Issue. 1 Answer
addition of vector3 1 Answer