- Home /
Converting Mouse Position to World. Stationary Camera.
So I'm just trying to get my mouse position into a world position. I've seen a thousand answers where you Camera.main.ScreenToWorld(Input.MousePosition) it doesnt work. the value it returns is the same (the cameas position 10.5,25,10.5)
This is an overhead perspective not first person thing. So how do I get a mouse pos to become a world one?
Answer by robertbu · Sep 21, 2013 at 04:42 PM
Camera.main.ScreenToWorldPoint(Input.mousePosition) will not work. The issue that you are mapping a 2D coordinate to a 3D world. To make it work, you need to specify the distance in front of the camera as the 'Z' coordinate in the position you want to map. So for example if you wanted the position 10 units in front of the camera:
var v3 = Input.mousePosition;
v3.z = 10.0;
v3 = Camera.main.ScreenToWorldPoint(v3);
You say 'overhead' perspective. As long as you mean straight down, setting the 'z' parameter is easy. If your camera is at an angle with respect to the "ground," then you want to a different approach to map mouse position to world space.
Doesnt really work. I set it to ortho and perspective no change. Tried different Z's and the wrongness changed. Typically I'm registering a click 1 above and 2 to the right (3 world units up 6 over) though as i go more right it just is 1 up. This is on a chess board if that helps, I included the code.
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
//Debug.Log("Click registered");
//Debug.Log(Input.mousePosition);
Vector3 pos = Input.mousePosition;
pos.z = 20;
pos = Camera.main.ScreenToWorldPoint(pos);
ray = new Ray(pos, Vector3.down);
Debug.Log(pos);
if (Physics.Raycast(ray, out hit))
{
hit.collider.renderer.material.color = Color.red;
//Debug.Log(hit);
}
}
'pos' will be the world position under the mouse. But this is not a position you want to use for a Raycast(). Ins$$anonymous$$d:
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
hit.collider.renderer.material.color = Color.red;
//Debug.Log(hit);
}
}
Tried that for good measure, still the same innacuracie. The only tile that it hits right is tile 7,7 everything else is 1 up 2 over unless its on the edge (x,7) then its one up unless its 7,7. Top row its 2 over unless its within one space of the wall (6,7) then its just one over.
Tiles are 3x1x3 scale wise. Y is down.
The code I've outlined here is right. Not sure what is going on with your code. Are you sure your colliders are aligned with the visible objects? Use a Debug.DrawRay() to display your raycast.
.< thank you. Collider was scaled up 5,1,3. I thought i set it back but it was on a temp object not the prefab. Now it works as expected.
Thank you again.
Answer by Unity_scat · Jun 12, 2016 at 07:02 AM
I wanted to test this out but all code doesn't have "hit" defined. Please help.
I had the same problem, not sure if this is right but I just declared my own variable of type RaycastHit. I also declared ray as a Ray, not sure if this matters. Like this:
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
hit.collider.renderer.material.color = Color.red;
//Debug.Log(hit);
}
}
Answer by melsov · Mar 10, 2017 at 02:35 PM
This question is old but, in case anyone needs it, there's a way to do this without ray casts.
The last property gives the mouse position projected onto the transform.
private static Vector3 cursorWorldPosOnNCP {
get {
return Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x,
Input.mousePosition.y,
Camera.main.nearClipPlane));
}
}
private static Vector3 cameraToCursor {
get {
return cursorWorldPosOnNCP - Camera.main.transform.position;
}
}
private Vector3 cursorOnTransform {
get {
Vector3 camToTrans = transform.position - Camera.main.transform.position;
return Camera.main.transform.position +
cameraToCursor *
(Vector3.Dot(Camera.main.transform.forward, camToTrans) / Vector3.Dot(Camera.main.transform.forward, cameraToCursor));
}
}
By the way, this solution assumes that you don't care about the geometry of the collider. If you need a mouse point on a collider and the collider isn't a box that always faces the camera, use ray casts. This gives a point on the plane that contains transform.position with normal vector (transform.position - camera.position).
Is there a way to have it completely static so it can be called easily from a single script?
Answer by exvalid · Sep 08, 2018 at 04:03 AM
public Camera[] Cam;
public Camera cam1;
public RaycastHit RayHit;
public Ray ray;
public GameObject ObjectHit;
public Vector3 Hitpoint = Vector3.zero;
update ()
{
Cam = Camera.allCameras;
cam1 = Cam[0];
if (cam1 != null)
{
//Cast Ray from Camera through Mouse
ray = cam1.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RayHit))
{
ObjectHit = RayHit.transform.gameObject;
Hitpoint = RayHit.point;
if (ObjectHit != null)
Debug.DrawLine(cam1.transform.position, Hitpoint, Color.blue, 0.5f);
}
//Cast Ray from Camera through Mouse Ends
}
}
Hitpoint is your new World Coridinates of the mouse pointer. this casts a line from the camera through the mouse pointer. Rember tochange camera to your camera, this is straight from my script Enjoy Exvalid PS YOUR RECAPTCHA-VERIFICATION SYSTEM IS THE WORST THING IVE EVER HAD TO ENDURE IN MY LIFE TO MAKE THIS POST AND EDIT IT REMOVE IT AT ONCE ITS TERRIBLE FIRE WHOEVER MADE IT.
Your answer
Follow this Question
Related Questions
Space Flying Script Using Mouse 1 Answer
MoveTowards? 3 Answers
Place 3D plane in 2D? 3 Answers
Converting Type to SpriteRenderer/Image/Text 1 Answer
2D mouse aiming C# 2 Answers