So for the past few months on-off I’ve been trying to implement a controllable boat that the player can move on even while the boat itself is moving. Main problem is how the CharacterBody3D player gets the collision (or position) feedback from the boat.
To add commentary for the GIF: When I start moving the boat using the button, the player moves back, along with where they see other colliders (in this case the button). You can see me having to walk forward to find the button on a stopped boat. This push back is larger with higher speeds, to the point where I can walk a meter behind the boat seemingly on air. Similarly I can fall through the front of the boat. The boat itself detects collisions with StaticBody3D obstacles in the world without any visible problems.
I’ve ran into this problem first when I had the boat implemented as a CharacterBody3D. Current implementation that you see in the GIF is made with AnimatableBody3D with Sync to Physics being off (due to being unable to control it, otherwise). I’m also adding the player as a child of the boat’s main node as soon as they enter it to prevent sliding off. All colliders and meshes are children on the same level for both the boat and player.
func _physics_process(_delta):
var move_dir = Vector3.ZERO
var movement = Vector3.ZERO
if Input.is_action_pressed("move_forward"):
move_dir += global_transform.basis.z
if Input.is_action_pressed("move_backward"):
move_dir -= global_transform.basis.z
if Input.is_action_pressed("move_left"):
move_dir += global_transform.basis.x
if Input.is_action_pressed("move_right"):
move_dir -= global_transform.basis.x
move_dir = move_dir.normalized()
if not is_on_floor():
movement.y -= gravity * 20.0
else:
movement = move_dir * MOVEMENT_SPEED
# MOVE_AND_SLIDE CODE
velocity = movement
move_and_slide()
Any suggestions for an entirely new way to implement a controllable roamable moving platform is also welcome.
If you’re using move_and_slide for the player, try adding get_platform_velocity() to the player when they are on the boat. I haven’t tried this before, but that’s the only thing I see currently.
Thanks for the suggestion. I added get_platform_velocity() to the velocity used for move_and_slide(). While it seems like a better substitute for adding player as a child, I’m still getting the same “offset” behavior.
Hey @michaelgame_dev, I finally got back at chipping away at my project, and remote transform seems to ignore collisions and I couldn’t make it work. Which got me thinking, it might not be necessarily a movement problem but a collider behavior problem. So maybe my saving grace is using a rigidbody platform and a rigidbody player.
So far I got horizontal movement working (with some jittering and floatyness but I’m still learning about RB) and after some tinkering by adding platform global position to the player global position and a substantial increase of physics ticks, player seems to “stick” to the moving platform seemingly without any of the previous pushback (although the player is ever so slightly sliding back which could again be my lack of knowledge of the RB). If in the end that won’t work properly, I’m afraid I’ll have to look to other engines.
Ok, after A LOT of experimenting it seems that RigidBody would be the best bet. I don’t get the weird effect of offset collisions with it, however it has it’s own problems.
Like, for example, if player CharacterBody walks into anything on the boat (like railing) in the direction the boat is moving at some wrong moment - it pushes the boat into spinning (with angular velocity and all) and can even launch the player out of it while zooming away into the distance. I tried playing around with physics ticks, continuous collisions and making sure that only the player has the collision mask for the boat and not the other way around, and I still get this behavior. There’s also player sliding outwards if boat has torque added to it.
I guess I’ll either have to hope the player doesn’t get unlucky grinding on parts of the boat while it’s moving or I’ll have to create collisions and movements from scratch without using CB built in functionality. I’m not sure what to think. Is it some Godot physics engine jank that PhysicsBodies have two way interaction when I do everything in my power to make sure it’s only one way?
@azerty - I am working on a project with a very similar problem, and your post is the only one I’ve seen yet with the same issue. So far, I have also tried CharacterBody3D and AnimatableBody3D, with the same issues you describe. To clarify your solution, you kept the player character as a CharacterBody3D, and made the platform a rigid body 3d? do you have any updates on this solution? I considered, as it seems you did, rewriting the interactions almost entirely, but I feel like there is probably a better solution.
The best solution in the end turned out to be using Jolt physics engine and still going with CharacterBody3D and RigidBody3D as player and platform respectively. As far as I could test, no problems with moving platform collisions even if I add obstacles on it.
A shame nodes can’t be nested and have the player move relative to the platform.