Characters Jerky and getting stuck when FPS gets towards 60fps

Hi all,

I am having a few issues with my characters becoming jerky, stuttering and being unable to move as the frame rate moves towards 60fps. I am emulating this by enabling VSYNC, although the same issues occur with VSYNC disabled is the frame rate drops.

A bit of Background: The game is a 2D top-down game using 2DToolkit. There is quite a bit of animation in the characters which is driven using Mecanim but I can’t see how this would affect things.

My character ‘follow’ code is basically a copy/paste of the included AIFollow class. (See below my version. All other functions within the script are the same as the standard AIFollow)

/** Update is called once per frame */
public void Update () {

	if (path == null || pathIndex >= path.Length || pathIndex < 0 || !canMove) {
		return;
	}
	
	//Change target to the next waypoint if the current one is close enough
	Vector3 currentWaypoint = path[pathIndex];
	currentWaypoint.z = tr.position.z;
	while ((currentWaypoint - tr.position).sqrMagnitude < pickNextWaypointDistance*pickNextWaypointDistance) {
		pathIndex++;
		if (pathIndex >= path.Length) {
			//Use a lower pickNextWaypointDistance for the last point. If it isn't that close, then decrement the pathIndex to the previous value and break the loop
			if ((currentWaypoint - tr.position).sqrMagnitude < (pickNextWaypointDistance*targetReached)*(pickNextWaypointDistance*targetReached)) {
				if (canMove)
                    ReachedEndOfPath ();
				return;
			} else {
				pathIndex--;
				//Break the loop, otherwise it will try to check for the last point in an infinite loop
				break;
			}
		}
		currentWaypoint = path[pathIndex];
		currentWaypoint.z = tr.position.z;
	}

    Vector3 dir = currentWaypoint - tr.position;
    
    // Rotate towards the target
    tr.rotation = Quaternion.Slerp(tr.rotation, Quaternion.LookRotation(dir, Vector3.forward), _rotationSpeed * _mbpGame.GameTimer.DeltaTimeGame());
    tr.eulerAngles = new Vector3(0, 0, tr.eulerAngles.z);

   
    MinusRotatorGO.rotation = Quaternion.identity;
    SymbolRotatorGO.rotation = Quaternion.identity;
    

    Vector3 forwardDir = -transform.up;
    forwardDir = forwardDir * _speed;
    forwardDir *= Mathf.Clamp01(Vector3.Dot(dir.normalized, -tr.up));
    forwardDir.z = 0;

    tr.Translate(forwardDir * _mbpGame.GameTimer.DeltaTimeGame(), Space.World);

}

One point to note is the Rotation and Movement code: I am multiplying the values by _mbpGame.GameTimer.DeltaTimeGame(). This is just a wrapper around Time.deltaTime which multiplies deltaTime by a float, either 1f, 2f or 3f. This is so I can give the player the ability to speed up the game. I think this is where the problem may be originating as the issue is not there when it is purely multiplied by 1 (just deltaTime). deltaTime * 2f makes the issue worse and deltaTime * 3f makes the characters stutter and get totally stuck. With VSYNC disabled the fps is about 1000 on my machine and there are no issues at all. It’s just as the fps drops towards 60.

Any help in tracking down what could be causing this issue (i’m hoping it is a ‘school boy error’)!

Kindest regards in advance,
Matt.

After further investigation I think the issue is with the ‘Rotate toward the target’ and the forward movement translations. Due to Z being up I think there is an issue here as the rotation is shaky and seems to keep tracking (doesnt seem to do this in the Grid Example within A* Pathfinding Project), but I can’t for the life of me seem to fix it (tried all I can think of now and am clutching at straws!)

Any help with rotation around the Z axis and movement would be greatly received.

  • Matt.

Hi

The reason is probably that between the time when it requests the path and when it gets the calculated path back, it has moved a bit. So it might have moved past the first waypoint already, in that case it might decide that it should turn around to get to the first waypoint and then turn around again to continue follow the rest of the path, this obviously leads to stuttering.

The solution that the included movement scripts (AIPath and RichAI) uses is that when they get the path back, the simulate movement from the point they requested the path and where they are now and see if they get close to the first waypoint (or any other waypoints), if so, they consider those points as reached already.

I think I am having another possibly connected issue…

Sometimes, not often but frequently enough to be noticeable, when a new path is requested my character doesn’t move at all but the result comes back that the destination has been reached. This new path doesn’t have to be close to the starting position, it could be on the other side of my game map. ReachedEndOfPath(); seems to only be being called from the Update() function within your AIFollow class so it appears to be thinking the character has reached the end… or could it be that it thinks the path is not valid?

Regards,
Matt.

Hi

I don’t think that is a connected issue.
Hard to say without knowing a bit more.
It could be that it couldn’t find a good path, so it finds the best path it can, which might be to move to the node it is currently standing on, if that was the closest one it could reach to the target.

However you should probably try to use some other scripts since the AIFollow class has been deprecated for a while now. Try the AIPath script.