Why does AIPath not work with timescale?

Hello,

I am using AIPath.cs and in its update function if you have a character controller it will not apply Time.deltaTime to the dir variable. CalculateVelocity seems to only use it as a clamp. I have noticed my objects will not move any faster when I increase timescale above 1. Am I missing something here?

    public virtual void Update () {
        if (!canMove) { return; }

        Vector3 dir = CalculateVelocity(GetFeetPosition());

        //Rotate towards targetDirection (filled in by CalculateVelocity)
        RotateTowards(targetDirection);

        if (rvoController != null) {
            rvoController.Move(dir);
        } else
        if (controller != null) {
            controller.SimpleMove(dir);
        } else if (rigid != null) {
            rigid.AddForce(dir);
        } else {
            tr.Translate(dir*Time.deltaTime, Space.World);
        }
    }

Hi

CharacterController.SimpleMove takes a velocity, not a movement delta, so a multiplication by Time.deltaTime should not be done for that case. See https://docs.unity3d.com/ScriptReference/CharacterController.SimpleMove.html.
I am not sure why it is not working for you however. Does it work the other way (i.e if you set timescale to a value smaller than 1)?

Ok figured it out. The code below is found in AIPath.cs in CalculateVelocity() ~Line 437. It clamps how much you move based upon Time.deltaTime. With a larger timescale the large Time.deltaTime gets. The larger deltaTime gets the more you are clamping your movement for that frame to 0. Thoughts?

if (Time.deltaTime > 0) {
         sp = Mathf.Clamp(sp, 0, targetDist/(Time.deltaTime*2));
 }
 return forward*sp;

Hi

What that piece of code does is that it makes sure that it does not move more than half the distance to the target in a single frame to avoid overshooting. I don’t think it is the source of your problem.

So if the timeScale is set high enough in reference to our speed that we would actually travel more than half the distance that frame, then what? I am assuming a situation where timeScale is at 10x and I may be having lower framerate as well. What else would you think is the issue? Commenting out the clamp does allow my objects to move at 10x timescale. Although I agree there is a risk of overshooting.

Well. I’m not sure if the AIPath script would be stable at such high velocities.
You can try it, but I cannot guarantee that it will work well.

The AILerp script might be a better fit since it has no risk of overshooting as it simply interpolates along the path.

I have switched to AILerp. There is one issue from what I can tell. Repath rate is affected by timescale. If my timescale is high and framerate low, it is possible to repath every frame that I would have moved. When repathing, previousMovementStartTime is set to Time.time. Thus if we repath every frame, we end up not moving at all.

I understand that we have framerate issues at 10x timescale. Like most development cycles sometimes those optimizations are done at a later time. Is it possible to allow AILerp to interpolate even if repathing every frame? I was considering making repathRate not affected by timescale but then that would only shrink the chances of this happening, not solve them.

I would like to keep interpolatePathSwitches to true as without it the the object jumps ahead every repath.

I would suggest however that when targetReached is set to true that you return the target’s position. As currently with this issue it is possible for targetReached to be true and we aren’t even at the destination.

Separate issue: I noticed that even after my objects have reached their destination and a repath happens, that they will want to rotate towards the new repath location on Update() even though we are close enough to not move at all. Thus I added to only rotate in update if targetReached is false.

I will try to debug the issue with AILerp not moving at all if recalculating the path every frame.