- Home /
Precise distance calculation with high timeScale for NavMeshAgents?
So here is my situation: While agentA goes toward agentB, and if the distance between them is less than 0.8, agentA and agentB will stop. agentB can also be moving and both game objects are NavMeshAgents actors moving by setting destination using Unity's NavMesh system. Here is the code I'm using to calculate the distance:
function Update(){
if( Vector3.Distance(agentA.position, agentB.position) < 0.8)){
//Stop both objects
}
}
Now, everything works great until I increase the timeScale. The higher the timeScale, the more agentA will 'miss' the proper 0.8 distance from agentB. I'm assuming that the reason why this happens is because the Update() function runs less times per frame and so it lacks precision once the timeScale is increased.
Is this correct? And if so, how can I make it so that agentA will stop at the right distance independently from the timeScale?
Have you tried calling FixedUpdate ins$$anonymous$$d of Update? FixedUpdate runs independently of the framerate. It might not work in this situation, but it's worth a shot.
Just tried it and it makes no difference. FixedUpdate is only used for Rigidbody calculations, right? Not sure how it could help in this situation.
Answer by Bunny83 · Sep 20, 2016 at 09:47 PM
Well, the problem is not that Update runs less often, but since you increased the timescale the movement steps get larger. Usually Time.deltaTime accumulates to "1.0" after one second. If you set the timescale to "2.0" deltaTime will accumulate to "2.0" after one realtime second. Likewise the gametime (Time.time) will also advance 2 seconds for every realtime second.
Since the steps get larger it has a similar effect as running on a low framerate. As solution you can use "super sampling". This should be possible by setting updatePosition to false for your agent and manually update the position each frame. nextPosition will give you the target position that your agent want to reach this frame. So you have to move it manually to this position. However instead of just moving it there in one step, you would use a loop and do it in several steps.
var agentAagent : NavMeshAgent;
function Update()
{
var superSampleCount = 2*Time.timeScale;
var delta = 1f / superSampleCount;
var oldPos = agentA.position;
for(var f = 0f; f < 1.0f; f += delta)
{
agentA.position = Vector3.Lerp(oldPos, agentAagent.nextPosition, f);
if( Vector3.Distance(agentA.position, agentB.position) < 0.8))
{
// Stop both objects
agentAagent.nextPosition = agentA.position;
break; // break out of the loop to stop in place.
}
}
}
This assumes that this script actually runs on "AgentA". As you can see each frame the agent will simply move to it's target position for the current frame, but it moves in smaller steps. The number of steps increases as Time.timeScale increases so the result should be more or less the same.
By default i let it perform two cycles per frame. So at timeScale =2 it will perform 4 cycles.
Note: It's important that you break out of the loop when you want to stop the agent at the current position.
What if I wanted to use a similar solution just to prevent an agent from over shooting when going from A to B? (independently from going to a target?)
Your answer
Follow this Question
Related Questions
How to prevent Navmesh Agent from overshooting destination with high Time.TimeScale? 1 Answer
How to detect if NavAgent has reached hit.point? (2) Distance doesn't work? 1 Answer
Find closest "item" object by NavMesh navigation distance performantly 0 Answers
Can we use Navmesh for Player without relying on SetDestination ? 0 Answers