Look at mouse on a spherical world
Hello guys. Im trying to make my player look at the mouse position while changing his rotation on the planet surface, but Im having problems. My goal is to combine the rotation on the Y axis (where the player is looking) and the rotation on the X and Z when moving on this sphere. rb stands for rigidbody, as Im using it to push the player towards the center of the planet. This is what I've done so far:
Vector3 gravityUp = (rb.position - position).normalized;
Vector3 localUp = rb.transform.up;
rb.AddForce(gravityUp * planet.gravity);
Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit floorHit;
if (Physics.Raycast(camRay, out floorHit, floorMask)) {
Vector3 playerToMouse = floorHit.point - transform.position;
transform.rotation = Quaternion.LookRotation(playerToMouse, gravityUp);
}
Quaternion rotation = Quaternion.FromToRotation(localUp, gravityUp) * rb.rotation;
rb.MoveRotation(rotation);
I changed a lot of things but none of them worked, except this one but the player starts to shake really hard and it leans forward when I have the mouse cursor near it. Any help would be really appreciated.
Answer by streeetwalker · Sep 05, 2020 at 07:49 PM
Hi @Fabio23000, interesting problem, but it's not clear in your description where your LookAt point actually is, and how you want the character to behave.
LookAt rotates an object such that the forward z axis points at the LookAt point. But I gather this is not what you want, because that will also pitch (tilt) the character on the X axis
First where is the LookAt point? In your code seems like you are projecting the mousePosition onto the planet.
From there I think you want to rotate the player on Y so that Z points in the direction of that projection without actually looking at it...
If so, I think trying to use LookAt will be more complex than finding the angular difference between the rotation of the player and the projection point, and use that to rotate the player.
Google "spherical triangles" to find the maths behind what I think you will need to do. I think that the player position and facing will define one side of the triangle
For example, define a spherical triangle with corners A, B, and C. Say the player is at corner A. Let C be your projection point. So AC defines the side of the triangle you want to rotate toward.
Let the segment AB define the side of the triangle the player is facing. Corner B is unknown, but you can chose any arbitrary point on the line defined by the direction the player is rotated - because all we are interested in is the angle between the sides. That said, of the calculations you will need to perform corner B is probably conceptually the most difficult to come up with, math-wise
Once you find the angle, it will be easy to create the quaternion to apply to your player's rigidbody.
All that is off the top of my head, but I think it will be the easiest way to do what you want. I'm sure there are other ways to do it, and perhaps there is another simpler solution someone else can come up with.
Thanks for your answer. This is what the script above does https://imgur.com/a/zvdURPj As you can see it kinda works but I can't "merge" the 2 different rotation, so it goes from one to the other and starts to shake. I hope this clarifies better what I'm trying to achieve.
Understood. Well no, your code does not really implement the algorithm I outlined. It approaches some elements of what the algorithm achieves. I think In essence you are trying to apply the rotation calculated from LookRotation and then use the result to compound the final rotation. One problem is the LookRotation is not actually applied to the rigidbody:
So, You have a conflict in trying to rotate the player's rigidbody and at the same time apply a rotation to the player's transform. If you are dealing with a rigidbody, you must use the physics engine API calls to perform all transformations.
The rigidbody component controls the transform of the object - not the other way around.
If you apply a rotation to the player's transform, the physics engine doesn't know about that. On the next physics engine update (just before the FixedUpdate message is sent) the physics engine will wipe out your transform change. You apply a rotation to the transform, but that does not rotate the rigidbody. That is why you get a jittering behavior.
(You also need to ensure all of the code that manipulates the rigidbody are in FixedUpdate - i'm sure you know that, but your code doesn't display it, so just to be sure.).
However, I'm not sure that is at the core of your problem. I'd have to think about it more. Perhaps your code will work if, instead of trying to apply a rotation to the player transform in the raycast condition block, you calculate the rotation and store it in a quaternion and then use that place of multiplying by rb.rotation in the line of code after your raycast in .
That said, I believe the algorithm outlined will give you a prefect solution.
I really appreciate your answer and explanation, but I can't seem to fully understand what you mean. Would you $$anonymous$$d writing a pseudocode? This quaternion/rotation thing is melting my brain
Answer by Rostes · May 17, 2021 at 11:55 PM
I am in the same situation except that I want to move my character to a Vector3 position generated by a raycast. My character rotates badly and spins like on the image shared by Fabio23000. https://imgur.com/a/JnkaLsi
If anyone has a solution, thank you very much!
Your answer