1
\$\begingroup\$

I have manually placed some cube on the floor and aim to walk my character on those cube as they are appearing in the hirarchey and here is the walk code.

 if (Vector3.Distance(pathPositions[pathIndex], walkingCharacter.transform.position) > 0.5f)
        {
            Vector3 newPosition = pathPositions[pathIndex] - walkingCharacter.transform.position;
            walkingCharacter.transform.position += newPosition * Time.deltaTime * walkingSpeed;
            walkingCharacter.transform.rotation = Quaternion.LookRotation(newPosition);
        }
        else {
            pathIndex++;
        }

I have walk in place animation which is working fine and the above code moving my character to specific points but not smoothly. As my character approach to specific path point it get slow then suddenly move towards next point. What i am doing wrong. Here is the video of the problem maybe it will helpful to understand the problem.

\$\endgroup\$
2
\$\begingroup\$

The code you've written is an exponential ease-out, which is why it slows down over time.

First, the newPosition vector isn't really a position but a target offset.

Vector3 newPosition = pathPositions[pathIndex] - walkingCharacter.transform.position;

It's measured from the character's position to their next waypoint, which means as the character approaches the waypoint, this offset vector gets shorter and shorter. You can imagine in the limiting case, if the character were allowed to reach a distance of zero away from the target, this vector would have no length at all.

Next, you increment the position by a multiple of this vector (here walkingSpeed isn't really a set speed at all, but an amplification factor on distance):

walkingCharacter.transform.position += newPosition * Time.deltaTime * walkingSpeed;

So as the offset gets smaller and smaller, so does the multiplied increment. So you approach the target in a manner like Xeno's paradox, taking smaller and smaller steps the closer you get.

To see this concretely, let's look at what happens if we have a walkingSpeed of 2 and a steady 1/30 deltaTime:

Frame    Offset to Target    Movement Increment
  1           30.00                2.00 <-- At this rate, we should reach 
  2           28.00                1.87     the goal in 15 frames!
  3           26.13                1.74
  4           24.39                1.63
  5           22.77                1.52
  6           21.25                1.42
  7           19.83                1.32
  8           18.51                1.23
  9           17.27                1.15
 10           16.12                1.07
 11           15.05                1.00
 12           14.05                0.94
 13           13.11                0.87
 14           12.23                0.82
 15           11.42                0.76
 16           10.66                0.71 <-- 15 frames later, we've only covered
                                            2/3rds of the distance, and we've
                                            lost 2/3rds of our speed. :(

Instead, it looks like you want MoveTowards:

walkingCharacter.transform.position = Vector3.MoveTowards(
    walkingCharacter.transform.position,
    pathPositions[pathIndex],
    walkingSpeed * Time.deltaTime
);

This keeps a constant movement speed of walkingSpeed throughout the travel.

Under the hood, it would look a bit like this (my re-implementation, not Unity's code):

public Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta) {
    float offset = target - current;

    // Avoiding square roots until they become necessary later.
    float lengthSquared = offset.sqrMagnitude;

    // If we're within our allowed movement range, we reach the endpoint and stop.
    if(lengthSquared <= maxDistanceDelta * maxDistanceDelta)
        return target;

    // Normalize the offset vector and scale it to the length of maxDistanceDelta.
    offset *= maxDistanceDelta / Mathf.Sqrt(lengthSquared);

    return target + offset;
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for insight but i will be happy if i don't use built in functions of unity in order to understand underlying mechanism, \$\endgroup\$ – Muhammad Faizan Khan Aug 7 '18 at 12:32
  • 1
    \$\begingroup\$ Says the one who's already using Vector3.Distance and Quaternion.LookRotation. ;) \$\endgroup\$ – DMGregory Aug 7 '18 at 12:38
  • \$\begingroup\$ :) actually my vector math is very weak. I don't have any option :) \$\endgroup\$ – Muhammad Faizan Khan Aug 7 '18 at 12:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.