x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Predict Stop Position of Character ahead in time

Hey there,

I am trying to predict the exact location of where the player would stop once Acceleration is zero, i started looking around the default movement component but i am not sure how to approach this yet. Does anyone know a good way to do it?

i tried doing some simple calculations using ( BrakingDecelerationWalking and GroundFriction ) but nothing comes close to my exact debug line that i draw yet.

Product Version: UE 4.14
Tags:
more ▼

asked Dec 01 '16 at 01:13 AM in C++ Programming

avatar image

Highflex
48 2 5 12

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

You can use the same method CharacterMovementComponent calculating velocity and move updatedcomponent to simulate the move result. In the code bellow, I used fixed time step, the result is very close (usually less than 5 unreal unit) to the real stop location.

I want to find the extract stop location and pivoting location, but CharacterMovementComponent doesn't use fixed time to calculate valocity (see UCharacterMovementComponent::GetSimulationTimeStep), it's update time step is related to current frame's DeltaTime。

 bool CalculateStopLocation(
     FVector& OutStopLocation,
     const FVector& CurrentLocation,
     const FVector& Velocity, 
     const FVector& Acceleration, 
     float Friction,
     float BrakingDeceleration,
     const float TimeStep, 
     const int MaxSimulationIterations /*= 10*/)
 {
     const float MIN_TICK_TIME = 1e-6;
     if (TimeStep < MIN_TICK_TIME)
     {
         return false;
     }
     // Apply braking or deceleration
     const bool bZeroAcceleration = Acceleration.IsZero();
     
     if ((Acceleration | Velocity) > 0.0f)
     {
         return false;
     }
 
     BrakingDeceleration = FMath::Max(BrakingDeceleration, 0.f);
     Friction = FMath::Max(Friction, 0.f);
     const bool bZeroFriction = (Friction == 0.f);
     const bool bZeroBraking = (BrakingDeceleration == 0.f);
 
     if (bZeroAcceleration && bZeroFriction)
     {
         return false;
     }
 
     FVector LastVelocity = bZeroAcceleration ? Velocity : Velocity.ProjectOnToNormal(Acceleration.GetSafeNormal());
     LastVelocity.Z = 0;
 
     FVector LastLocation = CurrentLocation;
 
     int Iterations = 0;
     while (Iterations < MaxSimulationIterations)
     {
         Iterations++;
 
         const FVector OldVel = LastVelocity;
 
         // Only apply braking if there is no acceleration, or we are over our max speed and need to slow down to it.
         if (bZeroAcceleration)
         {
             // subdivide braking to get reasonably consistent results at lower frame rates
             // (important for packet loss situations w/ networking)
             float RemainingTime = TimeStep;
             const float MaxTimeStep = (1.0f / 33.0f);
 
             // Decelerate to brake to a stop
             const FVector RevAccel = (bZeroBraking ? FVector::ZeroVector : (-BrakingDeceleration * LastVelocity.GetSafeNormal()));
             while (RemainingTime >= MIN_TICK_TIME)
             {
                 // Zero friction uses constant deceleration, so no need for iteration.
                 const float dt = ((RemainingTime > MaxTimeStep && !bZeroFriction) ? FMath::Min(MaxTimeStep, RemainingTime * 0.5f) : RemainingTime);
                 RemainingTime -= dt;
 
                 // apply friction and braking
                 LastVelocity = LastVelocity + ((-Friction) * LastVelocity + RevAccel) * dt;
 
                 // Don't reverse direction
                 if ((LastVelocity | OldVel) <= 0.f)
                 {
                     LastVelocity = FVector::ZeroVector;
                     break;
                 }
             }
 
             // Clamp to zero if nearly zero, or if below min threshold and braking.
             const float VSizeSq = LastVelocity.SizeSquared();
             if (VSizeSq <= 1.f || (!bZeroBraking && VSizeSq <= FMath::Square(10)))
             {
                 LastVelocity = FVector::ZeroVector;
             }
         }
         else 
         {
             FVector TotalAcceleration = Acceleration;
             TotalAcceleration.Z = 0;
 
             // Friction affects our ability to change direction. This is only done for input acceleration, not path following.
             const FVector AccelDir = TotalAcceleration.GetSafeNormal();
             const float VelSize = LastVelocity.Size();
             TotalAcceleration += -(LastVelocity - AccelDir * VelSize) * Friction;
             // Apply acceleration
             LastVelocity += TotalAcceleration * TimeStep;
         }
 
         LastLocation += LastVelocity * TimeStep;
 
         // Clamp to zero if nearly zero, or if below min threshold and braking.
         const float VSizeSq = LastVelocity.SizeSquared();
         if (VSizeSq <= 1.f
             || (LastVelocity | OldVel) <= 0.f)
         {
             OutStopLocation = LastLocation;
             return true;
         }
     }
 
     return false;
 }

more ▼

answered Feb 21 '18 at 06:08 PM

avatar image

王智禺
36 3 5

avatar image Highflex Feb 21 '18 at 08:21 PM

Has been a while since i messed with this but thank you for the detailed example!

From what i remember, i did something like this too but i was never able to predict the 100% exact position just as you described above.

Your added example looks very interesting and might give me some new ideas on how to approach it.

I am going to experiment with it very soon and see how it goes.

Thanks again.

avatar image Soumik_25 Nov 03 '18 at 05:35 AM

Hey I tried to predict the stop location, and its very accurate I say, about 0.02 error when stopping

avatar image duofuan Feb 11 '19 at 08:20 AM

Cool! Can you share how to do this?

avatar image HeruNoTsurugi Feb 11 '19 at 08:31 AM

I'm also interested in this as well. I saw your results on YouTube and I must say I'm impressed. The one I built using a simple kinimatic equation is off by around 1 unit. Be really interested in learning how you are getting .02 accuracy

avatar image Soumik_25 Feb 11 '19 at 11:36 AM

This is the C++ code: and I use: MaxWalkSpeed = 450.f; MaxAcceleration = 1600.f; BrakingDecelerationWalking = 1600.f; BrakingFrictionFactor = 1.f; GroundFriction = 0.0f;

and its run on average 60FPS. in editor

// Get and store current world delta seconds for later use float Local_WorldDeltaSecond = UGameplayStatics::GetWorldDeltaSeconds(this);

     // Small number break loop when velocity is less than this value
     float SmallVelocity = 10.f * FMath::Square(Local_WorldDeltaSecond);
 
     // Current velocity at current frame in unit/frame
     FVector CurrentVelocityInFrame = Velocity * Local_WorldDeltaSecond;
 
     // Store velocity direction for later use
     FVector CurrentVelocityDirection = Velocity.GetSafeNormal2D();
 
     // Current deacceleration at current frame in unit/fame^2
     FVector CurrentDeaccelerationInFrame = (CurrentVelocityDirection * BrakingDecelerationWalking) * FMath::Square(Local_WorldDeltaSecond);
 
     // Calculate number of frames needed to reach zero velocity and gets its int value
     int StopFrameCount = CurrentVelocityInFrame.Size() / CurrentDeaccelerationInFrame.Size();
 
     // float variable use to store distance to targeted stop location
     float StoppingDistance = 0.0f;
 
     // Do Stop calculation go through all frames and calculate stop distance in each frame and stack them
     for (int i = 0; i <= StopFrameCount; i++)
     {
         //Update velocity
         CurrentVelocityInFrame -= CurrentDeaccelerationInFrame;
 
         // if velocity in XY plane is small break loop for safety
         if (CurrentVelocityInFrame.Size2D() <= SmallVelocity)
         {
             break;
         }
 
         // Calculate distance travel in current frame and add to previous distance
         StoppingDistance += CurrentVelocityInFrame.Size2D();
     }
     
     // return stopping distance from player position in previous frame
     return CharacterLocation + CurrentVelocityDirection * StoppingDistance;

}

avatar image HeruNoTsurugi Feb 11 '19 at 08:49 PM

Brilliant! Thanks it works perfectly for me.

avatar image Soumik_25 Feb 15 '19 at 01:09 PM

If any one interested check this video on my chanel:link text

I tried to create the paragon animation system...

avatar image dandezign Feb 15 '19 at 02:30 PM

I tried Translating this into BP I failed massively lol maybe you could make a tutorial showing how you did it in c++ :) on line 32 I get hugeeeee numbers but that's using bp I haven't done it in c++ cause idk but I can read c++ and understand it just a bit.

avatar image Soumik_25 Feb 15 '19 at 03:04 PM

I think you can do that in BP because i made a prototype of this prediction system in BP. I love to share that but un fortunately Many of my previous projects got deleted or corupted..

And also paragon animation sytem project is not completed yet. There are many bugs thats killing me.. 1.Triggers that I used to predict start stop location jump locations works 90% of the time I don't know why. 2. There is also a bug with jump and spin transaction that crashes the whole editor to crash... :(

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question