I followed the speech bubble tutorial at http://www.41post.com/4545/programming/unity-how-to-create-a-speech-balloon. And i want to put this pointing at the head of my NPC characters when they say something. The solution is working fine however the positioning of the element is definitely not what I want, I tried fiddling here and there with the offsets but i couldnt get it working. Look at the two screenshots I included of how it looks like ingame. The first one is the ‘small’ view which just doesn’t show the text at all (Imgur: The magic of the Internet). while the second one does show the balloon but as you can see it is way to low (http://imgur.com/VvngEF6)
My code is:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//tutorial followed at http://www.41post.com/4545/programming/unity-how-to-create-a-speech-balloon
//Edited to my own needs (appear on collision, positioning, ...)
public class SpeechBubble : MonoBehaviour {
private Transform goTransform;
private Vector3 goScreenPos;
private Vector3 goViewportPos;
public static bool bubbleShow { get; set; }
public int bubbleWidth = 300;
public int bubbleHeight = 100;
public float offsetX = 0;
public float offsetY = 250;
private int centerOffsetX;
private int centerOffsetY;
private Material mat;
private GUISkin guiSkin;
public string whatToSay { get; set; }
//use this for early initialization
void Awake ()
{
bubbleShow = false;
mat = (Material)UnityEngine.Resources.Load ("White Unlit", typeof(Material));
guiSkin = (GUISkin)UnityEngine.Resources.Load("GUISkin", typeof(GUISkin));
goTransform = this.GetComponent<Transform>();
}
void Start()
{
if (!mat)
{
Debug.LogError("Please assign a material on the Inspector.");
return;
}
if (!guiSkin)
{
Debug.LogError("Please assign a GUI Skin on the Inspector.");
return;
}
centerOffsetX = bubbleWidth/2;
centerOffsetY = bubbleHeight/2;
}
//Called once per frame, after the update
void LateUpdate()
{
goScreenPos = Camera.main.WorldToScreenPoint(goTransform.position);
goViewportPos.x = goScreenPos.x/(float)Screen.width;
goViewportPos.y = goScreenPos.y/(float)Screen.height;
}
//Draw GUIs
void OnGUI()
{
if (bubbleShow) {
GUI.BeginGroup(new Rect(goScreenPos.x-centerOffsetX-offsetX,Screen.height-goScreenPos.y-centerOffsetY-offsetY,bubbleWidth,bubbleHeight));
GUI.Label(new Rect(0,0,200,100),"",guiSkin.customStyles[0]);
GUI.Label(new Rect(10,25,190,50),whatToSay,guiSkin.label);
GUI.EndGroup();
}
}
//Called after camera has finished rendering the scene
void OnRenderObject()
{
if (bubbleShow) {
GL.PushMatrix ();
mat.SetPass (0);
GL.LoadOrtho ();
GL.Begin (GL.TRIANGLES);
GL.Color (Color.white);
GL.Vertex3 (goViewportPos.x, goViewportPos.y + (offsetY / 3) / Screen.height, 0.1f);
GL.Vertex3 (goViewportPos.x - (bubbleWidth / 3) / (float)Screen.width, goViewportPos.y + offsetY / Screen.height, 0.1f);
GL.Vertex3 (goViewportPos.x - (bubbleWidth / 8) / (float)Screen.width, goViewportPos.y + offsetY / Screen.height, 0.1f);
GL.End ();
GL.PopMatrix ();
}
}
void OnTriggerEnter(Collider other) {
bubbleShow = true;
}
void OnTriggerExit(Collider other) {
bubbleShow = false;
}
}
Does anyone have a solution to this or a better solution to speech bubble generation in general?