Hi, I am trying to implement a simple waypoint-node object to make NPC object move towards a fixed Vector3 location.

The location scene is based on 3D node, and it has both position and rotation, my goal is to make NPC object slowly moving towards ' position' and slowly turning to the same facing(rotation x, y, z of the target 'waypoint node'), I searched a bit and the only function seemed to work is called 'look_at', but the function make the NPC object turn to a desired Vector3 location instantly rather than turning to it over time.

This is the workaround I am temporarily using:

func _nav_turn_to(target : Vector3, delta):
	var normalized_rate : Vector3 = get_nav_max_turnrate() * (delta / 1000)
	
	var target_rotx = target.x
	var target_roty = target.y
	var target_rotz = target.z
	
	var test = self.get_parent().get_parent() as Entity
	
	if test == null:
		print("null entity in _nav_turn_to function")
		return
	
	var rotation : Vector3 = test.rotation
	var new_rotation : Vector3 = rotation
	
	var origin_rotx = rotation.x
	var origin_roty = rotation.y
	var origin_rotz = rotation.z
	
	var diff_x = target_rotx - origin_rotx
	var diff_y = target_roty - origin_roty
	var diff_z = target_rotz - origin_rotz
	
	if diff_x > 0:
		if abs(diff_x) <= normalized_rate.x:
			new_rotation.x = target_rotx
		else:
			new_rotation.x = origin_rotx - normalized_rate.x
	else:
		if abs(diff_x) <= normalized_rate.x:
			new_rotation.x = target_rotx
		else:
			new_rotation.x = origin_rotx + normalized_rate.x
			
	if diff_y > 0:
		if abs(diff_y) <= normalized_rate.y:
			new_rotation.y = target_roty
		else:
			new_rotation.y = origin_roty - normalized_rate.y
	else:
		if abs(diff_y) <= normalized_rate.y:
			new_rotation.y = target_roty
		else:
			new_rotation.y = origin_roty + normalized_rate.y

	if diff_z > 0:
		if abs(diff_z) <= normalized_rate.z:
			new_rotation.z = target_rotz
		else:
			new_rotation.z = origin_rotz - normalized_rate.z
	else:
		if abs(diff_z) <= normalized_rate.z:
			new_rotation.z = target_rotz
		else:
			new_rotation.z = origin_rotz + normalized_rate.z
	
	#_nav_state = NAV_TURN_TO
	
	return new_rotation

So is there a function that rotates the facing x,y,z over time like move_and_slide, or I need to manually calculate rotate x, y, z speed based on 'delta'?

Thanks.

eidit: pasted wrong func -.-

    • Interpolation is a clean way of doing it.
    • There is even the same thing you are trying to do in the Godot docs.
    • Give that page a read.
    • Also another option is tweens, they are an another way of doing that. They don't need delta.
    • The Tween class in Godot docs
    • You can do something like this:
      func move_and_rotate(target_position, target_rotation, duration):
          var tween = get_tree().create_tween()
          tween.set_parallel(true) # So that the below tweens happen at the same time, not move then rotate
          tween.tween_property(self, "global_position", target_position, duration)
          tween.tween_property(self, "rotation", target_rotation, duration)
    • Call the function whenever you need to move the node.
  • Interpolation is a clean way of doing it.
  • There is even the same thing you are trying to do in the Godot docs.
  • Give that page a read.
  • Also another option is tweens, they are an another way of doing that. They don't need delta.
  • The Tween class in Godot docs
  • You can do something like this:
    func move_and_rotate(target_position, target_rotation, duration):
        var tween = get_tree().create_tween()
        tween.set_parallel(true) # So that the below tweens happen at the same time, not move then rotate
        tween.tween_property(self, "global_position", target_position, duration)
        tween.tween_property(self, "rotation", target_rotation, duration)
  • Call the function whenever you need to move the node.

    BroTa Thanks for the detailed explanation, I will see which one suits better for my case.