Godot Version
godot4.4
Question
i want to make an arcade car controller with a ball as the wheels but the mesh rotates with the ball i want the mesh to stay on the ground and not rotate i have been trying to fix this for a while but no results any help is appreciated
extends Node3D
@onready var ball = $"."
@onready var tank_mesh = $Tank
@onready var body_mesh = $Tank/Body
@onready var ground_ray = $Tank/RayCast3D
@onready var right_wheel = $Tank/Body/Wheel_front_right
@onready var left_wheel = $Tank/Body/Wheel_front_Left
# Where to place the car mesh relative to the sphere
var sphere_offset = Vector3.DOWN
# Engine power
@export var acceleration = 80
# Turn amount, in degrees
@export var steering = 15
# How quickly the car turns
@export var turn_speed = 6
# Below this speed, the car doesn't turn
@export var turn_stop_limit = 0.75
# Variables for input values
var speed_input = 0
var turn_input = 0
var body_tilt = 80
func _physics_process(delta):
if ground_ray.is_colliding():
ball.apply_central_force(-tank_mesh.global_transform.basis.z * speed_input)
func _process(delta):
if not ground_ray.is_colliding():
return
speed_input = Input.get_axis("brake", "accelerate") * acceleration
turn_input = Input.get_axis("steer_right", "steer_left") * deg_to_rad(steering)
right_wheel.rotation.y = turn_input
left_wheel.rotation.y = turn_input
if ball.linear_velocity.length() > turn_stop_limit:
var new_basis = tank_mesh.global_transform.basis.rotated(tank_mesh.global_transform.basis.y, turn_input)
tank_mesh.global_transform.basis = tank_mesh.global_transform.basis.slerp(new_basis, turn_speed * delta)
tank_mesh.global_transform = tank_mesh.global_transform.orthonormalized()
# tilt body for effect
var t = -turn_input * ball.linear_velocity.length() / body_tilt
body_mesh.rotation.z = lerp(body_mesh.rotation.z, t, 10 * delta)
if ground_ray.is_colliding():
var n = ground_ray.get_collision_normal()
var xform = align_with_y(tank_mesh.global_transform, n)
tank_mesh.global_transform = tank_mesh.global_transform.interpolate_with(xform, 10.0 * delta)
func align_with_y(xform, new_y):
xform.basis.y = new_y
xform.basis.x = -xform.basis.z.cross(new_y)
xform.basis = xform.basis.orthonormalized()
return xform.orthonormalized()