I've seen examples of this posted around on using things like look_at() and even some rotation maths but it seems that none of them really do what I'm thinking of specifically. I want to have the Z origin.basis of my node pointing towards where it is moving. I tried using various rotation and look_at() methods for this but they were either too generalised with the axis so that would mean my node would wobble or point all over the place as it was moving and trying to find the target which is to be expected because the X and Z axis rotations were screwing up the behaviour. I tried just having the Y axis pointing towards my vector 3 but of course that just had it point directly at the co-ordinates it was travelling to rather than having it point forward along the path it was travelling.

What's the best way to approach this? The specific example I'm dealing with is to try and have my navmesh agent always pointing forward in the direction it's travelling, don't know why it's proving to be a bit of a fussy thing to implement in Godot but here I am again lol. There are some snippets I've seen posted of this rotation behaviour being used in 2D but not much on the 3D front.

  • Well that was fast, found the answer.

    	if velocity != Vector3.ZERO:
    		var lookDirection = atan2(velocity.x, velocity.z)
    		rotation.y = lerp (rotation.y, lookDirection, 1 * delta)

    Literally all I needed, thought it was being too complicated for what I wanted to do.

Transform3D's method rotated_local( forward_axis, angle ) ?

I believe the forward axis must be normalized ...

Looking at the documentation how would the angle calculation work? Haven't seen this before.

Pseudo code experiment, something like?

declaredNode.rotate_object_local(Vector3(0, transform.basis.z, 0), ???)

Don't know what to do with the angle.

Okay this is funny LOL.

declaredNode.rotate_object_local(transform.basis.y, 1)

So the rotations are happening now which is refreshing but it's just spinning around, hadn't realised the angle was the rotation speed. I think I get where you're going with this, the issue now is making it so it rotates in the correct direction, for that I need to somehow give this rotate_object_local the direction it's moving in.

The basis is the node's orientation (or rotation). If you have a direction, you can just convert that into a rotation.

If you are on flat ground, then you could do something like this.

human.transform.basis = Basis(Vector3.UP, angle_from_above)

Where human is the node you want to rotate, and angle_from_above is a float in radians around the y axis.

You can also create a Basis from just a Vector3:

human.transform.basis = Basis(angle_vector_angle)

Ah, now that's the problem I keep running into, I don't have a direction.

The velocity it is moving is the direction (you can plug it into my second example).

Should I be switching from Kinematic to Rigidbody then for this code to work?

It would need to be a KinematicBody. This will snap the rotation. Once you get the math working, you can use a linear interpolate to smooth it.

var villagerTargetLocation : Vector3
var villagerTargetRotation : Basis
var rotationLerp = 0.0
var rotationSpeed = 1.0
func _physics_process(delta):
	
	villagerRotationProcess(delta)
func VillagerRotation_SetTargetLocation(new_target: Vector3):
	villagerTargetLocation = new_target
	rotationLerp = 0
	
func villagerRotate(delta):
	if rotationLerp < 1:
		rotationLerp += delta * rotationSpeed
	elif rotationLerp > 1:
		norseMaleVillagerMesh_Spatial.transform.basis = transform.basis.slerp(villagerTargetRotation, rotationLerp).orthonormalized()
		norseMaleVillagerStatus_Spatial.transform.basis = transform.basis.slerp(villagerTargetRotation, rotationLerp).orthonormalized()

func villagerRotationProcess(delta): 
	villagerTargetLocation.y = transform.origin.y
	if villagerTargetLocation != transform.origin:
		villagerTargetRotation = transform.looking_at(villagerTargetLocation, Vector3.UP).basis
		villagerRotate(delta)

That's almost working now which is fantastic, but it's not rotating as potentially instantly as I'd like and I still need to convert the movement direction properly, I think that's why.

You don't need the if statement. You can just set rotationLerp to a value like 0.3 and it will work okay.

Hmmm, need to investigate this code and poke at it some more, I think it's a bit overcomplicated for what I'm try to do and can be tidied up.

@cybereality This is all new code to me so I'm going to have to do some poking at it.

Well that was fast, found the answer.

	if velocity != Vector3.ZERO:
		var lookDirection = atan2(velocity.x, velocity.z)
		rotation.y = lerp (rotation.y, lookDirection, 1 * delta)

Literally all I needed, thought it was being too complicated for what I wanted to do.