Trying to make simple vehicle (CharacterBody3D or AnimatedBody3D following Path3D) however another CharacterBody3D (player character) is never stable standing on such moving platforms. It slides and moves around eventually falling off.
Scene and code setup
Platform in video is ‘Car’ which is simple CharacterBody3D with basic movement script.
AnimatableBody3D is another test, it was suggested to use this for moving platforms but its same issue. Tried all the friction settings too
Character controller.gd
extends CharacterBody3D
const SPEED = 4
const JUMP_VELOCITY = 4.5
var last_angle = 0
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity += get_gravity() * delta
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
var input_dir := Input.get_vector("left", "right", "forward", "backward")
var world_direction = transform.basis * Vector3(input_dir.x, 0, input_dir.y)
var direction = world_direction.normalized()
#quick test in how to keep rotation with vehicle
var angle_change = $"../Car".rotation.y - last_angle
last_angle = $"../Car".rotation.y
$Humans_Master.rotation.y += angle_change
if direction:
velocity.x = (direction.x * SPEED)
velocity.z = (direction.z * SPEED)
$Humans_Master.rotation.y = lerp_angle($Humans_Master.rotation.y, atan2(input_dir.x, input_dir.y), delta * 12)
else:
velocity.x = 0
velocity.z = 0
$Humans_Master/AnimationTree.set("parameters/conditions/idle", input_dir == Vector2.ZERO && is_on_floor())
$Humans_Master/AnimationTree.set("parameters/conditions/run", input_dir != Vector2.ZERO && is_on_floor())
move_and_slide()
minimal vehicle controller.gd
extends CharacterBody3D
@export var gravity = 0
@export var wheel_base = 2
@export var steering_limit = 10.0
@export var engine_power = 6.0
@export var braking = -9.0
@export var friction = -2.0
@export var drag = -2.0
@export var max_speed_reverse = 3.0
var acceleration = Vector3.ZERO
var steer_angle = 0.0
func _physics_process(delta):
get_input()
apply_friction(delta)
calculate_steering(delta)
acceleration.y = gravity
velocity += acceleration * delta
move_and_slide()
func apply_friction(delta):
if velocity.length() < 0.2 and acceleration.length() == 0:
velocity.x = 0
velocity.z = 0
var friction_force = velocity * friction * delta
var drag_force = velocity * velocity.length() * drag * delta
acceleration += drag_force + friction_force
func calculate_steering(delta):
var rear_wheel = transform.origin + transform.basis.z * wheel_base / 2.0
var front_wheel = transform.origin - transform.basis.z * wheel_base / 2.0
rear_wheel += velocity * delta
front_wheel += velocity.rotated(transform.basis.y, steer_angle) * delta
var new_heading = rear_wheel.direction_to(front_wheel)
var d = new_heading.dot(velocity.normalized())
if d > 0:
velocity = new_heading * velocity.length()
if d < 0:
velocity = -new_heading * min(velocity.length(), max_speed_reverse)
look_at(transform.origin + new_heading, transform.basis.y)
func get_input():
var turn = Input.get_action_strength("steer_left")
turn -= Input.get_action_strength("steer_right")
steer_angle = turn * deg_to_rad(steering_limit)
$"Back 1".rotation.y = steer_angle*2
$"Back 2".rotation.y = steer_angle*2
acceleration = Vector3.ZERO
if Input.is_action_pressed("accelerate"):
acceleration = -transform.basis.z * engine_power
if Input.is_action_pressed("brake"):
acceleration = -transform.basis.z * braking
Ignore cam jitter (another problem cant solve with smoothing addons or interpolation)
See how character slides left side and right side when turning and it slowly slides backwards eventually falling off at the end. During driving player character velocity is 0.
Is there a way to make character perfectly stable on such platforms while retaining ability to still move around on it while its moving?