- Home /
Camera.WorldToScreenPoint and Camera.WorldToViewportPoint giving negative values why?
I am trying to make a simple UI system where a text object appears above an interactable object on the canvas. I am using an object clicking script off the internet to debug this. Everything works with the clicking, it finds the objects and finds their positions. However, when trying to use those positions as a parameter for Camera.WorldToScreenPoint or Camera.WorldToViewportPoint I get completely wrong numbers (often negative). Whereas from the description negative values shouldn't even be possible if I'm checking something within the viewport, right?
What I'm using to get the target position (debug)
if (Input.GetMouseButtonDown(0))
{
Ray ray = TargetCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform != null)
{
PushPrompt(hit.transform.position, "Prompt Here");
}
//custom function that gets a vector3 and a string which does the following
public void PushPrompt(Vector3 ObjectPosition, string Line)
{
PromptText.text = Line;
PromptTarget = ObjectPosition;
}
PromptTarget being a vector3 which is then used:
if(PromptText.text != null && PromptTarget != null)
{
Vector2 PromptPosition = TargetCamera.WorldToScreenPoint(PromptTarget);
Prompt.anchoredPosition = new Vector2(PromptPosition.x - TargetCamera.pixelWidth*0.5f, PromptPosition.y - TargetCamera.pixelHeight*0.5f);
}
All of this (if my math is correct) would work only if Camera.WorldToScreenPoint actually gave me values between 0 and screen resolution, but it doesn't. Please help, this is ridiculous.
Answer by Bunny83 · Jan 20, 2018 at 04:32 AM
Uhm your math doesn't make much sense to me. Why do you normalize the screen position you get back from WorldToScreenPoint? This doesn't make much sense. The resulting position would be on a quater circle around the lower left corner of the screen for any position within the viewport. Also keep in mind that you use the object's transform.position, not the actual point of the mouse. So it is possible to hit an object with your raycast whose position is not inside the view.
Keep in mind that ScreenSpace as well as ViewportSpace has it's origin at the bottom left.
Yes, sorry, the math isn't exactly correct (I was trying different equasions for hours, this was the last). But the problem isn't the math, the problem is that WorldToScreenPoint is giving me see$$anonymous$$gly random(but consistent) values (often negative) for objects that I clicked wihtin the camera's view- ergo by definition those should be somewhere between 0 and screen resolution.
So have you tried placing a Debug.Log statement after this line:
Vector2 PromptPosition = TargetCamera.WorldToScreenPoint(PromptTarget);
Debug.Log(
"Input: " + PromptTarget +
" Output: " + PromptPosition +
" \nCamPos: " + TargetCamera.transform.position +
" CamRot: " + TargetCamera.transform.eulerAngles,
TargetCamera.gameObject
);
What exactly does this print out? Also i added the used camera as context object. When you click on the debug message in the console, Unity should ping / highlight the camera object. So you know if you're using the correct camera. Can you copy and paste the result of this log from the console and post it as a comment?
ps: You haven't said what kind of camera you are using. Do you use an orthographic or a perspective camera?
Yeah, the camera (perspective, main camera, the only one in the scene) was fine. I gave up on this and here's why: I made some more debug scenarios, and came to the conclusion that WorldToScreenPoint doesn't do the thing it advertises. It simply just takes a 3D position, switches two values, multiplies everything by screen resolution, spits it out. (Or something along these lines) Bottom line: It doesn't actually tell you which pixel of the screen a ray from the camera to the target position intersects, it just translates one vector 3 to another. There go 8 hours of my life. Do you maybe know anything that can achieve the above desired effect?
Answer by Tion-Gaming · Mar 16 at 06:58 PM
Sorry to dig up an old thread, but for anyone else who is asking the same question, and confused, the WorldToScreenPoint function will return negative values because the point you are using is off of the screen. The viewport ranges from 0,0 which is the bottom right corner of the screen, to 1,1 with is the top left. If you divided the position by the resolution, you would get the pixel. Since unity needs to work for all sizes of resolution, it chooses to use this method of calculation. To achive what he wants, "Do you maybe know anything that can achieve the above desired effect?" He would just need to check to make sure the returned value lies between 0 and 1 on both axis, otherwise the point isnt visible and should be ignored. Then he should divide the point by the current screen resolution and bam.