Can someone help me setting up a "local" gravity within a moving spaceship?

Godot Version

v4.6.1.stable.arch_linux [14d19694e]

Question

I’m trying to setup a game where:

  1. There is a Player, in a Spaceship, flying in Space
  2. So I have 3 scenes: Sector (has a Mesh for a planet, and a Spaceship), Spaceship (has a .blend of my spaceship with -col named meshes for automatic collision shapes), Player (CharacterBody3D atm) which is in the Spaceship, which is in the Sector
  3. The Player can move around the Spaceship and collisions work and this works fine
  4. I’ve not been able to find a way to move the spaceship without it spazzing out the Player

From what I’ve read, I think this is sort of like the Spaceship is a moving platform. I can “kind of” get this working, but when the spaceship rolls (for example) everything gets messed up.

So, I think I need to have a sort of “local” Y direction?

Is there a magic combination of nodes and gravity things that will make this work? At the moment, when the ship rolls for example, the “up” direction of the player doesn’t match and the player slides on the ground/walls or their movement is all whacky.

Other methods the player has phased out of the ship into space.

I’m thinking I might have to do all the physics myself manually?

Did you try parenting to the space ship?

1 Like

You need your player to be a child of the spaceship node to prevent this behaviour

My solution is to write a function that will put the player inside the spaceship when needed, and another function to put it out when needed (in case if the player can walk outside the ship)

As already said you have to parent the character to the spaceship for the hracter to move with the ship.

But still, the character’s up_direction will not update manually. (I added a suggestion about this on github, but probably won’t be implemented any time soon)
You can do something like this in the character’s script to make the character’s up_direction match the spaceship’s rotation, so the character won’t slide off when the ship rotates:

func _process(delta: float) -> void:
	up_direction = spaceship.get_global_basis().y

When the character jumps / falls, you can use -up_direction * 9.81 as the gravity you apply to the character to fall downwards.

(And the basic character controller is a little more complicated if you want it to work while your character is upside down with the spaceship, the default template godot creates for CharacterBody3D will probably not work)

Thanks all, I found a different solution:

I created a proxy version of the ship at the world origin. It’s not visible. The player walks around this proxy version which just has the collision shapes. The actual ship is then moved by the player in world space, rotated etc. The player’s camera is then kept in sync with the ship.

That way the physics of the player in the ship remain very simple. If the player docs, I just add a new proxy of the docked place on the proxy ship. Enemies can path find easily. Everyone has “local gravity” meanwhile their visual representations are floating about and the ships can all experience a different physics layer for smashing into each other.

4 Likes

Cool, I saw the same concept described by this guy here:

2 Likes

Crazy solution, good job!