Enter and Exit car with specific key

Godot Version

4.6.2

Question

Hello, I am newbie to GoDot and scripting in general, trying to learn through videos and trying to read documentation as best to my ability, and just experimenting with random scripts found through videos.

I was trying to make a vehicle in which I can enter and exit out. The problem I had was trying to

was with the Input.

If I use “ui_up” on the Input Action, I can enter and exit the car as freely as I can.

but when I use “interact”, I immediately enter, and exit the vehicle immediately.

I tried used print_debug, but I can’t still figure it out.

Here is the script for the car:

extends CharacterBody2D

@onready var car_sprite: AnimatedSprite2D = $CarSprite
@onready var car_collision: CollisionShape2D = $CarCollision
@onready var interactable: Area2D = $interactable



var speed = 200
var direction : Vector2
var active_player = false

func _ready() -> void:
	interactable.interact = _on_car_interact


func _on_car_interact():
	if active_player == false:
		_enter_car()

func car_input():
	if not active_player: return
	direction = Input.get_vector("left","right","up","down")
	velocity = direction * speed
	move_and_slide()
	
	#Problem (if "ui_up" is "interact"(E key), I enter and exit the vehicle immediately)
	if Input.is_action_just_pressed("ui_up"):
		_exit_car()



func _physics_process(delta: float) -> void:
	car_input()
	car_animation()


func car_animation():
	if velocity.y < 0 && velocity.x < 0:
		car_sprite.play("up_left")
		car_collision.rotation_degrees = -45
		interactable.rotation_degrees = -45
	elif velocity.y < 0 && velocity.x > 0:
		car_sprite.play("up_right")
		car_collision.rotation_degrees = 45
		interactable.rotation_degrees = 45
	elif velocity.y > 0 && velocity.x < 0:
		car_sprite.play("down_right")
		car_collision.rotation_degrees = -135
		interactable.rotation_degrees = -135
	elif velocity.y > 0 && velocity.x > 0:
		car_sprite.play("down_left")
		car_collision.rotation_degrees = 135
		interactable.rotation_degrees = 135
	elif velocity.x < 0:
		car_sprite.play("left")
		car_collision.rotation_degrees = -90
		interactable.rotation_degrees = -90
	elif velocity.x > 0:
		car_sprite.play("right")
		car_collision.rotation_degrees = 90
		interactable.rotation_degrees = 90
	elif velocity.y < 0 :
		car_sprite.play("up")
		car_collision.rotation_degrees = 0
		interactable.rotation_degrees = 0
	elif velocity.y > 0:
		car_sprite.play("down")
		car_collision.rotation_degrees = 180
		interactable.rotation_degrees = 180


func _enter_car():
	var player = get_tree().get_first_node_in_group("player")
	active_player = true
	player.queue_free()
	print_debug(active_player)


func _exit_car():
	var player = preload("res://scenes/objects/player.tscn").instantiate()
	active_player = false
	get_tree().current_scene.add_child(player)
	player.global_position = global_position
	print_debug(active_player)

The code works as expected from what i can tell, but im assuming a lot of things including that you’re using interact hotkey to enter the car? When you press interact, the input event runs and makes you enter the car. Active player is true. physics_process runs car_input which comes in and checks if it’s true, and it is. It checks if you just pressed interact, and you did. So it runs exit_car.

Why ui_up works is that you’re using two different hotkeys. When process runs and you go to the check for if you just pressed interact, the condition is failed, so you didn’t exit the car.

This is my best guess given the context.

1 Like

yeah, I tried to print debug when the functions ( enter_car_ and _exit_car ) are called for each keys.
so when I tried entering the vehicle for each key,

for “ui_up”:

true
At: res://scenes/objects/car.gd:80:_enter_car()

for “interact”:

true
At: res://scenes/objects/car.gd:80:_enter_car()
false
At: res://scenes/objects/car.gd:88:_exit_car()

if this is the case, I was wondering if you have any tips, or how do I make it so that I don’t call the enter and exit car functions at the same time?

You could create a timer in enter_carto delay setting active player to true.

1 Like

huge thankss dude, actually works really nice as well!

func _enter_car():
	var player = get_tree().get_first_node_in_group("player")
	#await timer
	await get_tree().create_timer(0.05).timeout
	active_player = true
	player.queue_free()
	print_debug(active_player)


func _exit_car():
	var player = preload("res://scenes/objects/player.tscn").instantiate()
	#await timer
	await get_tree().create_timer(0.05).timeout
	active_player = false
	get_tree().current_scene.add_child(player)
	player.global_position = global_position
	print_debug(active_player)
1 Like

I think you can also use await get_tree().process_frame(). But more fundamentally, im not sure if the interact to exit car should be called from physics process. I think you can consider trying something like..

func oncar_interact()
if not active_player: enter_car
else: exit_car.

This makes things very easy unless there’s some reason why the exit car needs to be in physics process due to other scripts.

1 Like

The process frame also works as well!

Also for that function, Ill take note of it