CollisionShape3D offsets at runtime

Godot Version

4.6.2.stable

Question

Hey there! I’m starting to transition my project from Roblox to Godot, so far, I’m amazed at how many new features I wanted for a long time are already available in Godot!

One of them, is specific CollisionShape3D objects, currently, I have a very basic character made up out of 2 TubeTrailMesh to denote which direction it’s facing, with a Capsule CollisionShape3D.

Now, my problem is that, every time I play the project, while holding any direction, the CollisionShape3D is offset a random amount, without me making any changes to the script or the positioning of the Nodes.

As you can see in the screenshots, it varies from barely noticeable, to very dislocated, its also worth noting that functionally, the CollisionShape3D will go back to the correct position when pressing against another object, and so, this only happens when running without anything getting in the way.

Also, when the offset is particularly negligible, the CollisionShape3D also rapidly flickers from being further away and returning to being closer.

Here is my movement script:

extends CharacterBody3D

@export_range(1.0, 15.0, 1.0, “or_less”, “suffix:M”) var speed: float = 6.0
@export_range(1.0, 20.0, 1.0, “suffix:M/s”) var jump_velocity: float = 8.0
var max_jump = 30

@export var camera: Camera3D
@export var player: Node3D

func _physics_process(delta: float) → void:

# Apply Gravity
if not is_on_floor():
	velocity += get_gravity() * delta

# Handle Jump
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
	velocity.y += jump_velocity

# Get Direction
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
var direction := Vector3(input_dir.x, 0, input_dir.y).normalized()
direction = direction.rotated(Vector3.UP, camera.global_rotation.y)

# Move Player
if direction:
	velocity.x = direction.x * speed
	velocity.z = direction.z * speed

# Look Direction
	if velocity.length_squared() >= 0.1:
		player.look_at(position + direction + Vector3.UP)

# Slow Down
else:
	velocity.x = move_toward(velocity.x, 0, speed)
	velocity.z = move_toward(velocity.z, 0, speed)

# Actuate
move_and_slide()

# Quit Game
func _input(event: InputEvent) → void:if event.is_action_pressed(“quit”):get_tree().quit()

I suspect it has to do with the Look Direction segment, since it uses the Node3D where the player model is stored, however, the pivot for said Node3D is position in the center of the bigger tube, besides, if it was the culprit, the offset wouldn’t change each time right?

Anyways, thanks for reading my question, if you need any more details, feel free to ask! :information_source:

Post your scene structure.

Try copying the tube positions(x,y,z) to the CollisionShape3D positions(x,y,z) in the editor. Also am i crazy or the collisionshape isnt conected to the characterbody?

Alright, so, I added a few collision.position = player.position in the Move Player and Look Direction sections of the script, but the issue persists.

In the editor, the Node3D containing the player model is at 0, 1, 0 and the ColllisionShape3D is at 0, 1, 0 too, so they’re both in the same coordinates. (The TubeTrailMesh inside the Node3D is at 0, 0, 0, with the smaller one being at 0, 0, -0.5. Setting both to 0, 0, 0 also does not fix the issue.)

I tried removing the mesh so only the CollisionShape3D exists, and as you can see in the short clip, it still goes too far ahead while the movement itself works correctly.

I’m going to keep trying to remove parts until the issue gets fixed, I’ll update the post if I figure out a solution!

Here it is! Sorry for not directly replying earlier.

Seems like a fairly standard set up, you shouldn’t have to change the collision shape’s position in code, it’s more likely one of your nodes is offset and it’s affecting their children.

Is anything set to “Top Level”, this can behave poorly with other transforms.

Just checked and no, nothing is set as top level, also, after going trough my code, even after removing everything and leaving the default character movement script, the issue persists.

Did you change the process priority on any nodes?

look_at might be problematic? You can probably replace it with this line anyways, you can add an offset to angle if need be.

var angle: float = input_dir.angle()
player.rotation.y = angle

Another guess may be physics interpolation, do you have that enabled in project settings? found in “physics/common/physics_interpolation”

Oh yes, turns out I had left Physics Interpolation on from some previous tests haha, now it works correctly again! Thanks a ton, I’ll be sure to take notes on what I change in the future!

Cool! With physics interpolation it should only be a visual issue, you can leave it on if it stops bothering you. I’ve noticed rotation with physics interpolation isn’t great though, but it looks like you aren’t rotating the physics body (Player) anyways so you aren’t seeing those jitters.