Initially position RigidBody3D in Godot 4.4.1

Godot Version

4.4.1

Question

Hi,

I’m having trouble initially positioning a RigidBody3D object via code. I’ve read up on it as much as I can and tried various approaches. The prevailing wisdom seems to suggest that because it’s a RigidBody3D you can’t just change the position, you need to do it as part of _integrate_forces. I’ve tried this, and what’s odd is that it seems to work if I set the initial position to be not too far from Vector3.ZERO (such as Vector3(10, 1, 10)), but if I set it to something farther away I get a strange effect where the object “bounces back” to its original position.

I’m using DAShoe1’s excellent Godot-Easy-Vehicle-Physics template project as a starting point. In demo_arcade.tscn the vehicle’s initial position is Vector3.ZERO.

The changes I’ve made to his code are as follows. I add a top level variable in vehicle.gd like so:

var teleport_position : Vector3

I then update _integrate_forces so it looks like this:

func _integrate_forces(state : PhysicsDirectBodyState3D):
	current_gravity = state.total_gravity # <-- Not added by me
	if teleport_position:
		state.linear_velocity = Vector3.ZERO
		state.angular_velocity = Vector3.ZERO
		state.transform = Transform3D.IDENTITY.translated(teleport_position)
		teleport_position = Vector3()

And then I attach a script to ArcadeDemo at the root of the scene with the following code:

extends Node3D


func _ready() -> void:
	# Setting the position to the value below seems to work as expected.
	# $VehicleController/VehicleRigidBody.teleport_position = Vector3(10, 1, 10)
	# But setting it to this, we end up with the vehicle being moved to that
	# position, and then something moves it "back"?
	$VehicleController/VehicleRigidBody.teleport_position = Vector3(50, 1, 10)

If I uncomment the first portion and comment the second it works fine, but with the second one uncommented there’s a weird “bounce back” effect. I’ve created all this in a repo that can be downloaded to easily reproduce the issue.

Many thanks for any help.

Tom

Concerning the physics engine, you should avoid touching the node3d transform when the physics class is in the tree. The reason is that the physics engine is responsible setting the position after its simulation has ran. There are basically two positions being maintained for one object, the scenetree transform and the physics server transform. So it becomes imperative that you modify the position in the correct context.

when initially positioning a node do so before its added to the scene tree and use a relative offset from its parent by adjusting the local position.

I have had success manipulating the direct body state in the physics process without issue, for multiplayer synchronization, instead _integrate_forces

This looks sus.

You should probably update the prevoius_global_position if teleport is used otherwise you will probably get some nonzero velocity after teleport

Awesome, thanks so much!

Basically I removed my changes to _integrate_forces and updated the beginning of _physics_process like this and it works nicely:

func _physics_process(delta : float) -> void:
	if not is_ready:
		return
		
	if teleport_position:
		global_position = teleport_position
		previous_global_position = global_position
		teleport_position = Vector3()