Wait() function refuses to work even though evidenced to work perfectly fine in other projects

Godot Version

4.5

Question

I’ve talked to my friend who uses godot all the time, I’ve checked several tutorials, they all say that this function is correct

func wait(seconds: float) -> void: await get_tree().create_timer(seconds).timeout

I’ve used it in this here, the reason the wait is at 0.5 is to make a gap more obvious if it were to actually work.

func _process(_delta: float) -> void:
	var gameWidth: float = get_window().get_size().x
	var mousepos = get_viewport().get_mouse_position()
	#var mousex = mousepos.x
	#var camy = neck.rotation.y
	
	if able_to_turn and mousepos.x > ((gameWidth/10)*9):
		print("turnright")
		for i in range(9):
			neck.rotation.y += deg_to_rad(10)
			wait(0.5)
		able_to_turn = false
	elif able_to_turn and mousepos.x < ((gameWidth/10)*1):
		print("turnleft")
		for i in range(9):
			neck.rotation.y -= deg_to_rad(10)
			wait(0.5)
		able_to_turn = false
	
	elif mousepos.x > ((gameWidth/10)*2) and mousepos.x < ((gameWidth/10)*8):
		able_to_turn = true

It does work, but you need to await this function to create a coroutine.
This should fix your issue I hope:

await wait(0.5)

thanks, works, only issue now is that it seems to keep rotating while it waits, but I presume I can fix that by just setting it to rotate by 0 before the wait.

okay that didn’t fix it at all
the issue seems dependant on the length of time the mouse is held on the side of the screen

You have this code in _process() and in a for loop, which means it will run every frame, regardless if you’re awaiting something or not.
await keyword creates a coroutine, which becomes disconnected from the main loop and then returns to the loop when the couritine finishes. It might be a bit confusing when you’re first learning about it, so you can maybe do some testing on the side to understand it better.
Here’s a good explanation, just ignore the yield part, as it’s relevant for Godot 3.x only.

You’re trying to await inside of _process, this doesn’t stop _process from running every frame so you end up with multiple process calls waiting 0.5 seconds.

If you want to animate the rotation maybe using a Tween would work better?

if able_to_turn and mousepos.x > ((gameWidth/10)*9):
	var turn_tween := create_tween()
	turn_tween.tween_property(neck, "rotation:y", 90, 4.5).as_relative()
	able_to_turn = false
1 Like

it just kinda
does absolutely nothing
it just doesn’t rotate at all

Do you have any other code altering the neck rotation property? Can you show your edited code?

I commented all of the code that would’ve edited the rotation out
so it shouldn’t be affected by anything
just gonna shove in the whole script

extends MeshInstance3D

func wait(seconds: float) -> void:
	await get_tree().create_timer(seconds).timeout
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.

# Called every frame. 'delta' is the elapsed time since the previous frame.
@onready var neck := $neck
@onready var camera := $neck/Camera3D
@onready var able_to_turn := true
func _process(_delta: float) -> void:
	var gameWidth: float = get_window().get_size().x
	var mousepos = get_viewport().get_mouse_position()
	#var mousex = mousepos.x
	#var camy = neck.rotation.y
	
	if able_to_turn and mousepos.x > ((gameWidth/10)*9):
		var turn_tween := create_tween()
		turn_tween.tween_property(neck, "rotation:y", 90, 1).as_relative()
	able_to_turn = false

Oh yeah I forgot the conversion to radians

turn_tween.tween_property(neck, "rotation:y", deg_to_rad(90), 1).as_relative()

And this line seems to be un-indented which would create many more rotation tweens running at the same time, causing issues

1 Like

thankss
only one more issue and it’s just the fact that the tweens stack on top of eachother if you turn again while already turning
nevermind it’s near impossible to turn while already turning when I just make the time shorter

Yeah, how do you want to resolve that? Generally your options are to kill the active tween or prevent new ones, either way you will need to store the turn_tween in the class body to keep track of the active one.

var turn_tween: Tween

func _process(_delta: float) -> void:
	var gameWidth: float = get_window().get_size().x
	var mousepos = get_viewport().get_mouse_position()
	#var mousex = mousepos.x
	#var camy = neck.rotation.y
	
	if able_to_turn and mousepos.x > ((gameWidth/10)*9):
		if turn_tween and turn_tween.is_valid(): # a tween is active, what now?
			turn_tween.kill() # kill it! (and start the new one)
			# or...
			return # prevent more tweens
		turn_tween = create_tween()
		turn_tween.tween_property(neck, "rotation:y", deg_to_rad(90), 1).as_relative()

thanks so much
I’ve been messing around with camera movement for days and I’m glad I’ve actually got a functional thing now.