+2 votes

In my 3D project, I am moving a kinematicbody from its current location to a specific point. When the kinematicbody is a certain length away from that point, I directly set its position to the point's position; position = point

The Godot docs warn against setting a kinematicbody's position directly, but for my purposes, I need the kinematicbody to be set exactly to the target point. So, is my approach okay? If not, what are the drawbacks and is there a better way to achieve what I want? Thanks in advance. Code example:

func _physics_process(delta):
    velocity = (target - position).normalized() * speed
    if (target - position).length() > 0.5:
        velocity = move_and_slide(velocity)
        position = target
in Engine by (37 points)
edited by

Setting the position and using translate for movement bypasses the physics. it's basically so collisions/interactions behave better.

So when I set "position = target" in the code snippet above, are you saying that if something were to collide with it during that assignment it could cause errors or are you saying that when I directly set the position, the physics is bypassed, therefore no physics error will occur?

No, it's ok to set it's position but you said "The Godot docs warn against setting a kinematicbody's position directly." This means it's better using move_and_slide instead of translate, for example the docs for move_and_slide say "If the other body is a KinematicBody or RigidBody, it will also be affected by the motion of the other body." translate would not allow for this as it alters the position directly.

Oh okay, I completely understand what you're saying. I'll have to run some test to see if being slightly off from the target is acceptable or if working around that drawback is the best choice of action. Thank you for your help. So, moving a kinematic body to a precise location isn't possible through the use of moveandslide.

1 Answer

+1 vote
Best answer

This is ok, but obviously there is a 0,5 meter margin, so it is not exact.
Godot 3.2 will get some methods to help for this case. Here is an example for float:

move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }

Hopefully there will be methods for Vector2 and Vector3 also. I am not sure myself how to implement it. However, you could implement this yourself in gdscript if needed in Godot 3.1:
Code is not tested. Hope this helps :)

func _physics_process(delta):
    var dir = (target - position).normalized()
    var move_amount = Vector2(move_toward(position.x, target.x, dir.x * speed  * delta), move_toward(position.y, target.y, dir.y * speed * delta))
    move_and_collide(move_amount) # or move_and_slide(move_amount / delta)

func move_toward(orig : float, target : float, amount : float) -> float:
        var result : float

        if abs(orig - target) <= amount:
            result = target
        elif orig < target:
            result = min(orig + amount, target)
        elif orig > target:
            result = max(orig - amount, target)
        return result
by (134 points)
selected by
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 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 webmaster@godotengine.org with your username.