+1 vote

Hi everyone. I recently started using Godot to make my first game which is a 3D role playing game using mouse click to move.

I used the Navmesh template provided and imported my own models and attempted to replace the settransform() function to use moveand_slide on my KinematicBody Character Node.

I have the character following the path but the movement speed is uneven. Between some points, the character moves slowly, between other points he zooms past really quickly. I think this may be because there are more points between some sections and fewer in other sections.

I'm looking to see if there is a better way to accomplish this. In fact I almost certain there is and could use some guidance. For example, I am checking if the character is close to his next point before removing the point from the array and getting the next point.

Here is a snip of my character nodes script that is handling the movement:

func _set_path(p):
    path = p
    set_physics_process(true)

func _physics_process(delta):
    var direction = Vector3(0,0,0)

if(path.size() > 0):
    var next_position = path[path.size()-1]
    direction = next_position - translation;
    direction.normalized()
    look_at(next_position + Vector3(direction.x,0,direction.z),Vector3(0,1,0))
    move_and_slide(direction * SPEED, Vector3(0,1,0),0.05,4,1)
    if(abs(translation.x - next_position.x) <= 0.05 and abs(translation.z - next_position.z) <= 0.05):
        path.remove(path.size() - 1)
    var anim = get_node("Character/AnimationPlayer")
    if(anim.is_playing() and anim.assigned_animation != "Anim_Run-loop"):
        anim.stop()
        anim.play("Anim_Run-loop")
else:
    set_physics_process(false)
in Engine by (29 points)

1 Answer

0 votes

I figured out what was missing.

I needed to use the linearinterpolation function to get a point between the characters current position and the nextposition for a smoother movement.

I do this by having a global variable called "nextmovepos = Vector3(0,0,0)"

func physicsprocess(delta):
var direction = Vector3(0,0,0)

if(path.size() > 0):
    var next_position = path[path.size()-1]
    if(next_move_pos == Vector3(0,0,0)):
        next_move_pos = next_position
    var distance = translation.distance_to(next_position)
    if(distance != 0):
        next_position = translation.linear_interpolate(next_position, (SPEED*delta)/distance)
    direction = next_position - translation;
    direction.normalized()
    #direction.y = direction.y * -9.8
    look_at(next_move_pos + Vector3(direction.x,0,direction.z),Vector3(0,1,0))
    move_and_slide(direction * SPEED, Vector3(0,1,0))
    if(abs(translation.x - next_move_pos.x) <= 0.05 and abs(translation.z - next_move_pos.z) <= 0.05):
        path.remove(path.size() - 1)
        next_move_pos = Vector3(0,0,0)
    var anim = get_node("Character/AnimationPlayer")
    if(anim.is_playing() and anim.assigned_animation != "Anim_Run-loop"):
        anim.stop()
        anim.play("Anim_Run-loop")
else:
    set_physics_process(false)

Another change is that the condition that determines removing the current point in the path and getting the next one, looks at the nextmovepos global variable rather than the linear_interpolated next position which changes often.

I still think there has to be a better way of determining that we have reached a point in a path and should now start moving to the next point than comparing the x and z position with the characters position with some leeway (0.05 in my case).

by (29 points)

I'm using it with a little tiny change:

var direction = Vector3(0,0,0)
var initialTranslation = translation   # Gatting the initial translation before moving
if(path.size() > 0):
    ...
    look_at(Vector3(next_move_pos.x, initialTranslation.y, next_move_pos.z) + Vector3(direction.x, 0, direction.z),Vector3(0, 1, 0))  # Using the y axis of the "initialTranslation"
    ...
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.