0 votes

I am trying to implement a 'lean' mechanic in my game, and to do so, I want to have my character move slightly left or right relative to its position when a button is held, and then return to its original position when the button is released.

In loose pseudocode this would be roughly:

if action "lean_right" is pressed, set local x position to 0.2
if action "lean_left" is pressed, set local x position to -0.2
else set local x position to 0.0

All of the position functions I have been able to find in GDScript pertain to global position. I am assuming I need to use a vector3 to move my character relative to itself, but I can only find information about setting a velocity value, which applies constant motion which in this case isn't desirable. Can someone please kindly explain how to modify an object's relative position in the manner specified?

Godot version 4.0 beta 1
in Engine by (17 points)

2 Answers

+1 vote
Best answer

Assuming you're not using a rigid body as your player, the following should work if I understand what you're trying to do:

if Input.is_action_just_pressed("lean_right") or Input.is_action_just_released("lean_left"):
global_position += 0.2
if Input.is_action_just_pressed("lean_left") or Input.is_action_just_released("lean_right"):
global_position -= 0.2

Alternatively, you could just set the positions of all the player's children (like the sprite, the hitbox, whatever else should be attached to the position of the player).

by (69 points)
selected by

I genuinely hadn't considered just using the child objects instead of the CharacterBody3D itself. That makes a lot more sense, and if I declare in physics_process, then it still respects collision. I could probably make my code a lot more concise, but here is what I ended up using, if anybody has the same query as me:

func _physics_process(delta):
    #handle leaning
    rotation.z = lerp(rotation.z, 0.0, lean_transition_speed * delta)
    player_capsule.position.x = lerp(player_capsule.position.x, 0.0, lean_transition_speed * delta)
    head.position.x = lerp(head.position.x, 0.0, lean_transition_speed * delta)
    if Input.is_action_pressed("Lean_left"):
        rotation.z = lerp(rotation.z, 0.4, lean_transition_speed * delta)
        player_capsule.position.x = lerp(player_capsule.position.x, -2.0, lean_transition_speed * delta)
        head.position.x = lerp(head.position.x, -2.0, lean_transition_speed * delta)
    if Input.is_action_pressed("Lean_right"):
        rotation.z = lerp(rotation.z, -0.4, lean_transition_speed * delta)
        player_capsule.position.x = lerp(player_capsule.position.x, 2.0, lean_transition_speed * delta)
        head.position.x = lerp(head.position.x, 2.0, lean_transition_speed * delta)


Thank you!

0 votes

Just use mathematic in relation to global_position instead of setting it.
global_postition.x += 10 or global_position += Vector3(10,0,0) and so on

If You need more complicated positioning in 3D, take a look at Transform property
However, editor will not memorize original location for You, You need to code it yourself.

by (7,925 points)

Unfotunately, setting global_position in this manner results in continuous motion that breaks collision. It also cannot be clamped, as clamp() can apparently only be set as an absolute value. I also experimented with transform.origin, in the manner described, but this causes constant co-ordinate fighting and crashes Godot after a few seconds.

I feel like I am missing something here. Surely moving a character along a single axis a set amount when a button is pressed, and returning to original position when the button is released cannot be too complicated?

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.