How to place sprite above GameObject?
I'm attempting to place a healthbar sprite that maintains the same pixel size regardless of distance to the enemy above an enemy. I've attempted to position the sprite on the canvas at the screen coordinates that correlate with the location of the enemy, but the sprite is not at the correct location. This is my current code:
Vector3 screenCoords = mainCamera.WorldToScreenPoint(enemy.transform.position);
healthBar.transform.localPosition = screenCoords;
What am I doing wrong, and how can I fix it?
Answer by alankemp · Jul 19, 2017 at 10:00 PM
I assume when you say it is not at the correct location you mean its being drawn at the centre (or maybe bottom) of the enemy?
You need to add a height offset to the enemy position before you translate it to world space. How much is going to be based on your characters. If you know how tall an enemy is, use that. Or maybe you need to calculate the height based on the renderer or collider.
I tend to just add a member variable to my enemy class for the height offset and tweak it per enemy until it looks right.
float offset = enemy.HeightOffset; // for example
Vector3 screenCoords = mainCamera.WorldToScreenPoint(enemy.transform.position + offset);
No, by 'not at the correct location' I had meant that there is no clear relation between the location of the sprite and the location of the enemy. The two are often not even on the same side of the screen, or one could be on the screen and the other completely offscreen.
Answer by karma0413 · Oct 14, 2017 at 01:38 PM
First, check your anchor placement of the rect transform.. Then, check how you are scaling everything... UNDER: canvas / canvas scaler/ scale mode...
Know how those each function..... if your problem is similar to mine. Here is the solution... I finally figured it out.... i was having a simiar problem....
Quick Description of my problem: I was using the Canvas to display a sprite ( a healthbar) which floats over all the characters. The problem however, was when i tried to obtain the WorldToScreenPoint it kept giving a result that was slightly off.... for example: the healthbar looked a little okay when the character was immediately in front of the camera... but as the character walks to the edge of the camera's fulstrum, the screens x,y placement becomes more and more incorrect.
Days and days of research and trying different combinations finally showed me that maybe there is a scaling issue which pointed me to look at Canvas / Canvas Scaler / scaling mode: scale with screen
Originally, this worked wonderfully when i had only 1 character and his healthbar stayed stuck to the top of the screen like old classic double dragon games. BUT when i made the decision to have many characters and they all need "floating healthbars", i didnt come back to re-evaluate whether this option needed to change.
Setting the canvas Scaler to: keep constant pixel size , fixes the problem and i now have the correct WORLDtoSCREENpoint that i needed! And now the healthbar floats beautifully above the characters...
BUT WAIT, ANOTHER PROBLEM! Now, if the screen resolution is small... the Ui sprite is obsurdly large..... and if the screen resolution is high definition then Ui sprite is way too small!
QUESTION: So how do i use the "scale with screen size" mode, but yet also still get back a correct WorldToScreenPoint?
ANSWER: you must take into consideration the overal scaling of the canvas when it is stretched to fit (whatever current resolution that you are using)
INSTEAD OF:
RectTransform myRect = GetComponent<RectTransform>();
Vector2 myPositionOnScreen = Camera.main.WorldToScreenPoint (myOwner);
myRect.anchoredPosition = myPositionOnScreen;
YOU CALCULATE THE OVERALL SCALE FACTOR LIKE THIS:
RectTransform myRect = GetComponent<RectTransform>();
Vector2 myPositionOnScreen = Camera.main.WorldToScreenPoint (myOwner);
Canvas copyOfMainCanvas = GameObject.Find ("Canvas").GetComponent <Canvas>();
float scaleFactor = copyOfMainCanvas.scaleFactor
Vector2 finalPosition = new Vector2 (myPositionOnScreen.x / scaleFactor , myPositionOnScreen.y / scaleFactor);
myRect.anchoredPosition = finalPosition;
If this helped anyone please log in to give me a thumbs up....