• Register

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

RSS My Blogs

Tooltip system on uGUI Unity 4.6

DrHogan Blog

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

Juggernauting the gamedev

DrHogan Blog

Work goes one, EiR grows day by day, it's amazing to witness that. The work on the tactical map already begun, and the research system is almost complete, even starting to have a temporary GUI now.
The single maps engine has been completely rewritten and it's now 100% more robust and flexible than before.
We're here guys, we're doing it, we won't stop!

Cheers!

The long, long way : On quality vs quick rushes (and Kickstarters)

DrHogan Blog

This last month, according to a few months old plan and timeline, we were all hype on "yeah, let's kickstart EiR and get money to pay the people we want to work for us".

I now realize how naive that was.

We think we are developing a high quality product, with very robust and optimized code in the engine, top-class graphics and a solid design featuring intriguing gameplay traits, about that we have no doubt.
It is not about boasting, but we are really putting a huge effort in have the above mentioned properties shining in our game. We also think that although this is the first independent game we work on, for ourselves and not for some imposed specifications from above, we have the technical experience to get something very nice out of that.

Given this premise (maybe then when we will delivery, people's opinion will prove us completely wrong, it might happen, but the little feedback received so far sounds promising), let's go back to the initial sentence : "oh, we kickstart".

True, experience is the best teacher, but as nobody was born experienced, we need to make our bones on that. So we spent the last months reading (a lot), discussing (a lot) and asking questions here and there (a lot) to understand what and how.

Kickstarter is a beautiful weapon, let's say a BFG9000 (for who gets the citation). It has only one little flaw. It has one bullet only. So if you aim unprecisely, or shoot in a moment in which no huge crowd of cacodemons is preparing to charge you, you just waste it. And then it's gone ( I don't believe in a second KS try, at least not in a short term).

So we took a look at Empire in Ruins (my preciousss!) and we coldly dissected it, to see what we have and what we don't. And I am talking of one year of semi-part time work (bills don't get paid by beautiful gamedev nights only).

  • We have a setting for the game. It comes from a book i am writing since a while (620 pages and going). not saying it is the most beautiful and creative setting ever (even though i hope it is), but that means that i spent 2 yrs thinking on it, so i know habits and costume of every single of the populations that live in it (in setting-building having been a DM in D&D for years is an invaluable tool).
  • We have a design. We know exactly how the game is and is gonna be structured, which features will be available and where the gameplay is gonna be focused.Not saying that it's never gonna change, but the plan is clear in mind and on doc files.
  • We already have most of the basic engine for a single map
  • waves and path system (newly rewritten, featuring also forests,water,amphibian, tunnels, flying,dynamically opened paths, etc etc, i am writing a journal entry about it but it's taking days)
  • units movement/animation/death/all functions
  • building and mouse interaction system (you can sneak a peek here Goo.gl )
  • towers shooting/best enemy targeting/special abilities (flaming arrows, clouds of smoke, throwing nets, caltrops, boiling oil, etc etc)
  • good-quality graphics for a single map demo (at least for terrains and towers)
  • We have, almost ready, a 4 minutes original song recorded and processed by a real band (Red Dew Hellpipes, doomish military metal with bagpipes)
  • We have a couple of sketches that demonstrate the skill of the illustration artist we will contract with the KS money.

Do you think all that is enough? After long long thinking, we decided that it's not.

First of all, I am absolute believe of the fact that a project shouldn't hit KS if it looks already complete or almost. I mean, why to ask money to produce something that you already produced?
But.
First of all you have to show some high quality stuff (bit of graphics, bit of video footage, bit fo drawings), to show that yes, you have a pool of skill available from which to draw what's necessary for a high quality product. And we think we are very close to that.
So what's missing?

Gameplay. People want to see a bit of all the gameplay features you will offer in the final game. Not finalized, but looking good, looking functional, looking interesting. Looking teasing.

In EiR for example we wanna put a large focus on two things that are not just the single TD map :R&D and tactics. (and RPG elements, but I will keep this for another entry of the journal)

An example of what the design states :
"The tactical map from which the single maps can be accessed is structured in regions. Each region has specific traits (e.g. forest regions, if developed, will confer a bonus to wood production during the fights in adjacent territories or on longer ranges depending on the development of the logistic system). Once a region has been conquered, mainly according to the plot flow (in several cases not only a single battlefield is open), it is up to the player to develop it and fortify it so that the enemy AI will not strike back, removing the region from the player's control"

Is this an appealing feature that might differentiate EiR from traditional TD games? We definitely think so.
Can we show that? No
Why not?

Because I think that development and showing off don't fit together. You don't rush superficially through features development only to have something to show off. I saw a few days ago a pic of of good old Bill Gates with the caption "It compiles?Ship it!".
Such a large game as we are developing (large for an indie company at least) implies a slow, accurate (to a level of paranois), modular development.

You start from medium-small components (a single map for example), then, keeping everything as modular as possible (you think you did it modular? probably is not modular enough yet), you build it. Feature after features, line of code after another. You develop the small component, you test it endlessly, then you declare it done and go with the next. And then you test the interaction over and over, and find all those if(...) cases that might arise in special situations and you solve them. And this way you go on, with a solid, robust, massive engine under your feet.

And if everything was done to perfection, a miracle will arise, a miracle called Emergence. (check this out Goo.gl

The one above about the tactical map is just an example among many, but the summarized moral is : don't do it quickly just to show it, and if you don't have it, don't rush towards showing it but take your time and do it well. It will pay off in the end.

Now my delirium of words, might be probably confused, ill-formed and emotional in its own way, but expresses my feelings about it, and the reasons why we decided to delay by at least two months our KS campaign.

Additionally, for exposure, if you sorta liked what I wrote, you could help us in enlarging the vital user base (that one also still too small in our case for KS and additional reason to decide to delay) and follow us on twitter or FB and retweet some of our stuff. If you don't like,
respect anyway that you got to read it until the end.
Twitter.com
Facebook.com
As usual, if I didn't want any comment or opinion I wouldn't have wrote all this publically, so feel free to comment. The meaner the more useful it will probably be.

Cheers,
H

Tower defence - Static Vs Dynamic building

DrHogan Blog

When we sent the link of our pre-pre beta release to several friends that were not into Tower Games, the first feedback was always the same : "cool...but well, a bit static...".In that version of the game, towers were being built automatically on click (Build Tower button - Choose position - Click - Tower built and fully working). While this is quite traditional for TD players, i get it that somehow seems unnatural for people otherwise used to RTS games.We want to keep with us all the traditional TD followers, but why not making a game that can make more people happy?So approx ten days ago, i backed up all the code, and went for a deep refactoring of the building system. What i decided to add was the following :
A limited amount of workers will be available on the map (their number depending on the skills of the player. They will leave from the castle (or from the workers tent when this building is available due to research and closer to the construction site than the castle) and walk until the construction site.There they will build the tower in a certain amount of time (progress shown by the building bar beneath the tower) and then come back to the castle.Construction sites are queued when the amount of builders available is smaller than the amount of sites.But then we decided to add some spice to it. Builders can be killed by passing too close to incoming enemies, therefore they try to avoid paths as much as possible, and in case of death, they will respawn in a certain time (unless the player spends some resources to make it instantaneous). The builders stats can be increased through research and skills.

Building system implemented - 2 Building system implemented
Now, what do you think of this concept? So far in the test it performed beautifully. We think it gives much more importance to the time between waves (so sometimes now skipping that time for money ain't worth anymore), it forces the player to develop a much more interesting building plan, and brings somehow the game to a level of vitality that was missed before.

Additionally, unlocking the builders tent becomes a very important achievement of the game, and increasing the number of workers and their skills (hp, speed and working time), gives additional interesting features for the research.
Any comment on it?

Video-game immersivity - Not only a feature for Virtual Reality environment

DrHogan Blog

Imagine watching a movie, and suddenly something in the movie looks obviously fake.
Doesn't it cause on you a sudden redrawal from the immersion in the scenes of the movie and back to reality?Don't you suddenly stop thinking on the scene you are watching a part of the story but as a fake scenery only. If so, your immersion in the movie has just been broken.Sometimes even a small detail is enough to break the spell : a piece of scenery looking wrong, a CGI background unnaturally strange, a modern watch on the wrist of a medieval knight. It doesn't matter what it is, but the magic is gone, and you find yourself staring at something instead of being inside it as a few seconds before.
Games are not much different. If every single detail fits correcly with the others, if no flaw pops out to bother that part of your brain that notices that kind of things, you will forget everything around you, spending hours in a world of pixels that for a while will be your world. But then, a couple of single flaws can break the spell as in the movies, kicking you out from the virtual environment and back behind your keyboard.Now, if the concept absolutely is vital in Virtual Reality (CAVE-like systems or HMD), that holds as well for any other game.
You are trying to capture the player focus completely, to grant him a full immersion on your game, and this concept applies in similar ways to tetris and to high-quality graphics FPS.Don't think that it depends on the quality of the graphics only, it is a much more complex phenomenon, emerging from the full synergy of the game features, even more sensitive because it can be easily ruined by any of the involved factors.
Given the above introduction, let's now focus on the specific way we are taking this into account in designing the engine and the graphics of our Empires in Ruins. Don't take it as manual of instructions, but more as food for thought you have to consider when being in the first stages of your design.I think the problem is easier to describe by pointing out what might disrupt the immersivity. And mind this, the following list is far from complete, but should be enough to give a first overview of the topic. Most probably most of you already know all this, many others know it but never thought about it in detail, anyway writing it down is also helping me in tidying my mind up ;) )

  • Animations/Game Speed - Do you really want your soldiers doing some sort of oily moonwalking when their speed on the path is much lower than the animation speed. I think this says it all...
  • Graphics quality and coherence - Quality means quality in the type of graphics that you chose. It can range from even really simple pixelart to high-res rendering as we use in EiR, but it has to be nice, and above all, the whole thing has to be coherent. Sounds obvious, but apparently not always it is.
  • Visual feedback. Be Newtonish : For every action there is a (...) reaction. Skipping the "equal and opposite" from the quote, still goes to the point. Everything needs visual feedback, also small details. Takes longer to implement them? Well, you aren't going for speed if you are reading this, you are aiming for quality. Example, the arrow hits an enemy? Show blood, make the enemy skill blink in red and/or shake a bit too etc. A catapult hits in the middle of a crowd of enemies. Is blood enough? I went through it, and nope, it couldn't look any faker if you don't "shake" the units too, pushing them in the opposite direction of the impact too. The enemy dies, should its sprite just disappear or are we going for a decent even if short death animation? You answer.
  • Proportions. What is the point of modelling really nice looking enemy units if then on screen they are 2 mm high? You want them a bit bigger, of course, to show off your graphics, but then if you make the towers proportional to it, they probably fill up the full screen and bye bye to playing the game. So what? An example (nothing new, Age of Empires got there much before). Make them disproportionate, but cheat the player's eyes with some tricks. An example we used is that the units are definitely larger than the towers proportionally, but the doors of the towers, that is the element next to which it will be possible for our eye to do the comparison, have the same proportion as the units. Believe me, a simple trick like this does miracles already.
  • Audio - This is quite sensitive as well. Enough audio is vital. Too much might be annoying. True, a battlefield is a loud chaotic place, but don't you think that too much sound would rape the ears of the player. Go instead for a smarter balancement. Try a simple trick we are implementing by using 3d sound on 2d game. Camera all zoomed out, lower sounds, some of them (like the dying of a unit), you can probably silence completely. Then when you zoom in, localized sound gets louder (only for the area of interest). Requires some tricks to simulate in 2D but nothing that can't be done (hint, create a probe object that moves around according to the camera).
  • 3D Prospective in 2D - This is a painful chapter, one of the ones that requires more thinking and has a larger impact on the results. First of all, you are simulating a 3D-ish world on a flat plane, every single detail can immediately make your scene look like a drunk Picasso drawing, and not one of those that got famous.
  1. First of all. Depth-buffer. If you don't plan to simulate this, don't even start. The game elements "lower in the screen" will have to be in front of those "higher in the screen". Might requires some painful tuning for each sprite, but you can't skip this. Forget about having your terrain all in a single image, unless it is a flat surface with no props or stuff. Depth is vital for the brain.
  2. Remember that speed of movement has to become "perspectivized". In simple words, if you want a realistic behavior, the on-screen vertical movement speed has to be lower than the horizontal one. Just a bit of map will do the trick, but don't ignore it. (I mean, if you have circular areas of effect that get squeezed into ellipses due to perspective, wider than higher, shouldn't the units employ the same time in crossing them vertically or horizontally? food for thought, but yes they should).
  3. Projectile trajectories. Here comes the math. This can sooo easily look wrong. They need two things, rather three things. First, write the formula for the real 3D trajectory (usually a parabola does the trick well enough). Second, transform the formula from 3 dimensions to 2 dimensions (ain't that nasty if you have hold of the math for it). Third, make the projectile realistically alive : change the rotation according to the trajectory, and play with the size. An object closer to the camera should look bigger than one further from it. This last trick, if well managed, can give a lot of realism to the effect.
  4. You're not in a lovely 3d environment taking care of generating all the shadows nicely by himself. But you need shadow to avoid the game looking flat and fake. How to solve it as 2D sprites don't seem to like to project shadows on other sprites? Simple, you have the shadows on the sprites, but (huge BUT here), remember this : your shadows will not bend and model themselves after the terrain and other sprites, so KISS (keep it simple and stupid, not KISS like in Rock'n'roll all nigh and party every day). Small smooth shadows might be less impressive than longer thicker ones, but will have a much higher flexibility in adapting to the 2D scene.
  5. This is important. By implementing a 3D world in 2D you are "cheating", remeber this. Cheat coherently and thing on gameplay. A couple of degrees changes in perspective among some elements might not invalidate the graphical look of the scene, but might do miracles for the gameplay. One example, our towers perspective has a slighly different view angle than the map. Why so? Because if they had the same, our towers would look too "tall" and hide too much of what's behind them. This is a very sensitive part that is usually solved by testing directly and validating visually.

Now well, I don't feel like I unveiled any absolute truth, but i hope it might be a decent thinking guideline for someone approaching for the first time the problem.Much of what i described can't yet be see (we worked so far for some months on the core engine, and that's something you don't see until you play it, and we think we're doing well on that), but believe me, is the topic of endless brainstorming and talks between me and the graphics artist, cause everything is being built according to those guidelines i defined above and more.Cheers,dr.H