Support Forum

Agent not moving when "Enable Rotation" off and a script rotates it

I want to do a custom rotation on an AIPath agent in 2D space.

For some reason, when I put a script on the agent, that does literally nothing except:

public void FixedUpdate()
     agent.transform.rotation = Quaternion.Lerp(agent.transform.rotation, toRotation, Time.fixedDeltaTime * rotationSpeedMax);

the agent just stops moving. The path is calculated correctly. If I disable this script, it instantly starts moving. It just doesn’t make any sense - why does rotation interfere with position?

How should I rotate properly?


Hmm, that is very weird. Can you post a screenshot of your agent settings?

I revisited the problem and tried simulating it on basic setup with a cube. It’s still broken.

The setup:

  • grid graph on XY plane (sidescrolling game - using this for an underwater scene to give you a picture)
  • agent AIPath:
  • moving the cube via simple “AI Destination Setter” from your package
  • there is a kinematic rigidbody on the cube
  • and this simple script
private void FixedUpdate()
	transform.forward = Vector3.up;

The problem seems to be with orientation. We are intending the forward blue vector to be the moving direction for the agent. There seems to be no working option for us in the combo box (Y axis forward 2D, Z axis forward 3D). The way I circumvented that before is having the rotation and the model on a separate gameobject that was following the AIPath agent. However this just complicated our life a lot because of root motion animations, which is why I’m trying to solve the problem again.

As soon as I disable the script and reset the rotation to 0 0 0, the cube starts moving again. Another thing that’s weird is changing the script to LateUpdate makes it move wrong (slower and not to the destination).

Hmmm, maybe there’s some code that relies on the rotation even though ‘enable rotation’ is disabled.
Try to enable the rotation setting, but set ai.updateRotation = false; and see if anything changes.

Ok, that works… Maaaan, you owe my employer like over a day of my salary thinking the problem is on my end :smiley: :smiley: I would not think for a second that “enable rotation” and “update rotation” both exist and do something completely different.

This is weird, as soon as I started using our rotation code:

private void FixedUpdate()
	transform.rotation = Quaternion.LookRotation(agent.Velocity2D, Vector3.up);

instead of

private void FixedUpdate()
	transform.forward = Vector3.up;

the cube is not moving again.

Ok, so this is pretty sad/funny. I reproduced the problem in a completely separate project, using non beta version of A* that can actually be debugged because it’s not a package. I went through the entire AIPath code and found out the problem seems to be here:

// Assign the final position to the character if we haven't already set it (mostly for performance, setting the position can be slow)
if ((positionDirty1 || positionDirty2) && updatePosition) {
	// Note that rigid.MovePosition may or may not move the character immediately.
	// Check the Unity documentation for the special cases.
	if (rigid != null) rigid.MovePosition(currentPosition);
	else if (rigid2D != null) rigid2D.MovePosition(currentPosition);
	else tr.position = currentPosition;

Now, I don’t know why MovePosition may sometimes not move immediately, and would really like to know, but you seem to know about the fact that this is possible (based on code comments). But then it seems like you’re relying on it to change position immediately, since right after that you call this function:

protected void UpdateVelocity () {
	var currentFrame = Time.frameCount;

	if (currentFrame != prevFrame) prevPosition2 = prevPosition1;
	prevPosition1 = position;
	prevFrame = currentFrame;

which basically sets velocity as the difference of two positions that are identical, as MovePositon hasn’t changed them, making velocity zero.

I don’t think this matters much, but long story short, if I rewrite the above code to not use MovePosition and use regular positon = x, the cube starts moving again. This explains why it also helps to just uncheck “isKinematic” on the RB to make the cube move.

This is all really weird, do you have any insight?

I can send you the cube test project, if you’d like.

Thank you. I’ll try to look into this.

Here’s the test cube project:

This is a big priority for us now, as the only fix I’ve found so far is chaning your code and since it is a package and I can’t version it in GIT :frowning:

Hi! Any update? … (character limit)

Hmm, I wonder if when you call transform.rotation this will override whatever local matrix the physics engine has calculated. So anything that MovePosition sets will be overriden by your rotation call. I think it only tracks “has the transform changed”, not the position and rotation individually.

Try to call Physics.SyncTransforms() before the transform.rotation = ... line and see if that changes anything.

I call it after the transform.rotation and it works! (I think script execution order may play a role here)

Not sure about performance implications, but there’s always the backup option of making the change in your code, copying the A* package out as regular asset files and just giving up on plugin updates.