I'm stumped on a key part of my game project, built in Godot 3.5.2.

I'm trying to have my player character be able to rotate around an object using A and D, as well as get closer and farther from it along a line using W and S. I've exhausted my personal knowledge on Godot trying to figure this out and I'll post my code below.

var move_base = .05
var move_dist = (Input.get_action_strength("move_down") - Input.get_action_strength("move_up")) * move_base
var move_orb = (Input.get_action_strength("move_right") - Input.get_action_strength("move_left")) * move_base
# Rotation variables
# Subtract origin point from target's position
var pivot_radius = Vector3.ZERO - target.global_translation
var pivot_transform = Transform(transform.basis, target.global_translation)

# Rotate around target
transform = pivot_transform.rotated(Vector3(0, 1, 0), move_orb).translated(pivot_radius)

I believe that if I can modify pivot radius to allow me to move along the radius it would work perfectly fine, but I'm bad when it comes to geometry and math.

I've also attached a picture to clarify what I'm trying to achieve if it helps at all. Thank you in advance!

enter image description here


1 Answer 1


First of all, work in global coordinates.

You are using target.global_translation which is global coordinates, but you are setting transform which isn't, instead it is relative to the parent node.

I will not go for a clever solution, but for one that is easy to follow.

We want to rotate the position of the player character global_transform.origin around the position of the distant object target.global_translation.origin.

So the vector we want to rotate is:

var vector_to_rotate := global_transform.origin - target.global_translation.origin

To rotate it we are to need a rotation axis, you are using Vector3(0, 1, 0), so I will use Vector3.UP. And I believe move_orb is the rotation angle. You might want to express it in terms of an angular velocity and use delta so it is frame rate independent, but I digress.

We rotate it like this:

var rotated_vector := vector_to_rotate.rotate(Vector3.UP, move_orb)

So we can compute the new position:

global_transform.origin = target.global_transform.origin + rotated_vector

Ah, but you want to control the distance too! So, instead we will get direction and distance. For example, like this:

var vector := global_transform.origin - target.global_translation.origin
var direction := vector.normalized()
var distance := vector.length()

You could also use direction_to and distance_to. Or you could normalize by dividing the vector over its length (but careful with division by zero).

Then we rotate the direction:

direction = direction.rotate(Vector3.UP, move_orb)

Change the distance:

distance += move_dist

Again, you could define a velocity and use delta, but you do you.

And we get the new position:

global_transform.origin = target.global_transform.origin + direction * distance

You can have the player character facing the target with a look_at:

look_at(target.global_transform.origin, Vector3.UP)

And that would account for the rotation.

  • \$\begingroup\$ Honestly I just did what you suggested in the last point and my final code ended up being: var move_orbit = (Input.get_action_strength("move_right") - Input.get_action_strength("move_left")) * move_base var move_dist = (Input.get_action_strength("move_down") - Input.get_action_strength("move_up")) * move_base look_at(target.global_translation, Vector3(0, 1, 0)) # Modify velocity velocity.x = move_orbit velocity.z = move_dist # Return velocity with modified angle to target. return velocity.rotated(Vector3(0, 1, 0), get_rotation().y) \$\endgroup\$
    – sungen
    Apr 29, 2023 at 3:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .