- Home /
Orthographic camera with rotation and ScreenToWorldPoint
I have an ortho camera which used to have no rotation. When I used
ScreenToWorldPoint(Input.mousePosition)
I would get the desired result. I have a grid of tiles and I would use this to place a graphic over the tile that was under the mouse.
However, now that I have added some rotation to the camera, the selected tile isn't actually the one that is under the mouse. I realise that this is to do with rotation and some answers I have already looked at suggest setting the Z to the cameras near clipping plane like so:
Vector 3 mousePosition = Input.mousePosition;
mousePosition.z = Camera.main.nearClipPlane;
Vector3 position = Camera.main.ScreenToWorldPoint(mousePosition);
However, this doesn't work and produces the same results if I left the Z axis alone.
Answer by SteenPetersen · Feb 05, 2018 at 04:29 PM
Ok Here is how I fixed it in my Game hope this helps. Lassade was correct btw here is how you do it:
You need to spin up a plane so that you can cast a ray at it in order to determine what the distance is from the camera.
So in my game I have a -30 rotation on the X of the camera which is ultimately means the 'world' is further from the top of the screen than it is from the bottom. That means that if I want to shoot a projectile say at the mouse. I need to know the exact mouse click position.
What I did was spin up a Plane in the same position as my world and cast a ray at it to determine what distance it was from the camera.
// define a plane variable
// may be Vector3.up in your case depending on your camera orientation
Plane plane = new Plane(Vector3.forward, Vector3.zero);
// Shoot a ray at it when your event happens, in my case projectile
public void OnCastComplete()
{
var projectile = Instantiate(projectile, somePoint.transform.position, transform.rotation);
//Create a ray from the Mouse click position
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//Initialise the enter variable
float enter = 0.0f;
if (plane.Raycast(ray, out enter))
{
Debug.Log("distance " + enter);
//Get the point that is clicked
Vector3 hitPoint = ray.GetPoint(enter);
//Draw a debug ray to see where you are hitting
Debug.DrawRay(ray.origin, ray.direction * enter, Color.green);
// create a direction vector (hitPoint => somePoint
Vector2 direction = new Vector2(
hitPoint.x - somePoint.transform.position.x,
hitPoint.y - somePoint.transform.position.y
);
// addforce force to the projectiles rigidbody in that direction.
projectile.AddForce(direction * projectileSpeed);
}
}
Hope this clears it up a bit. This will certainly help in my game and it took me a long time to find the solution so I hope it helps others.
Answer by lassade · Jan 26, 2018 at 05:58 PM
I think you have an complex rotation on your camera, like in the one of a isometric game, in this case you should convert your sceen point to ray then raycast it on a plane (look at Plane class) or in the collider geomtry of your game.
Thanks for the info. The game has no colliders, each tile is just a sprite.
I have a very similar problem and cannot seem to fix it, trying to work on it at the moment will update if I find a solution.
Your answer
Follow this Question
Related Questions
Is there any way to create a fade effect in order to hide what isn't rendered by the camera? 0 Answers
3rd Person Camera clips through walls 0 Answers
ScreenToWorldPoint not working 1 Answer
Camera.main.ScreenToWorldPoint not outputting expected results. 1 Answer
Near clipping plane is different when game is maximized 0 Answers