2

I posted this question on the stack math site, but they are not too excited to see questions including programming. Anyway, now I am here :)


  1. I have an object, which is located at MyTransform.position (Vector)
  2. That object should follow the DesiredPosition (Vector), which is moving in varius directions with a changing velocity
  3. MaxDelayDistance (float) is the maximum distance my object is allowed to have to the DesiredPosition.
  4. DelayRecovery (float) are the seconds my object has in order to move to the DesiredPosition if the MaxDelayDistance is reached.
  5. Time.deltaTime (float) is a term we use to describe the time the last frame update took. It's value is usually about 0.025f.

private Vector3 GetLerpedPosition(Vector3 DesiredPosition) {
            //DesiredPosition now contains the goal
            Vector3 dirToDesiredPosition = (DesiredPosition - MyTransform.position).normalized; //Direction to desired position
            Vector3 lerpStart = DesiredPosition + (-dirToDesiredPosition * MaxDelayDistance); //Start the lerp at my farthest allowed position
            float lerpCurrentT = Vector3.Distance(MyTransform.position, DesiredPosition) / Vector3.Distance(lerpStart, DesiredPosition); //My current fragtion (t) of the lerp

            //Now I lerp from lerpStart to DesiredPosition using a calculated fraction
            Vector3 result = Vector3.Lerp(
                lerpStart,
                DesiredPosition,
                lerpCurrentT + (DelayRecovery / MaxDelayDistance * Vector3.Distance(MyTransform.position, DesiredPosition) * Time.deltaTime)
                );
            return result;
        }

The main problem is that my object is not following the DesiredPosition smoothly. It jumps from MaxDelayDistance to DesiredPosition and back. Somehow the fraction (t) in my Lerp function always results in about 1.005 or about 0.001. Can you spot any problems in my approach?

Noel Widmer
  • 4,444
  • 9
  • 45
  • 69
  • If I understand your goal correctly, you might achieve a more consistent result by calculating `dirToDesiredPosition`, tracking some value `distanceMoved` that increases each frame, then moving the object to `lerpStart + dirToDesiredPosition * distanceMoved`. – rutter Apr 30 '15 at 14:32

1 Answers1

2

I see several issue, and I'm not sure of the direction you have choose (at least never seen anything similar before).

Preamble:

Vector3.Distance(lerpStart, DesiredPosition)

this is a constant and is the radius around DesiredPosition.

Here's some problems I noticed:

Problem 1

lerpT is always >=1 for every point more distant more than MaxDelayDistance (outside the radius). So when an object is further distant than MaxDelayDistance it will be immediately moved to DesiredPosition.

Problem 2

DelayRecovery (float) are the seconds my object has in order to move to the DesiredPosition if the MaxDelayDistance is reached.

Not sure of having completely understood your intricate lerp, btw the statement above seems to be false. DelayRecover is always taken in consideration while lerping despite its distance.

Problem 3

Possible division by zero when you are closed to DesiredPosition (* operator is evaluated before /)

Some considerations

I'll read with more attention your code, and I'll try to figure out the logic behind that. It's something I've never seen. Some general approach for moving toward a given position:

  1. If start and destination are known and fixed, than lerping (or an ease function) allow to control exactly the travel time incrementing t parameter from 0 to 1.
  2. If destination is moving you can still smooth follow the target using lerp (maybe not the more correct use from a theoretical point of view, nor physical realistic but in any case effective). Lerp factor in this case is a kind of "speed toward the goal". Effectively linear proportional to the distance from the target.
  3. Some physic based approach. Integrate. Define some kind of max speed and max acceleration and calculate the next position (eventually clamp to prevent overshooting and oscillation)
  4. PID controllers. Lot of power, but I always found them hard to tweak.

Consider also to use Vector3.MoveToward, here's how it's implemented:

public static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta)
    {
        Vector3 a = target - current;
        float magnitude = a.magnitude;
        if (magnitude <= maxDistanceDelta || magnitude == 0f)
        {
            return target;
        }
        return current + a / magnitude * maxDistanceDelta;
    }

Hope this helps.

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • I will check this as soon as I am back at my pc. Thanks for the explanation already! – Noel Widmer May 01 '15 at 19:07
  • Thanks for the very useful tips! I though about your ideas and implemented something that works. I'll also try the other tips to find a best fit. I probably just confused myself while trying to figure something out and came up with a very complex not-working solution. Thank's for clearing this up for me. :D – Noel Widmer May 04 '15 at 10:56