- Home /
ScreenPointToRay question
Hey guys... I'm utterly stumped on this so hoping for some guidance.. Generally when I can't find the answer online I'm doing something fundamentally wrong but I'm not sure what that is, so here goes:
I'm working on a FPS style portion of the game, where the game camera is attached to a GameObject that is being moved, rotated, etc etc. I'm using NGUI for the HUD portion and a part of that has a targeting system where an NGUI reticle moves on the GUI to track towards a bad guy on the screen. Imagine an auto turret that can't move as fast as the target, so it's working to keep up but if the target is constantly moving it's often a little behind etc etc, and this reticle indicates where a shot would go... the player's best chance of hitting the target is to get the reticle on the bad guy. Hopefully that's clear.
I wrote a coroutine to be periodically called to test whether the reticle happens to be over the bad guy, and figured Ray Casting was the best way to do this, only the ray cast doesn't seem to be going straight out of the camera into the game world as I expect. I'm currently using Debug.draw to see where it's going and it's off at a weird tangent from the camera. My unityscript code looks like this:
function initRaycast() {
//An experimental function to see if I can determine that a raycast has hit the bad guy periodically... the ray cast will use
//the position of the crosshair as a basis and raycast out to it.
while (true) {
if(current_target != "none") {
//var the_pos : Vector3 = gui_camera.ScreenToWorldPoint(crosshair.transform.localPosition);
var the_pos : Vector3 = gui_camera.ViewportToWorldPoint(crosshair.transform.localPosition);
Debug.Log("Position of the NGUI Component : " + crosshair.transform.localPosition);
Debug.Log("Position converted through the camera : " + the_pos);
var the_ray : Ray = gameCamera.ScreenPointToRay(the_pos);
var hit : RaycastHit;
//Debug.DrawRay (the_ray.origin, the_ray.direction, Color.green);
if (Physics.Raycast(the_ray, hit)) {
Debug.Log("THEORETICAL: We hit this : " + hit.transform.tag);
var target_pos : Vector3 = hit.point;
var source_pos : Vector3 = gameCamera.transform.position;
Debug.DrawLine(source_pos, target_pos, Color.green, 5);
}
else {
Debug.Log("THEORETICAL: Missed");
}
}
//and pause
yield WaitForSeconds(0.5);
}
}
When I run this rather than seeing the debug line in the editor project straight from the camera down a Vector consistent with where the reticle is it is instead shooting more or less off at a 90 degree angle from the cameras view and into the ground. From behind the camera looking down the game world in the editor I wouldn't expect to see the ray as more of a dot going into the distance, instead I see it going into the ground, where if 0 degrees was a point directly above the camera, 180 degrees directly beneath the camera, the line goes out at like 200 degrees, into the ground, not away from the camera in the direction I need at all...
The debug code on my position translation from the NGUI camera to the game camera appear to be working based on the numbers I'm getting dumped into the console, so I'm happy with that.
So I guess my question is; is my understanding of what ScreenPointToRay does completely off?
I'm wondering if I need to do something to the ray.direction to tease it into going where I want? The alternative approach to this that I'm toying with is taking the reticle position and the same logic I already have for tracking the bad guys position on the GUI and doing some comparison logic to see if there's an acceptable delta between the 2, but Ray Casting seems like the best hammer for the job.
I welcome any thoughts either way. :)
Thanks all! Greg
Answer by steakpinball · Jan 14, 2015 at 09:23 PM
You have the right idea. The issue you're having is trying to use the target world position as a screen position.
var viewportPosition : Vector3 = uiCamera.WorldToViewportPoint(crosshair.transform.position);
var theRay : Ray = gameCamera.ViewportPointToRay(viewportPoint);
Line 1 takes the position of the crosshair in the world and converts it to the position in the viewport. Say the crosshair is in the center of the screen, the viewport point will be (0.5, 0.5, 0)
. The z
value will be the object's distance from the camera.
Line 2, takes that viewport position and uses it as the starting point of the ray from the game camera. The ray will cast out from that point on the game camera.
I don't have the reputation to upvote this, but it is the correct answer, so anyone who stumbles upon this who can upvote it, please do!
Thank you brianturner for the quick response, I'm finally registering hits and the debug lines for the rays are originating and heading in the right direction. This whole area is a little confusing and I clearly need to do some more reading around it but at least I'm ungated. Cheers
Your answer
Follow this Question
Related Questions
Raycast hit not detected on cube 1 Answer
Use layer name for LayerMask instead of Layer number for ignoring collideres while RayCasting 3 Answers
How to Detect the Number of times a raycast intersects a Mesh 2 Answers
How can i find Next and Previous Child ? 1 Answer
Shooting towards mouse cursor 2 Answers