See my answer below for the solution!
////////////////////////////////////////////////////////////////////////////////////////////////
Basically what I need is an algorithm which can calculate the Z value for the Camera.main.ScreenToWorldPoint, to get the projected position of the mouse position in 3D space.
The idea is to circumvent having to make 60 ray calls per second. And here is how it is supposed to work:
The Camera angle and the distance to the object are given.
I get the mouse position with
(Input.mousePosition.y - Camera.main.WorldToScreenPoint(transform.position).y)/Screen.height
This gives me values where 0,0 is the transform.position.
Next step would be to calculate the camera z projection values, which I failed to do.
Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance + [calculated mouse.y + something]));
If the camera would project orthographically, everything would be significantly easier.
The ray to the object can be calculated by
root(distance^2 + mouse.y^2)
but then the hard part is to figure out the green ray length (when mouse.y is positive), or violet ray (mouse.y is negative), which by adding/subtracting to the original z distance would give us the projection.
Any help would be greatly appreciated.
PS: And please let me know if I am making this to complicated and there is a nice and easy function which does this automatically (beside actual ray tracing
Description Update -----------------------------------------------------------------------------
Let me first describe what I am creating:
I am doing a Diablo style game, where the camera looks from a fixed angle down on the player. The player movement is controlled via WASD and the player orientation follows the mouse cursor.
The player rotation is achieved by calculation the 2D position of the mouse and subtracting those values from transform.position
// Mouse controlling rotation
Vector2 mouseP = Input.mousePosition;
Vector2 centerP = Camera.main.WorldToScreenPoint(transform.position);
Vector3 directionOld = new Vector3((mouseP.x - centerP.x), 0, (mouseP.y - centerP.y));
Debug.DrawLine (transform.position, directionOld, Color.red);
if (Quaternion.LookRotation(directionOld) != transform.rotation) {
float speed = rotSpeed * Time.deltaTime * RSPEED;
transform.rotation = Quaternion.RotateTowards( transform.rotation, Quaternion.LookRotation(directionOld), speed);
}
This works just fine, except if you are planing to implement some sort of long range combat. In that case you will completely miss your shots. (see picture segment1)
So this solution only works to make your character look in the general direction of where you are aiming.
Next I found out about that cool function Camera.main.ScreenToWorldPoint which gives you a vector which appears to be perfectly aligned with the mouse.
// Mouse controlling rotation
// Old
Vector2 mouseP = Input.mousePosition;
Vector2 centerP = Camera.main.WorldToScreenPoint(transform.position);
Vector3 directionOld = new Vector3((mouseP.x - centerP.x), 0, (mouseP.y - centerP.y));
Debug.DrawLine (transform.position, directionOld, Color.red);
// New
float heightM = (Input.mousePosition.y - centerP.y)/Screen.height;
Vector3 mouseW = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,
Input.mousePosition.y,
distance));
Vector3 direction = new Vector3((mouseW.x - transform.position.x), 0, (mouseW.y - transform.position.y));
Debug.DrawLine (transform.position, mouseW, Color.yellow);
if (Quaternion.LookRotation(direction) != transform.rotation) {
float speed = rotSpeed * Time.deltaTime * RSPEED;
transform.rotation = Quaternion.RotateTowards( transform.rotation, Quaternion.LookRotation(direction), speed);
}
(see picture segment 2 and 3)
As you can see the yellow vector appears to be aligned but it is actually parallel to the camera, which ultimately gives us an direction vector which is slightly off.
So now the solution would be to figure out a “value” which I can add to
Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance + "value"));
This “value” needs to be the length of the green/violet lines shown in the first schematic.
This would basically give me the correct representation of my 2D mouse position in 3D space (basically a projection), which I can use to get the true rotation of my character.
This method would be resource friendly (I think a calculated value is faster than an actual physical ray trace) and secondly, I would not have to rely on a flat terrain to get the rotation. Because here the we don’t get probes of the terrain but a calculation based on an virtual plane.