Help needed with 3D top down character rotation

Godot Version

4.6 dev 4

Question

I need help to solve a weird rotation issue

Hi. I’m currently working on a 3D top-down game, where I have a character controlled by a gamepad. The issue i’m facing is that when the character is moving and I release the left stick of my controller quickly, my character rotates sometimes abruptly to face a direction that i’ve not set with my controller. A showcase is given down below.

The is code i’ve written to rotate my player :

if input.length() > 0.1:
player_skin.rotation.y = lerp_angle(player_skin.rotation.y,
atan2(input.x, input.z) + PI,
data.rotation_speed * delta)

You will see that most of the time it is barely noticeable, but sometimes it is very obvious.

Can you help me please ?

It is from the accurate reading of your controller, you need to add a dead zone to however you are getting your input because when you let go of stick the it doesn’t center to 0,0 all the time.

Lets say you are holding the stick full left and then let go the values could look like this:

X = 1.0

then you let go

X = -0.1

instead of going to center it has a slight deviation because of the accuracy of your input function.

1 Like

Oh I see ! What would be the best way to implement a deadzone ? Should i define a custom one, or just modifying it in the Project Settings ?

Are you normalizing your input before this if statement? If so try to remove that, especially if using Input.get_vector otherwise you can use limit_length(1.0) instead for potentially better results

2 Likes

Setting up controller is a bit tricky because you might want to be able to “walk” and “run” while using only the left stick:

The page I provided should help you learn about controller input and how to implement them into gdscript

3 Likes

Input.get_vector has a deadzone parameter, though I never used it, don’t know hot it works, you could try passing 0.05 or 0.1 maybe. And from the input length value on your screen it looks like you’re normalizing the input, you probably shouldn’t do that for a controller, as already said above.

1 Like

My movement style is based on Link’s Awakening. So I do not need walk/run logic, only walk. So I think it’ll be simpler.

Thanks for the doc. I’ll dive into it right now :smile:

My input is not normalized → This is what i’m using : var input = Input.get_vector(“left”, “right”, “up”, “down”).

Interesting, I noticed the “Input Length: 1.0” label at the top of the screen, but it was only every 0.0 or 1.0, so it seems to be normalized somewhere or you are terribly quick with the stick, or I guess the label could be wrong. Anyway if you show more of the controller script that may help.

2 Likes

As I said to @gertkeno, input is not normalized → This is what i’m using : var input = Input.get_vector(“left”, “right”, “up”, “down”).

The deadzone is the 5th parameter so it would be something like:

var input = Input.get_vector(“left”, “right”, “up”, “down”, 0.1)

(But as I’ve said I don’t know if it would help…)

1 Like

Oh sorry, i’m getting confused with all my scripts :cold_face: !

In my UI script i have floored the input value, this is why you only see 0 or 1 :
%Label.text = str(floorf(action.move().length())), as action.move() is a input vector declared in an Autoload script:

extends Node

var input_vector: Vector2

func move() → Vector2:
   input_vector = Vector2(
      Input.get_axis(&“left”, &“right”),
      Input.get_axis(&“up”, &“down”)
   )
   return input_vector

And in my player script, i’ve used a temporary test solution :

func _update_player_input():
var input = Input.get_vector(“left”, “right”, “up”, “down”)

Again I’m sorry. I got confused my scripts

But none of them are normalized.

So I’ve used the Input.get_vector() method with 0.5 as deadzone, after reading the doc, and I’ve set the deadzone of the four axis in Project Settings to 0. For now the problem seems to be fixed, but i’ll explore all the others possibilities. Thank you very much !

This is what i’ve ended up, as of now :

var input = Input.get_vector(“left”, “right”, “up”, “down”, 0.5)

It works quite nicely, but there’s still some work to do.

I’m going to explore what you have suggested to me, namely the limit_length method()

Thank you for your help !

I suspect something is wrong with your code. For example why is liable not showing values between 0 and 1. Try to map it to arrow keys and see if it has same issue.

Maybe you should attach entire script?

1 Like