I have (what I hope is) a simple problem, concerning syncing movement with a NavMeshAgent and Animator rootmotion.
I have a simple animator controller, containing only two states (at the moment), “Idle” and “Run”, which I want to use in conjunction with a navmesh agent in the following way:
The movement speed should be determined by the agent, but the actual movement should be done by the controller so that the controller can sync the animation speed to avoid gliding of feet etc.
Turning should be handled by the agent, the animator should just keep playing the run animation if the agent is moving, else it should play the idle animation. There is no concept of walking bakwards, straifing etc.
So what I am looking for is some way to get the speed of the agent, pass it in to the controller, adjust the animation play speed and then use rootMotion to move the agent forward at the correct speed (which is the actual speed of the agent, so I guess the agent can just keep moving if it can “trust” that the animator play speed is correct).
I have looked at several examples available in the assets store, including the locomotion projects, but I cannot get it to work properly. It also seems like overkill to use those controllers/scripts since they are made to handle turning etc. (It also makes the agent behave in a way that does not meet the desired behaviour I am after).
I’d appreciate any help to get me started! Also, if there is any alternative way to handle this problem I am open to suggestions. The reason that I want to let the agent handle the actual movement is that I have built a system which uses agents for local avoidance etc, which includes turning the agent on and off as well as manipulating it in different ways.
Instead of two states (Idle and Run), use one state that’s a blend tree. Blend on Speed, where 0 is Idle and 1 is Run.
Set NavMeshAgent.updatePosition=false and updateRotation=true to allow the agent to control rotation and the animator controller to control position via root motion.
NavMeshAgents tend to rotate only when moving, so it shouldn’t rotate while idle (which would look unnatural).
It might take a little more tweaking once you get the basic functionality working. You might want to tamp down on Speed when you get within the target range so the character stops nicely.
_animator.SetFloat("Speed", Vector3.Distance(navMeshAgent.desiredVelocity, new Vector3(0, 0, 0)));
since desiredVelocity is a Vector3 and SetFloat expects a float or int.
Thanks again for your help.
*Edit. There is still the problem though that the playback speed of the animation isn’t dependent on the movement speed of the game object, which will result in gliding if the movement speed is too fast or slow :S
(In my situation, using the value 6 as _baseSpeed works well… I guess it’s depending on the animation… There is probably some dynamic way of finding this out though)
Hi! How can I synchronize the animation in speed, I have a blend (idle and walk), there is a navmeshagent, I want to set the speed navmeshagent.speed, and so that the speed of the animation corresponds to the speed
I know this is a necro, but this is the #1 Google hit on the thing.
The above works well (though I wonder why using desiredVelocity and not velocity ?) - but only for forward speed.
I’ve been looking for a way to sync turn speed (rotation) as well, and the only real answer is on https://docs.unity3d.com/Manual/nav-CouplingAnimationAndNavigation.html - which strikes me as insanely complicated for what should be a one-liner like above. Also, the values this produces in the animator jump all over the place, resulting in terrible jagged animations.
Is there a solution to hand over the navmesh agents angular speed to the animator? The actual “angularSpeed” value contains the MAX angularSpeed as set in the inspector, not the CURRENT one.
If you’re allowing the NavMeshAgent to move the character, track the rotation manually. Record the current rotation so you can compare it to the next frame’s rotation. Then you can apply this to the animator. If it’s jagged, turn off root motion. If you want to use root motion, turn off the NavMeshAgent’s updatePosition and updateRotation, and set animator parameter values to handle let the animator handle them.