Move to vector, when reached it keeps vibrating/moving.

Hello,

Atm. i am making a rts/click to move engine, i am using the script below to move up to 300 objects to a clicked position, but when it reach the destination it keeps vibrating(only 1 object, due to ray will stop all others), is there a way to stop it from doing that?


def move_unit(cont):
    
    own = cont.owner
    
    if own['destination']:
        
        vector = own['destination'] - own.worldPosition
        script.face_direction(own, vector) #alignAxisToVect


        y_direction = own.worldPosition + own.worldOrientation.col[1]
        ray = own.rayCast(y_direction, own, 3.0)
        
        if own['destination'] is not own.worldPosition and not ray[0]:
            Rasterizer.drawLine(own.worldPosition, own['destination'], [0,0,1])
            own.localLinearVelocity = [0, own['speed'], own.localLinearVelocity.z]

thought this should work, but ofcourse this wont work because the vectors are never the same

<Vector (0.2005, 27.1154, 1.0382)> <Vector (0.2047, 27.0419, -0.0000)><Vector (0.2052, 27.0330, 1.0386)> <Vector (0.2047, 27.0419, -0.0000)>
<Vector (0.2005, 27.1154, 1.0389)> <Vector (0.2047, 27.0419, -0.0000)>
<Vector (0.2052, 27.0330, 1.0391)> <Vector (0.2047, 27.0419, -0.0000)>

so i thought making new vectors and round it to get a match would do the trick, so i made this:


        own_pos_x = round(own.worldPosition.x, 1)
        own_pos_y = round(own.worldPosition.y, 1)
        new_own_vec = [own_pos_x, own_pos_y, 0]
        
        des_pos_x = round(own['destination'][0], 1)
        des_pos_y = round(own['destination'][1], 1)
        new_des_vec =[des_pos_x, des_pos_y, 0]
        
        if new_own_vec is not new_des_vec and not ray[0]:


and it prints

[0.5, 24.7, 0] [0.4, 24.7, 0][0.4, 24.7, 0] [0.4, 24.7, 0]
[0.5, 24.7, 0] [0.4, 24.7, 0]
[0.4, 24.7, 0] [0.4, 24.7, 0]

so we have a match, but why does it keep vibrating/moving at the destination?
more important how do i stop it from doing that?

I usually get the target vector (destination - start) and find out its length.

start = own.worldPosition.copy()
end = target.worldPosition.copy()

target_vector = end- start
distance = vector.length

If the length is < 0.001 or something similar then stop.

EDITED:
Removed the call at the end of length.

you mean like this?


        destination_vec = own['destination'] - own.worldPosition
        asd = destination_vec.length()
        print(asd)

But this gives me an error:
TypeError: ‘float’ object is not callable

#edit
Nvm, needed to remove the () at length

#edit 2
Thanks it works great.

The “is” operator checks identity, not equality. Two books can be equal (in content) but never the same (in identity).
In addition, you would need to check for some epsilon difference between vectors, as two floats are rarely the same even if the algebra would have them be (due to precision and other effects)


def vecs_are_close(a, b, eps=1e-6):
    return (a - b).length &lt; eps

Thanks agoose i will try it out.

But does it bring some additional functions? because the script example of smoking_mirror works perfectly.
as i understand ’ eps=1e-6’ rounds it of to 6 decimals?

It doesn’t add anything new; my post didn’t send when I wrote it before SmokingMirror’s reply. It’s just a convenience function to test if two vectors are ~equal.

Of course it depends on how accurate you want placement to be. If your characters are 2 blender units tall then 0.002 blender units is accurate enough. If they are 0.002 BU tall then it probably isn’t.