Hello Everyone,
(Still pretty new to Godot and game dev. Not great at maths either... what a combo).
Have read through a lot of other posts, but can't quite find something the same as my situation and not sure if I'm even going about this the right way, so would appreciate some advice.
I'm trying to make a simple top-down 3D scene consisting of a tank and a wall. The tank turret can be rotated/controlled separately to the tank. I had made something similar in 2D before and it automatically treated the tank and turret as one - there was no extra code required for collision detection / handling. I'm trying to achieve the same kind of thing in 3D, but struggling.


I have previously tried having a single KinematicBody for the Tank and using CollisionShape for the turret, but was not able to get the collision to register. I later determined this was because the CollisionShape was a ConcavePolygonShape.
I switched it out for many ConvexPolygonShapes instead, but the only way I could figure to have them rotate together as a single shape was to create a second KinematicBody for the Turret. That then allowed me to rotate the KB and add code to register collisions.

At this stage, I have turret collision / reaction working OK if it collides when either the turret or tank rotates, with this code:
extends KinematicBody
export var movement_speed = 1.5
export var rotation_speed = 1.2
export var turret_rotation_speed = 1.2
var rotation_dir = 0
var turret_rotation_dir = 0
var velocity = Vector3.ZERO
var acceleration = 0
onready var turret_body = $TurretBody
func _ready():
pass
func get_input(delta):
# Handle movement input.
rotation_dir = int(Input.is_action_pressed("tank_rotate_left")) - int(Input.is_action_pressed("tank_rotate_right"))
turret_rotation_dir = int(Input.is_action_pressed("turret_rotate_left")) - int(Input.is_action_pressed("turret_rotate_right"))
acceleration = int(Input.is_action_pressed("tank_backward")) - int(Input.is_action_pressed("tank_forward"))
velocity = acceleration * transform.basis.z * movement_speed
func _process(_delta):
pass
func _physics_process(delta):
# Check for input that will affect movement.
get_input(delta)
# Handle rotation/movement for tank body.
rotate_object_local(Vector3(0, 1, 0), rotation_dir * rotation_speed * delta)
velocity = move_and_slide(velocity)
var rot_collision = turret_body.move_and_collide(Vector3(0, 0, 0))
if(rot_collision):
turret_body.rotate_object_local(Vector3(0, 1, 0), (rotation_dir * -1) * rotation_speed * delta)
turret_body.transform.origin = Vector3(0, 0, 0)
# Handle rotation for tank turret.
turret_body.rotate_object_local(Vector3(0, 1, 0), turret_rotation_dir * turret_rotation_speed * delta)
var turret_rot_collision = turret_body.move_and_collide(Vector3(0, 0, 0))
if(turret_rot_collision):
turret_body.rotate_object_local(Vector3(0, 1, 0), (turret_rotation_dir * -1) * turret_rotation_speed * delta)
turret_body.transform.origin = Vector3(0, 0, 0)
func _unhandled_input(event):
pass
What I'm struggling with now is how to make the turret rotate away from the collision point if the tank acceleration causes the turret to collide with the wall. Without code to handle it, the turret gun simply slides into the wall.

Using Godot v3.2.3 on Ubuntu 20.04.4 LTS
Any suggestions or advice (especially if I'm going about this all wrong) would be much appreciated.