Why look_at rotates to the wrong angle?

I’m working on a 3D game with a dialogue system, and I need the player to rotate their Y angle to a target position.

But if I rotate the player mesh it breaks this line of code that rotates the player to the direction angle.

Body.rotate.y = lerp_angle(Body.rotation.y, atan2 (direction.x, direction.z), delta * rotation_speed)

Send help

Need more info.

Please put code between ``` like this:

```gdscript
#Code here
```

#Code here

How are you rotating the player? Where is that code? Also, the one line you did show does wildly different things depending on where you put it. I’m assuming that it’s probably in _physics_process(), but I honestly don’t want to spend time this late at night giving you advice based on that assumption just to find out it’s somewhere else.

We can only help if you give us enough information to work with.

1 Like

Try this to rotate the object to face the to_target coordinates:

	var target_rotation = atan2(to_target.x, to_target.z)
	rotation.y = move_toward(rotation.y, target_rotation, delta * speed)

I suppose you use these lines in your _process or _physics_process function.

1 Like
extends CharacterBody3D
#region, Llamada a nodos y variables OwO
@onready var cam: Node3D = $Camara_centro/Brazo_angulo
@onready var Cuerpo :Node3D = $Chucho_cuerpo
@onready var Hurtbox: Node3D = $Hurtbox/CollisionShape3D
@onready var HitboxDaño :Node3D = $Chucho_cuerpo/Armature/Skeleton3D/Hitbox/CollisionShape3D
@onready var Salto_fx :GPUParticles3D = $Chucho_cuerpo/Salto #Efectos visuales
@onready var Pasos_fx :GPUParticles3D = $Chucho_cuerpo/Pasos
@onready var Fuego_fx :GPUParticles3D = $Chucho_cuerpo/Fuego
var dash_fantasma = preload("res://Personajes/Chucho/Visuales/dash.tscn")
@onready var Slash1 :MeshInstance3D = $Chucho_cuerpo/Armature/Skeleton3D/EspadaMano/Ataque1
@onready var Animador = $Chucho_cuerpo/Animador2
@onready var ataque_sonido = $Sonidos/Ataque
@onready var Dash_tiempo :Timer = $Temporizadores/Dash_tiempo #Tiempos de abajo
@onready var Dash_fantasma :Timer = $Temporizadores/Dash_fantasma
@onready var Ataque_tiempo :Timer = $Temporizadores/Ataque_tiempo
@onready var Coyote_tiempo :Timer = $Temporizadores/Coyote
# -> VARIABLES DE PERSONAJE
@export var Velocidad : float = 5.4
@export var Rotacion_velocidad : float = 10
@export var Salto : float = 22.4
# -> ESTADOS SPECIFICOS
var Angulo_Eloy_inicial_y : float 
var Angulo_camaras_inicial_y : float
var Coyote :bool # Coyote time
var salto_caida :bool #Esta en el aire
var Estuvo_aire :bool
var Ataque_CD :bool #bloquea atacar si es verdadero
var Acciones_CD : bool #bloquea dash si es verdadero
# -> VARIABLES DE ANIMACION
var Quieto :bool 
var Moverse :bool 
var Ataques : bool 
var Dashea :bool 
var Ataque : int = 1 # Numero de animacion
#endregion, Llamada a nodos y variables OwO 


#region, Habilidades del personaje [INPUT]
func _input(_event: InputEvent) -> void:
# -> Habilidad de ataque, todas las animaciones de ataque duran lo mismo
	if Input.is_action_just_pressed("Ataca") and !Ataque_CD and !Dashea:
		Ataque_CD = true
		HitboxDaño.disabled = false
		Ataque_tiempo.start()
		_REINICIAR_ANIMS()
		Ataques = true
		ataque_sonido.play()
		if Ataque == 1:
			Animador["parameters/Ataques/blend_position"] = 0
			Slash1.visible = true
			return
		if Ataque == 2:
			Animador["parameters/Ataques/blend_position"] = 1
			Slash1.visible = true
			return
		#if Ataque == 3:
		#if Ataque == 4:

	if Input.is_action_just_pressed("Dash") and !Acciones_CD and !Ataques:
		Acciones_CD = true
		Hurtbox.disabled = true
		Coyote_tiempo.wait_time = 2.9
		Dash_tiempo.start()
		_REINICIAR_ANIMS()
		Dashea = true
		Fuego_fx.emitting = true
		crear_fantasma()
		Dash_fantasma.start()
		$Sonidos/Dash.playing = true

	if is_on_floor() and Coyote == false:
		Coyote = true # Puede saltar si esta en el suelo
	elif Coyote == true and Coyote_tiempo.is_stopped():
		Coyote_tiempo.start(Coyote)

	if Input.is_action_just_pressed("Salto") and Coyote:
		Coyote = false # Desactiva el coyote time al saltar
		velocity.y = Salto # Salta XD
		Salto_fx.top_level = true
		Salto_fx.position = $".".position
		Salto_fx.emitting = true
		$Sonidos/Salto.playing = false
		$Sonidos/Salto.playing = true
#endregion, Habilidades del personaje [INPUT]

func _ready() -> void:
	Cuerpo.rotation_degrees.y = Angulo_Eloy_inicial_y
	$Camara_centro/Brazo_de_camara.rotation_degrees.y = Angulo_camaras_inicial_y
	$Camara_centro/Brazo_angulo.rotation_degrees.y = Angulo_camaras_inicial_y

func _on_coyote_timeout() -> void:
	Coyote = false
 
func _on_dash_tiempo_timeout() -> void:
	Dashea = false
	Coyote_tiempo.wait_time = 0.82
	Fuego_fx. emitting = false
	Dash_fantasma.stop()
	Hurtbox.disabled = false
	
	await get_tree().create_timer(0.6).timeout
	Acciones_CD = false

# Desactiva las animaciones de ataque, inicia el temporizador de bloqueo, y desactiva hitbox de espada
func _on_ataque_tiempo_timeout() -> void:
	Slash1.visible = false
	Ataques = false
	HitboxDaño.disabled = true 

	await get_tree().create_timer(0.15).timeout
	if Ataque == 2:
		Ataque = 1
	else:
		Ataque = 2
	Ataque_CD = false

func _on_dash_fantasma_timeout() -> void:
	crear_fantasma()

func crear_fantasma (): # Controla el fantasma que se crea al hacer dash
	var fantasma: Node3D = dash_fantasma.instantiate()
	get_parent().get_parent().add_child(fantasma)
	fantasma.global_position = global_position
	fantasma.rotation.y = Cuerpo.rotation.y

@export var objetivo :Node3D
func _MirarObjecto(_delta):
	pass

func _REINICIAR_ANIMS():
	Quieto = false
	Moverse = false
	Ataques = false
	Dashea = false
	salto_caida = false

### -> MOVIMIENTO, GRAVEDAD Y ANIMACIONES
func _physics_process(delta: float) -> void: 
	if not is_on_floor(): 
		velocity += get_gravity() * delta # Matematicas de gravedad XD
		if !Ataques and !Dashea: #ANIMACIONES 
			_REINICIAR_ANIMS()
			salto_caida = true
			Estuvo_aire = true
	else: # Efecto visual al regesar al suelo
		if Estuvo_aire == true:
			Estuvo_aire = false
			Salto_fx.top_level = true
			Salto_fx.position = $".".position
			Salto_fx.emitting = true
			$Sonidos/Caer.playing = true
	
	if Dashea: # Se mueve y hace dash chingon
		self.position = $Chucho_cuerpo/Dash_ubi.global_position
		if !is_on_floor():
			velocity.y += 0.28
	
	# Get the input direction and handle the movement/deceleration.
	var input_dir := Input.get_vector("izquierda", "derecha", "delante", "atras")
	var direction = (cam.global_basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	
	if direction and !Dashea:
		velocity.x = direction.x * Velocidad
		velocity.z = direction.z * Velocidad
		Cuerpo.rotation.y = lerp_angle(Cuerpo.rotation.y, atan2 (direction.x, direction.z), delta * Rotacion_velocidad)
		if !Dashea and !Ataques and is_on_floor():
			_REINICIAR_ANIMS()
			Moverse = true
	else:
		velocity.x = move_toward(velocity.x, 0, Velocidad)
		velocity.z = move_toward(velocity.z, 0, Velocidad)
		if !Dashea and !Ataques and is_on_floor():
			_REINICIAR_ANIMS()
			Quieto = true 
	
	
	# Pone una animacion
	Animador["parameters/conditions/Moverse"] = Moverse
	Animador["parameters/conditions/Quieto"] = Quieto
	Animador["parameters/conditions/Salto_caida"] = salto_caida
	Animador["parameters/conditions/Dash"] = Dashea
	Animador["parameters/conditions/Ataques"] = Ataques
	#Efecto visual de pasos mientras esta en el suelo
	if Moverse == true:
		Pasos_fx.emitting = true
	else:
		Pasos_fx.emitting = false
	move_and_slide(); # Reorganizar codigo inporta 

This is the script i want to make the character to look at to an object

@export var objetivo :Node3D
func _MirarObjecto(_delta):
	pass

but i cant rotate 180 degrees the mesh of the player because the player rotates based on walking direction

	if direction and !Dashea:
		velocity.x = direction.x * Velocidad
		velocity.z = direction.z * Velocidad
### Rotation
		Cuerpo.rotation.y = lerp_angle(Cuerpo.rotation.y, atan2 (direction.x, direction.z), delta * Rotacion_velocidad)
### Rotation
		if !Dashea and !Ataques and is_on_floor():
			_REINICIAR_ANIMS()
			Moverse = true

Here’s what I would do: Change the walking direction of the player to be pointing towards the way you want them to look during the dialog. There are other ways you could handle it, but since you’re already dealing with facing, just do it there. Then turn off player input during the dialogue.

1 Like

I found a line of code that works the way I want, but rotation isn’t smooth.

@export var target :Node3D
func _LookAtOwO(): # Call this function when is nesesary
	self.look_at(target .global_position, Vector3.UP, true)
	self.rotation_degrees.x = 0 # Resets the X rotation lol

You can just use the lerp function like you did above to smooth it out.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.