Godot Version
v4.3.stable.official [77dcf97d8]
Questions
I’m using collide_shape
to proactively check if rotating my RigidBody3D
is going to cause a collision. If a collision is detected I want to adjust the rotation to stop the nodes overlapping (I still need them to collide, so signals are emitted).
I can’t figure out how to use the result of collide_shape
to adjust the angle correctly.
- How can I use the resulting collision vectors from
collide_shape
to adjust the rotation? - Is there an alternative method I could/should use instead?
- I’ve also added some questions as comments directly in the code snippet below
More details
I’m using a tween
to animate the rotation. This is done over a short timeframe 0.2
seconds, which results in a high move speed. This was causing my nodes to clip into each other and freak out. I’ve sort of worked around this by upping the physics tick to 120
, but this didn’t feel like a real solution. This is why I started looking into checking for collisions before rotating.
The reason I rotate the RigidBody3D
rather than using forces is because its frozen
and following a Path3D
. My entire game has been built around this and everything I’ve wanted to do so far seems to be working So trying to use forces isn’t going to be a viable solution, I’d basically have to start everything from scratch
This is hopefully the important snippets from my code.
# pivot is a Node3D being rotated
# _rigid_body is a RigidBody3D that is a "child" of pivot (technically a RemoteTransform3D is the child, but that is transforming the _rigid_body)
func _create_jump_tween(final_rot: float, on_finished: Callable) -> void:
_jump_tween = create_tween()
_jump_tween.set_process_mode(Tween.TWEEN_PROCESS_PHYSICS)
# Should I be using `pivot.rotation` or another method?
_jump_tween.tween_method(_do_jump.bind(pivot), pivot.rotation, Vector3(0, final_rot, 0), 0.2)
_jump_tween.finished.connect(on_finished)
func _collision_test(adjust: Transform3D = Transform3D.IDENTITY) -> Array[Vector3]:
var space_state: PhysicsDirectSpaceState3D = _rigid_body.get_world_3d().direct_space_state
var psqp: PhysicsShapeQueryParameters3D = PhysicsShapeQueryParameters3D.new()
psqp.shape = BoxShape3D.new()
psqp.shape.size = model.aabb.size
psqp.collision_mask = 0b1100
psqp.exclude = [_rigid_body.get_rid()]
# Is this the correct way to adjust the transform?
psqp.transform = Transform3D(_rigid_body.global_transform) * adjust
return space_state.collide_shape(psqp, 1)
func _do_jump(rot: Vector3, pivot: Node3D) -> void:
# Is this the correct way to get the rotated transform?
var end_transform: Transform3D = pivot.transform.rotated(Vector3.UP, rot.y - pivot.rotation.y)
var collision_result: Array[Vector3] = _collision_test(end_transform)
if not collision_result.is_empty():
var collider_position: Vector3 = collision_result[0]
var other_position: Vector3 = collision_result[1]
# What do I do with these results to adjust the rotation?
pivot.rotation = rot
Diagram
This is an example top down look of what I’m doing
- The blue rectangle is the node I’m rotating around the black circle pivot point
- The yellow is something in the way the blue rectangle should collide with
- The red cross is a collision result
collide_shape
is giving me back - The dotted rectangle represents the full rotation
- I know the width and length of the blue rectangle (
floats
) - I know the location of the black pivot point (
Vector3
) - I know the location of the red cross (
Vector3
) - I know the full rotation that would result in the dash rectangle (
Vector3
)
I feel like there is some trigonometry that would allow me to work this out but I just can’t figure it out, and I feel like I’m probably over complicating things…
Any help muchly appreciated as always!