Very good, I've always used Root Motion in my controllers, I find it easier to use the movement of the animations than to synchronize everything with the movement of Rigidbody or CharacterController, but I've never been able to do that with Agents. you saved me again, mandatory.
Awesome 😎! I actually didn't realize so many people used root motion. I had always done it with just a playback of the animation and setting velocity. After diving in deep into it on this video I see why a lot of people prefer root motion!
This helped so much! Thanks for making these videos, super essential to my project :) The end thoughts about the importance of BlendTree setup finally fixed my jitter issues i've had for months now
Thank you for a truly helpful tutorial, haven't really seen anyone tackle this problem in such a simple way Also to anyone who is still having troubles syncing agent and animator even with root motion working, make sure all your armature bone scales are set to 1, I had root bone resized to make character the desired size, but it caused further desync, hope this helps
I'm using this tutorial for a series of NPC cats. it works wonderful except during a cat's jump attacks. The Navmesh agent launches the cat further than it should, then the cat snaps back into the NavMesh spot. I don't know how to fix this.
Awesome video, but I'm trying to make the animations work with rotation and I'm noticing that velocity.x is very sparadic and fast moving. This makes it near impossible to "smooth" animations as it flicks from say 0 to 1 constantly. Even trying to smooth this out using a lerp I'm finding very jittery motion when turning. I think the issue here is that the nextPosition from the agent is forever changing, so velocity.x is flicking back and forth very quickly. Have you had any luck with root motion rotations?
Hmm... I didn't have that problem with 2d velocity when the animation had turns. In this repository you can see a 2d velocity including turning animations with "The Dude". github.com/llamacademy/ai-series-part-42. What you are describing sounds like perhaps you have a zero stopping distance on the NavMeshAgent that is resulting in the NavMeshAgent never coming to a complete stop so they are toggling between moving slightly and being completely still.
@@LlamAcademy I have the same problem and i dont have a stopping distance of 0, the transitions between the animations on my blendtree are super stuttery, also i did put a in place walking animation
@Emanuel Polsky Hey - yea sorry I thoguht I'd written a reply to LlamAcademy on this, but clearly never hit send! Ops. I'm running a little by memory here, as I do'nt have the code to hand. I ended up using a range of -1 (left) to 1 (right) and checking the agents position in relationship to where they were and applying left/right within that range. That meant the animations would always -1 or 1 on the X axis in the animator. This worked pretty smoothly. I'm using it for animal AI though, so the player is never controlling the animal. It may not be the best solution for people trying to applying root motion to a player controlled character.
@@willthomas4909 thank you for the suggestion but that way it would work only if the animator have only one kind of turn, so it wouldn't have accuracy turn
Very helpful. I had some trouble because I set the Agent.updateRotation = false; Which hosed everything, once I commented it out everything worked well.
Hey 👋! Since I know you're super excited about that topic, I wanted to let you know the way I was planning to implement that didn't work out how I wanted to. I need to restart it from the drawing board so that video is not on the immediate horizon
Thank you very much for this video!! Can you please help me how to rotate the agent with proper animations without changing its position. I mean I need a Function which will take a Vector3 point and the function will only rotate the agent towards that position without changing its position, not SetDestination. I can do transform.rotation, I have seen the LookAt coroutine in the Enemy Attacking video, but that's not using turning animations, how to do this, what value need to pass for velX, velY ? Pls help me. Or give me the function pls.
I think you can just play your Root Motion animation to turn. That can probably be achieved with some turn left/right floats provided to the Animator that play in-place root motion turning animations. If you provide velX/velY the agent will move because that's tied to an animation that moves the enemy!
Hello, When I put my script into a child component that references the navmesh agent and Root parent Transform. My character Stutters but when I put everything in the root transform everything is smooth. Any insights?
further debugging. I noticed that when I put the movement script into the child component. The navmesh agent is moving faster than the root transform. so in the root I had a capsule collider and this was the one that was not catching up with the navmesh agent
Great video's sir. i am using your this project for my game. i add dude as enemy and add walk animations in place of running. now i add in it he can see the player and chase him and add chasing on sound sound. but i don't know how i do in multi can you please guide me something .
I was having an incredibly hard time trying to figure out why my characters were not tracking the NavMeshAgent properly. They were always sliding to the left. Make sure you have the Root Transform Rotation of your animations Based Upon (at Start) Original rather than Body Orientation. If e.g. your character animation is walking forward but their root bone is rotated about the Y axis, root motion will apply relative to Z+ which is not necessarily forward.
How do i make the agent walk towards a chair and sit down properly. Currently what happens is the agent moves towards the chair and constantly bumps into the collider of the chair.
"Sit down" is a non-navigation function. So I would recommend to have a scripted sequence to control the sit down process. If you have a Root Motion animation to sit down, you just have to get the character into the right position to start the sit down sequence, then disable the NavMeshAgent (maybe colliders too) and perform the sit down animation.
Great tutorial. One question tho. Does setting up root animation to control Agent movement affects the the real-time neighbor Agent avoidance in anyway? So far mine are completely ignoring each other and just bump in one another, although the priorities are randomized.
It's been a little bit but I'm pretty sure it considered the avoidance even using root motion here. Agents with mixed priorities tend to have worse results (in my opinion) than if they all have the same priority. With mixed priority some agents, seemingly randomly, will just push other agents out of the way.
for the interruption source, you actually dont need to set it at all for this specific case as it makes no difference i believe. probably it could be useful when there are more than 1 transition from idle animation otherwise pointless.
Sadly this doesn't work when you have a walking animation thrown in the mix. I'm doing a 2D blend tree with walk (half speed) - walk - run. If I do either walk or run it's perfect, but the two of them don't work.
Doesnt work. I added your EnemyMovement script to my enemy and i set in update agent.SetDestination to target the player position but when reach a corner of the map goes back some time, then continues the path. Dont know why is bouncing back when reach a corner
Maybe. That’s mostly setting up your state machine in the Animator. I can add some more in-depth Animator configuration topic to the list of ones to cover
@@LlamAcademy also, the scripting, regarding different settings, the animation might have foot sliding, i encountered different issues and difficulties with this kind of system.
Great video as always and I appreciate what you are doing. Foot slip annoys me so I have been toying with this issue for a while and this is what I have come up with. Attach the navMeshAgent to the npc's Animator.transform and turn the npc towards the navMeshAgent.steeringTarget while having the navAgent's speed = 0 using the following code: public void TurnToNavTarget() { var navTarget = navMeshAgent.steeringTarget; Vector3 direction = (navTarget - navMeshAgent.transform.position).normalized; if (direction.x != 0 && direction.z != 0) { Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z)); navMeshAgent.transform.rotation = Quaternion.Slerp(navMeshAgent.transform.rotation, lookRotation, Time.deltaTime * 5); } } This way the NavMeshAgent is always in the same position relative to the npc. I have the npc model a child of a GameObject that has all it's scripts so the only thing my npc model has attached to it is it's Animator, a NavMeshAgent and any scripts that use the "OnAnimatorIK" function.
Does this work for Horses/Cars?(can we map velocity to root motion in similar manner?) Where you don't have the independence of moving in all direction?
It’s based on the speed values you plan on using, the movement speed of your animation, and how you want the game to feel. I usually start at -1, 0, 1 for the 1D and see how it works. There’s some guesswork and checking the result involved.
@@LlamAcademy Dang, that's pretty difficult since animations can come in a massive variety and speeds. So, would you normally just use the velocity on the animation itself?
You would drive the Animator parameter based on the keyboard / game pad input in a similar way to how we are having the NavMeshAgent drive the Animator properties based on the desired velocity and direction.
So for my next trick, I am going to rebuild my enemy AI script to predominantly use RigidBody but use NavMesh to find pathing. I am not to where I want to use ragdolls quite yet, but I do want to use rigidbody to simulate knock back. In my case I noticed a few things, 1 the agent gets wonky in cases where the player is out of reach of any locations the AI can say is reachable but are still in range of the AI. So say my player jumps on a ledge, the AI will instead of disengaging they'll do random stuff. Now if they all disengaged or just all did the same things it would make sense. But they all do random things. Next is knock back, part of what makes them do random things is the interaction between rigidbody and navmesh. Simply these two things hate each other. The forces will be applied but the agent will attempt to go to a location at the same time. The enemies can hit each other so I guess they hit each other and do random things. To fix this I read a bit about putting the navmesh on a child object and using Rigidbody.Move to handle the rest. However upon researching I found a ton of stuff on ragdolls but not much on just enemy AI rb controllers.
Hey! For a knockback effect, you can attach a rigidbody with IsKinematic = true and swap it to IsKinematic = false when the knockback should occur, apply the force and disable the NavMeshAgent the same frame. Once you want the knockback effect to be completed (maybe velocity has slowed down near zero?), do NavMeshAgent.Warp() to the current location and swap the Rigidbody back to IsKinematic = true. That should give you pretty close to what you are looking for. The enemies doing random stuff when the player moves to an unreachable location is something you have to handle in your code. A way to handle it is instead of naively setting NavMeshAgent.SetDestination to the player's location, you can first use NavMesh.SamplePosition to see if there is a point nearby. If not, you can handle that however you wish. It could be that you just let them continue on to their previous spot, or do something else entirely. I hope these suggestions can help you!
@@LlamAcademy Thank you, I got something a little different working so far. The agent is on but not in control of the AI. Instead it creates a path which I send a child of the AI to follow along with. The RB then adjusts its angle and velocity to the child's position. It still hasn't resulted in the knock back effect yet but right now the RB and it have great locomotion.
@@LlamAcademy yea, i did and the white dudes are running around but the Big Daddy is gone and im not sure if i can replace him with something else not loosing nice animation fit :(
Nice, pretty advanced tutorial, but nice :) Let me know if you have something in this subject at Udemy (im a subscriber that plataform). thanks so much.
You're very welcome 😃. I do not have any Udemy course, everything I have is public and free on TH-cam and GitHub. If you want to support monetarily there is only the TH-cam SuperThanks and Patreon monthly or one time support options.
This is the best video on this subject, and I've been looking for a while.
You deserve all the love in the world, thank you❤❤❤❤❤
you cracked the code! I've wanted to fix issues between nav/anim for 2 years. Thank you so much.
Very good, I've always used Root Motion in my controllers, I find it easier to use the movement of the animations than to synchronize everything with the movement of Rigidbody or CharacterController, but I've never been able to do that with Agents. you saved me again, mandatory.
Awesome 😎! I actually didn't realize so many people used root motion. I had always done it with just a playback of the animation and setting velocity. After diving in deep into it on this video I see why a lot of people prefer root motion!
@@LlamAcademy For the zombies in my game that have an irregular walking pattern, it was a real necessity 😵
I'm very happy to be coming to this video to remind myself how to do this :D
This helped so much! Thanks for making these videos, super essential to my project :)
The end thoughts about the importance of BlendTree setup finally fixed my jitter issues i've had for months now
🧡 that's awesome to hear! I love to hear stories like this!
Thank you for a truly helpful tutorial, haven't really seen anyone tackle this problem in such a simple way
Also to anyone who is still having troubles syncing agent and animator even with root motion working, make sure all your armature bone scales are set to 1, I had root bone resized to make character the desired size, but it caused further desync, hope this helps
Dude you are a lifesaver!
😃 thanks! I knew it was an important topic to cover!
I'm using this tutorial for a series of NPC cats. it works wonderful except during a cat's jump attacks. The Navmesh agent launches the cat further than it should, then the cat snaps back into the NavMesh spot. I don't know how to fix this.
Thank you! You just made my game a little better.
Great Video as always. You have only forgot to include it in the "AI Tutorial Series" Playlist
Oh! Thank you for that! I will add it right away
Awesome video, but I'm trying to make the animations work with rotation and I'm noticing that velocity.x is very sparadic and fast moving. This makes it near impossible to "smooth" animations as it flicks from say 0 to 1 constantly. Even trying to smooth this out using a lerp I'm finding very jittery motion when turning. I think the issue here is that the nextPosition from the agent is forever changing, so velocity.x is flicking back and forth very quickly. Have you had any luck with root motion rotations?
Hmm... I didn't have that problem with 2d velocity when the animation had turns. In this repository you can see a 2d velocity including turning animations with "The Dude". github.com/llamacademy/ai-series-part-42. What you are describing sounds like perhaps you have a zero stopping distance on the NavMeshAgent that is resulting in the NavMeshAgent never coming to a complete stop so they are toggling between moving slightly and being completely still.
@@LlamAcademy I have the same problem and i dont have a stopping distance of 0, the transitions between the animations on my blendtree are super stuttery, also i did put a in place walking animation
did you ever found a solution ? because I still have this problem
@Emanuel Polsky Hey - yea sorry I thoguht I'd written a reply to LlamAcademy on this, but clearly never hit send! Ops.
I'm running a little by memory here, as I do'nt have the code to hand. I ended up using a range of -1 (left) to 1 (right) and checking the agents position in relationship to where they were and applying left/right within that range. That meant the animations would always -1 or 1 on the X axis in the animator. This worked pretty smoothly. I'm using it for animal AI though, so the player is never controlling the animal. It may not be the best solution for people trying to applying root motion to a player controlled character.
@@willthomas4909 thank you for the suggestion but that way it would work only if the animator have only one kind of turn, so it wouldn't have accuracy turn
Very helpful.
I had some trouble because I set the Agent.updateRotation = false;
Which hosed everything, once I commented it out everything worked well.
This is just for movement but if tries to attack the attack animations will fail
High quality video
Waiting for brust compiler and job system tutorial ❤
Hey 👋! Since I know you're super excited about that topic, I wanted to let you know the way I was planning to implement that didn't work out how I wanted to. I need to restart it from the drawing board so that video is not on the immediate horizon
@@LlamAcademy oh really....ok then i will wait. thanks for the update ❤️
Thank you very much for this video!!
Can you please help me how to rotate the agent with proper animations without changing its position.
I mean I need a Function which will take a Vector3 point and the function will only rotate the agent towards that position without changing its position, not SetDestination. I can do transform.rotation, I have seen the LookAt coroutine in the Enemy Attacking video, but that's not using turning animations, how to do this, what value need to pass for velX, velY ? Pls help me. Or give me the function pls.
I think you can just play your Root Motion animation to turn. That can probably be achieved with some turn left/right floats provided to the Animator that play in-place root motion turning animations.
If you provide velX/velY the agent will move because that's tied to an animation that moves the enemy!
Hello, When I put my script into a child component that references the navmesh agent and Root parent Transform. My character Stutters but when I put everything in the root transform everything is smooth. Any insights?
further debugging. I noticed that when I put the movement script into the child component. The navmesh agent is moving faster than the root transform. so in the root I had a capsule collider and this was the one that was not catching up with the navmesh agent
Great video's sir. i am using your this project for my game. i add dude as enemy and add walk animations in place of running. now i add in it he can see the player and chase him and add chasing on sound sound. but i don't know how i do in multi can you please guide me something .
If you mean multiplayer, you'll need to look into Mirror, Fishnet, NetCode for GameObjects, or maybe Photon
I was having an incredibly hard time trying to figure out why my characters were not tracking the NavMeshAgent properly. They were always sliding to the left. Make sure you have the Root Transform Rotation of your animations Based Upon (at Start) Original rather than Body Orientation. If e.g. your character animation is walking forward but their root bone is rotated about the Y axis, root motion will apply relative to Z+ which is not necessarily forward.
How do i make the agent walk towards a chair and sit down properly. Currently what happens is the agent moves towards the chair and constantly bumps into the collider of the chair.
"Sit down" is a non-navigation function. So I would recommend to have a scripted sequence to control the sit down process. If you have a Root Motion animation to sit down, you just have to get the character into the right position to start the sit down sequence, then disable the NavMeshAgent (maybe colliders too) and perform the sit down animation.
Great tutorial. One question tho. Does setting up root animation to control Agent movement affects the the real-time neighbor Agent avoidance in anyway?
So far mine are completely ignoring each other and just bump in one another, although the priorities are randomized.
It's been a little bit but I'm pretty sure it considered the avoidance even using root motion here. Agents with mixed priorities tend to have worse results (in my opinion) than if they all have the same priority. With mixed priority some agents, seemingly randomly, will just push other agents out of the way.
for the interruption source, you actually dont need to set it at all for this specific case as it makes no difference i believe. probably it could be useful when there are more than 1 transition from idle animation otherwise pointless.
I think you are right, good call out
Sadly this doesn't work when you have a walking animation thrown in the mix. I'm doing a 2D blend tree with walk (half speed) - walk - run. If I do either walk or run it's perfect, but the two of them don't work.
What problem do you have adding in a run? There’s conceptually no difference between walk and run
Is there a way to add a speed boost to the root motion? Say my sprinting speed is 2 and when I get a boost it will go to 7. How can I accomplish that?
I think for root motion animation this requires either different animations or adjusting the animator playback speed.
Doesnt work. I added your EnemyMovement script to my enemy and i set in update agent.SetDestination to target the player position but when reach a corner of the map goes back some time, then continues the path. Dont know why is bouncing back when reach a corner
Sounds like maybe a misconfiguration of some of these available params. I had similar issues initially before tweaking the values.
Awesome program
Thanks 🙏
Great tutorial! Can you make one even more complex? With animation turns in place, different states, jumping?
Maybe. That’s mostly setting up your state machine in the Animator. I can add some more in-depth Animator configuration topic to the list of ones to cover
@@LlamAcademy also, the scripting, regarding different settings, the animation might have foot sliding, i encountered different issues and difficulties with this kind of system.
@@LlamAcademy Hi, I'm back with another question. At min 5:50 the character has a flick. Have you managed to fix that?
Great video as always and I appreciate what you are doing. Foot slip annoys me so I have been toying with this issue for a while and this is what I have come up with.
Attach the navMeshAgent to the npc's Animator.transform and turn the npc towards the navMeshAgent.steeringTarget while having the navAgent's speed = 0 using the following code:
public void TurnToNavTarget()
{
var navTarget = navMeshAgent.steeringTarget;
Vector3 direction = (navTarget - navMeshAgent.transform.position).normalized;
if (direction.x != 0 && direction.z != 0)
{
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
navMeshAgent.transform.rotation = Quaternion.Slerp(navMeshAgent.transform.rotation,
lookRotation, Time.deltaTime * 5);
}
}
This way the NavMeshAgent is always in the same position relative to the npc. I have the npc model a child of a GameObject that has all it's scripts so the only thing my npc model has attached to it is it's Animator, a NavMeshAgent and any scripts that use the "OnAnimatorIK" function.
Cool, thanks for sharing that!
Does this work for Horses/Cars?(can we map velocity to root motion in similar manner?) Where you don't have the independence of moving in all direction?
I think it could work by limiting the angularSpeed of the NavMeshAgent
@@LlamAcademy how do you predict angularSpeed from let's say car wheel got a limitation of 45 degree angle?
Very cool thanks 💝😋
You're welcome 😊
How do you determine the beat values for the blend tree?
It’s based on the speed values you plan on using, the movement speed of your animation, and how you want the game to feel. I usually start at -1, 0, 1 for the 1D and see how it works. There’s some guesswork and checking the result involved.
@@LlamAcademy Dang, that's pretty difficult since animations can come in a massive variety and speeds. So, would you normally just use the velocity on the animation itself?
@@riekumar6999 I think that would be a good starting point!
how to make this work with keyboard/gamepad input?
You would drive the Animator parameter based on the keyboard / game pad input in a similar way to how we are having the NavMeshAgent drive the Animator properties based on the desired velocity and direction.
So for my next trick, I am going to rebuild my enemy AI script to predominantly use RigidBody but use NavMesh to find pathing.
I am not to where I want to use ragdolls quite yet, but I do want to use rigidbody to simulate knock back.
In my case I noticed a few things, 1 the agent gets wonky in cases where the player is out of reach of any locations the AI can say is reachable but are still in range of the AI. So say my player jumps on a ledge, the AI will instead of disengaging they'll do random stuff.
Now if they all disengaged or just all did the same things it would make sense. But they all do random things.
Next is knock back, part of what makes them do random things is the interaction between rigidbody and navmesh. Simply these two things hate each other. The forces will be applied but the agent will attempt to go to a location at the same time.
The enemies can hit each other so I guess they hit each other and do random things.
To fix this I read a bit about putting the navmesh on a child object and using Rigidbody.Move to handle the rest.
However upon researching I found a ton of stuff on ragdolls but not much on just enemy AI rb controllers.
Hey! For a knockback effect, you can attach a rigidbody with IsKinematic = true and swap it to IsKinematic = false when the knockback should occur, apply the force and disable the NavMeshAgent the same frame. Once you want the knockback effect to be completed (maybe velocity has slowed down near zero?), do NavMeshAgent.Warp() to the current location and swap the Rigidbody back to IsKinematic = true. That should give you pretty close to what you are looking for.
The enemies doing random stuff when the player moves to an unreachable location is something you have to handle in your code. A way to handle it is instead of naively setting NavMeshAgent.SetDestination to the player's location, you can first use NavMesh.SamplePosition to see if there is a point nearby. If not, you can handle that however you wish. It could be that you just let them continue on to their previous spot, or do something else entirely.
I hope these suggestions can help you!
@@LlamAcademy
Thank you, I got something a little different working so far.
The agent is on but not in control of the AI. Instead it creates a path which I send a child of the AI to follow along with.
The RB then adjusts its angle and velocity to the child's position.
It still hasn't resulted in the knock back effect yet but right now the RB and it have great locomotion.
Thats a pitty I cannot run this project out of the box :| Its a bit of a problem for a begginer :(
Why not? You should be able to pull it off GitHub and run it out of the box.
@@LlamAcademy yea, i did and the white dudes are running around but the Big Daddy is gone and im not sure if i can replace him with something else not loosing nice animation fit :(
Oh dear, I managed to animate my own character and it works flawlesly :) Thanks!
Nice, pretty advanced tutorial, but nice :) Let me know if you have something in this subject at Udemy (im a subscriber that plataform). thanks so much.
You're very welcome 😃. I do not have any Udemy course, everything I have is public and free on TH-cam and GitHub. If you want to support monetarily there is only the TH-cam SuperThanks and Patreon monthly or one time support options.
pretty sure this whole video was just an excuse for you to say "the dude" in a funny voice 100 times haha.
😂