Researcher in Virtual Reality and Scientific visualization with a secret, uncontrollable passion for gamedev.

  • View media
  • View media
  • View media
  • View media
  • View media
  • View media
RSS My Blogs

Here we go, it took some pain as we only begun using uGUI less than a couple of weeks ago, but we managed to develop a functional tooltips system. It might still be improved and polished and the code is partially dirty, but it works well, it shows no performance issues of any kind.

No more talking and straight to how we did it, as we saw several people asking about something similar in several other places.

Video Example Tooltip System

We have a tooltip object in the canvas, consisting of a panel with the background image and a child text element. to the panel we attached our tooltip script.

first of all add on top of your scripts

using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;


When we are building the interfaces, we attach an EventTrigger to the object from the inspector, graphically, then from the code initializing the button we add triggers with a callback to the objects we need to get the data from in the following way :

public ToolTip ttp; //initialize this by getting the script attached to the tooltip

foreach(RectTransform elem in childs){
	if(elem.name=="Button"){
		portraits.Add(elem.GetComponent<Image>());
                EventTrigger trig = elem.gameObject.GetComponent<EventTrigger>();
		AddPointerEnterTrigger(trig,OnPointerEnter,EventTriggerType.PointerEnter);
		AddEventTrigger(trig,OnPointerExit,EventTriggerType.PointerExit);
	}

and the functions are

private void AddPointerEnterTrigger(EventTrigger evTrig, UnityAction<BaseEventData> action, EventTriggerType triggerType){
	EventTrigger.TriggerEvent trigger = new EventTrigger.TriggerEvent();
	AddEventTrigger(evTrig,d => OnPointerEnter(d, evTrig.gameObject),EventTriggerType.PointerEnter);
	EventTrigger.Entry entry = new EventTrigger.Entry() { callback = trigger, eventID = triggerType };
	evTrig.delegates.Add(entry);
}

private void AddEventTrigger(EventTrigger evTrig, UnityAction action, EventTriggerType triggerType){
	EventTrigger.TriggerEvent trigger = new EventTrigger.TriggerEvent();
	trigger.AddListener((eventData) => action()); 
	EventTrigger.Entry entry = new EventTrigger.Entry() { callback = trigger, eventID = triggerType };
	evTrig.delegates.Add(entry);
}

private void AddEventTrigger(EventTrigger evTrig, UnityAction<BaseEventData> action, EventTriggerType triggerType){
EventTrigger.TriggerEvent trigger = new EventTrigger.TriggerEvent();
trigger.AddListener((eventData) => action(eventData)); 
EventTrigger.Entry entry = new EventTrigger.Entry() { callback = trigger, eventID = triggerType };
evTrig.delegates.Add(entry);
}
private void OnPointerEnter(BaseEventData dataObject, GameObject hovered){ if(hovered != null){ ttp.SetTooltip(hovered.name); } } private void OnPointerExit(){ ttp.HideTooltip(); }

and then this is the script attached to the tooltip object. (this is the version for the gui canvas on screen overlay mode), it contains already a rough function so that the tooltip never goes offscreen if the mouse is close to the edge, and resizes itself (on a single line only at the moment) according to the length of the text

//text of the tooltip
    Text text;
 
    //if the tooltip is inside a UI element
    bool inside;
   
    bool xShifted = false;
    bool yShifted = false;
 
    int textLength;
 
    float width;
    float height;
 
    int screenWidth;
    int screenHeight;
 
    float canvasWidth;
    float canvasHeight;
 
    float yShift;
    float xShift;
 
    int canvasMode;
 
public void SetTooltip(string ttext){
        //ScreenSpaceOverlay Tooltip
        if(GUIMode==RenderMode.ScreenSpaceOverlay){
            //set the text and fit the tooltip panel to the text size
            text.text=ttext;
 
            this.transform.GetComponent<RectTransform>().sizeDelta = new Vector2(text.preferredWidth+60f,text.preferredHeight+20f);
            width = this.transform.GetComponent<RectTransform>().sizeDelta[0];
            height = this.transform.GetComponent<RectTransform>().sizeDelta[1];
 
            Vector3 newPos = Input.mousePosition-new Vector3(xShift,yShift,0f);
            //check and solve problems for the tooltip that goes out of the screen on the horizontal axis
            float val;
            val=(newPos.x-(width/2));
            if(val<=0){
                newPos.x+=(-val);
            }
            val=(newPos.x+(width/2));
            if(val>screenWidth){
                newPos.x-=(val-screenWidth);
            }
            //check and solve problems for the tooltip that goes out of the screen on the vertical axis
            val=(screenHeight-newPos.y-(height/2));
            if( val<=0 &amp;&amp; !yShifted){
                yShift=(-yShift+25f);
                newPos.y+=yShift*2;
                yShifted=true;
            }
            this.transform.position=newPos;
            this.gameObject.SetActive(true);
 
            inside=true;
        //WorldSpace Tooltip
        }
}
 
public void HideTooltip(){
        //ScreenSpaceOverlay Tooltip
        if(GUIMode==RenderMode.ScreenSpaceOverlay){
            xShift = 40f;yShift = -30f;
            xShifted=yShifted=false;
            this.transform.position=Input.mousePosition-new Vector3(xShift,yShift,0f);
            this.gameObject.SetActive(false);
            inside=false;
        }
}
 
void FixedUpdate () {
        if(inside){
            //ScreenSpaceOverlay Tooltip
            if(GUIMode==RenderMode.ScreenSpaceOverlay){
                Vector3 newPos = Input.mousePosition-new Vector3(xShift,yShift,0f);
                //check and solve problems for the tooltip that goes out of the screen on the horizontal axis
                float val;
                val=(newPos.x-(width/2));
                if( val<=0){
                    newPos.x+=(-val);
                }
                val=(newPos.x+(width/2));
                if(val>screenWidth){
                    newPos.x-=(val-screenWidth);
                }
                //check and solve problems for the tooltip that goes out of the screen on the vertical axis
                val=(screenHeight-newPos.y-(height/2));
                if(val<=0){
                    if(!yShifted){
                        yShift=(-yShift+25f);
                        newPos.y+=yShift*2;
                        yShifted=true;
                    }
                }
                this.transform.position=newPos;
        }
}


here is a little video showing how it works. we make the tooltip appearing a bit above the mouse pointer so that it doesn't cause onpointerover problems, and we use the fixedupdate for the refresh as it is somehow more reliable about flickering and speed.

Video Example Tooltip System

if you have any problem in implementing it, feel free to ask more details!

Cheers,
H

Start a group Groups
Hammer&Ravens;

Hammer&Ravens;

2 members Developer & Publisher

Development group based in Tallinn, Estonia. After a past as independent media developers (kinect,leap motion,touch screens, stereoscopics and autostereoscopics...

Tower Defense IndieDev

Tower Defense IndieDev

12 members Fans & Clans

For all the indiedev out there that think that, while needing to reinvent itself and envolve, Tower Defense is far from dead. To share ideas, to share...

Grand strategy fans

Grand strategy fans

24 members Fans & Clans

For everybody who loves/likes grand strategy games.

Post a comment
Sign in or join with:

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.

Level
Avatar
Avatar
Last Online
Country
Estonia Estonia
Friends
Become friends
Member watch
Follow
Statistics
Rank
4,504 of 645,763
Visitors
4,156 (1 today)
Time Online
3 days
Activity Points
667
Watchers
4 members
Comments
50
Tags
2
Site visits
2,209
Contact
Contact
Send Message
Twitter

Latest tweets from @eir_td

RT @EiR_TD: Well, tough as she is battlefields have their pitfalls... . #indiedev #gamedev #screenshotsaturday @EiR_TD T.co

21hours ago

RT @EiR_TD: On the rare occasion that she has nothing to do on the battlefield, she would really like one really good cigar. .… T.co

21hours ago

RT @EiR_TD: And on she goes after finishing the task at hand . #indiedev #gamedev #screenshotsaturday @EiR_TD T.co

21hours ago

RT @EiR_TD: Presenting the Krovan Medic administering poison or medicine in her own wicked way! #indiedev #gamedevT.co

21hours ago

Well, tough as she is battlefields have their pitfalls... . #indiedev #gamedev #screenshotsaturday @EiR_TD T.co

Dec 9 2017

On the rare occasion that she has nothing to do on the battlefield, she would really like one really good cigar. .… T.co

Dec 9 2017

And on she goes after finishing the task at hand . #indiedev #gamedev #screenshotsaturday @EiR_TD T.co

Dec 9 2017

Presenting the Krovan Medic administering poison or medicine in her own wicked way! #indiedev #gamedevT.co

Dec 9 2017

RT @RazorsEdge_org: I've never asked a favor but this tiny team went through a MAJOR upgrade (which almost killed them) to the new vers… T.co

Dec 8 2017

RT @EiR_TD: Our babysteps towards a decent UI continue, still lot to do, but again happy of the progress. #indiedev #gamedevT.co

Dec 8 2017

Friends
StellarAngel
StellarAngel Online
mcunha98
mcunha98 Online
adhikara13
adhikara13 Online
Galandil
Galandil Online
FenderXT
FenderXT Online
Kerringer
Kerringer Online
MohamedFS
MohamedFS Online
EnglishMuffinGames
EnglishMuffinGames Online
BlackSheepGames
BlackSheepGames Online
1gmshosting
1gmshosting Online