Normalizing and then multiplying Vector2()s doesn't work

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

I implemented a joystick for a mobile game project but it doesn’t work when i normalize the vector and multiply it by the speed.
These are the player script and a piece of debug text i collected (i cut some lines for it to be more understandable).

Player script:

extends KinematicBody2D


var dir = Vector2();
var vel = Vector2();


func _physics_process(delta):
	process_movement(delta);

func process_movement(delta):
	var dir = $UI/Joystick/Joystick.movement;
	dir = -dir.normalized();
	
	vel = dir*250.0;
	
	print(vel)
	
	vel = move_and_slide(vel,Vector2(0.0,1.0));

Debug text:

(-0, -0)
(176.776688, -176.776688)
(176.776688, -176.776688)
(176.776688, -176.776688)
(176.776688, -176.776688)
(237.170822, -79.056938)
(248.470917, -27.60788)
(249.688095, -12.484405)
(249.935455, 5.680351)
(250, -0)
(250, -0)
(250, -0)
(250, -0)

As you can see, vel goes from 0 to (176,-176) to (248,-27) when i drag the button, which is intended. But when i release it, the value doesn’t change, then becomes the factor i’m multiplying by (250) and drops to 0.
I’ve tried this without normalizing dir and it works. It seems like a problem with “normalized()”, but i’m not sure.

Print $UI/Joystick/Joystick.movement as well. If it’s not exactly 0,0 it will still get normalized.

Magso | 2020-09-25 23:51

It’s not clear what you’re actually looking for here. It almost looks like you want a binary mechanism where when you’re not touching the stick, you get no motion, and when you are touching the stick (even just a tiny bit), you get full speed motion. Is that correct?

I’d say the immediate problem is exactly as pointed out by @Masgo - your values aren’t exactly 0,0 when you release, and that’s getting normalized back into a full-length vector.

Maybe you can provide some more explanation of the intended result?

jgodfrey | 2020-09-26 15:02

If you really are looking for a binary mechanism (as described above), something like this should probably fix your problem:

func process_movement(delta):
    var dir = $UI/Joystick/Joystick.movement;

    if is_equal_approx(0, dir.length):
        dir = Vector2.ZERO

    dir = -dir.normalized();

    vel = dir*250.0;

    print(vel)

    vel = move_and_slide(vel,Vector2(0.0,1.0));

So, just reset the vector if its length is very nearly zero. Depending on your needs, you could bypass some of the other code there as well if the vector length is nearly zero…

jgodfrey | 2020-09-26 15:54