• 3D
  • Player orientation and gravity for spherical planet

First some background on what I'm trying to do: I want to create a spherical planet the player can explore. The player is of course a KinematicBody who navigates with the WASD keys and looks around with the mouse. I'm generating the planet terrains using OpenSimplex Noise with no problem. However I need to figure out two challenging issues: Orient the player to always point toward the center of the planet and navigate relatively to it, as well as having gravity pull the player (and later other physical objects) toward this center. With flat plane terrain this is easy as you do everything on the global Y axis, for spider physics you need to figure out the direction and orientation manually.

First of all what I do have: I'm obtaining the direction from the player's origin to the center of the planet using var direction = (planet_origin - get_transform().origin).normalized() which itself seems to be correct. As far as player gravity is concerned, I'm temporarily implementing it the easy way by applying my velocity on its global_transform.basis.y... this works for characters as they have a fixed orientation, but won't be viable for objects that may have any rotation on all axes.

What I tried but failed thus far: rotation.x = -direction.z with rotation.z = -direction.x partly got my character to orient correctly with the planet from some angles, but it doesn't go all the way nor does it always get the direction right... clearly more conversion needs to be done on the direction, but what? Alternatively I tried using the builtin look function, specifically look_at(get_transform().origin + direction, Vector3(0, 1, 0)) which got me closer than other methods but is still rotating the player the wrong way. I'm also trying to avoid the look_at function because mouse input changes the player's Y rotation so I only want to edit the X and Z rotations without having the character's orientation overridden too.

What are the maths and GDScript functions I should be using? Both to orient my character so their feet are always pointing toward my desired Vector3 origin, as well as the velocity vector passed to move_and_slide to ensure the player always falls toward this origin? I played with every mixture I could find for hours but nothing gave the desired result.

@Bimbam said: I've not used it, but have you seen this plugin in the asset store? https://godotengine.org/asset-library/asset/631

Thank you: That looks like it should provide an answer, at least for the gravity part. Still need a solution to make the player also face toward the planet downward... tried look_at but for some reason it's inconsistent.

I'm fairly new so hopefully someone else can chip in, but one way I imagine it could be done if look_at is being funky (probably not the right way) is to fire a raycast from the kinematic body to the center of the planet; then reading the collision angle from the planets surface and rotating the player accordingly?

@Bimbam said: I'm fairly new so hopefully someone else can chip in, but one way I imagine it could be done if look_at is being funky (probably not the right way) is to fire a raycast from the kinematic body to the center of the planet; then reading the collision angle from the planets surface and rotating the player accordingly?

That sounds like an interesting suggestion. Perhaps a bit too complicated for something as simple as this though, it still seems simpler to just use the proper angles for the rotation math... the real issue is those angle maths are more complicated than I expected lol

I think you are on to something with look_at. Have you tried using the vector from the planet to the body normalized, as an up vector in that function call?

I think player movement can be done with cross product. Look_at() is good for aligning player's feet to the planet, unless you want him to be smoothly aligned(although then you could use look_at() with lerping).