Make 3D character face direction of movement

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Yaann

Hi guys, I wanna make my character face the direction to where he is heading.
Here’s the script:

public void Move()
{

    velocity = new Vector3();
    if (Input.IsActionPressed("right"))
        velocity.x += 1;
    if (Input.IsActionPressed("left"))
        velocity.x -= 1;
    if (Input.IsActionPressed("down"))
        velocity.z += 1;
    if (Input.IsActionPressed("up"))
        velocity.z -= 1;
    velocity = velocity.Normalized() * speed;
}

public override void _PhysicsProcess(float delta)
{
    Move();
    MoveAndSlide(velocity,Vector3.Up,true,3);
:bust_in_silhouette: Reply From: Magso

Make the character MeshInstance(s) children of a spatial and use look_at()

character_spatial.look_at(transform.origin + velocity, Vector3.UP)

Unfortunately, it doesn’t work, probably because it is a Sprite3D.
In 2D there is this simple method:

sprite.rotation = velocity.Angle();

In 3D it’s another story since it uses a Vector3 as rotation, is there any ways I can mimic the same thing?

Yaann | 2020-04-21 10:43

2D rotation is a float, 3D rotation uses Basis which can be set by a basis, quaternion or Vector3. There isn’t a 3D method similar to angle(). look_at() is the easiest method to use here otherwise you need to get a target rotation and rotate to it. The only other workaround I can think of (but can’t guarantee if it’ll work) is cheat using Vector2(Vector3.x, Vector3.z).angle() and set rotation_degrees.y to the returned float.

In this case your Vector3 will be the velocity variable.

Magso | 2020-04-21 12:19

Looks like setting the rotation.z to new Vector2(veclocity.x, velocity.z).angle() does the trick. Thanks!

Yaann | 2020-04-21 14:46

:bust_in_silhouette: Reply From: Tato64

Just replying because i landed here from google and more people may too:

	var lookdir = atan2(-velocity.x, -velocity.z)
	rotation.y = lookdir

works perfectly if you only want the character to rotate “left/right”

Pay attention to the minus in the the “velocity.x” and “velocity.z”, no sure why but they need to be negative or else the model will face backwards.

You can also slap some more code to polish this a bit more like:

if velocity != Vector3.ZERO:
	var lookdir = atan2(-velocity.x, -velocity.z)
	rotation.y = lerp(rotation.y, lookdir, 0.1)

I think it depends on which way your model scene is facing VS the position of your camera. My model faces the +Z direction, and my camera is in the +Z direction relative to the play area. I was able to use rotation.y = atan2(velocity.x, velocity.z) without massaging the values.

zipperman | 2022-02-01 01:05

Of course, you can make your models face any direction, it’s just that negative Z is the commonly accepted default “forward” direction

Tato64 | 2022-02-09 05:43

Maybe there’s a way to make it check for when it’s a not a negative number, so the way it calculates the direction of the player is split into two seperate scripts, one for negative numbers and the other for positive numbers.

Entity2020 studios | 2023-05-26 14:51