For some reason the NavMeshAgent bounding cylinder always drops to the ground. Do you have an idea how to keep it a certain distance above ground for flying enemies? Otherwise they jump over knee high obstacles, even though they are visually above it. Thanks and greetings from Germany!
Unfortunately the cylinder must be on the ground. That is the representation of the Agent on the NavMesh. One way to make the flying enemy be able to seamlessly fly over knee-high obstacles you can attach a NavMeshModifier to the obstacle and ignore it from the build for the flying enemy's NavMesh.
In this case they're climbing up the side of staircase, so eventually there will be some kind of "jump" since they can fly up/down the gaps. You can minimize that by adjusting what they can fly up/down or you can smooth that out some by checking the "corners" property of the NavMeshAgent. If the Y value changes dramatically between two points in a short distance you can lerp the baseOffset of the agent.
Can you consider to make a vid on how to use the enemy-spawner to respawn enemies when entering a trigger or any other kind of event appears. Also would be nice to set the number of spawns for each enemy-type...
Really struggling with this one, im watching it over and over but I cant get the mesh to simply fly over the geometry. Does this only work with meshes built in probuilder?
No. This should work with any meshes. The important part is the bake settings of the surface and the agent configuration. Those two allow the flying agents to “walk over” some meshes that others cannot
@@LlamAcademy Ok I see where I got this wrong now, it was the base offset which was the important part, i increased the base offset and it works perfectly! What I actually would like to implement is something akin to an enemy that is a hybrid of flying but also humanoid scale. Think of something like a gargoyle. It's base offset is quite low but its able to fly over things to reach its destination quicker if need be. I would also like to know if the flying agent used in this video can also lower its base offset in order to go under things?
@@ty-xq7bl Yeah, you can manipulate the base offset while the game is running and get effects like flying under things. You'll start needing a pretty sophisticated method of determining what it should be doing if you want it to dynamically make those decisions. For flying AI that can "transform" from one type to another you can see in games like StarCraft 2 and the Viking, it spawns as an Air unit, and only if the ground below it is traversable by the ground type can you make it swap. It doesn't automatically swap from one to another. If that mechanic can work for your game, then I think it is feasible to have 2 NavMeshAgent configurations for the unit and just make it toggle between the two based on the "Air" or "Land" style.
So I found that using SphereCast vs using a Sphere with a collider interacts less with other things that might react to triggers or collision or raycast.
Be careful with that - to achieve a similar result I would expect you to use Physics.OverlapSphere instead of Spherecast. If you spherecast while inside of another object you will not get that object as a hit!
@@LlamAcademy Yep, you are right, I was using Physics.OverlapSphere; I should have double checked before typing. I just remembered having tried using the Sphere child collider and got interactions I didn't want. Raycast for example would still see the sphere's collider, instead of redoing all the systems I chose Overlap.
Hey Liam, so I can't recall which video it was but you employed a pattern for Coroutines that I thought was amazing: I then abused the heck out of it and got called out on the GC it created, my guess is the context you were using it in was different. Anyway in the case that it wasn't I felt like I should share a gc minimal version of the same thing: ```cs private void Start() { SomeAction(); } private void SomeAction() { //Damage Was Taken damage = 5; StartTrackingSomething(); } private void StartTrackingSomething() { if (check != null) return; check = StartCoroutine(PlayRoutine()); } IEnumerator PlayRoutine() { while(health > 0 && damage > 0) { health--; damage--; yield return end; if (damage < 2 && health > damage + 5) SomeAction(); Debug.Log("Health: " + health); } } That will prevent running an existing coroutine while updating its values to suit whatever new values are in play.
you'll see that I check if check is null similar with your pattern but instead of going forward and Stopping check I just return out of the method. end by the way is WaitForSeconds end = new WaitForSeconds(.5f); With this you have 0 GC in process by 64 GC from when the Coroutine was started.
@@LlamAcademy Actually I made an even better way with 0 GC. Do you have a Discord? Or is it okay if I post it here again, it looks funky as heck on YT.
@@LlamAcademy EH, never mind, I don't see you posting about a Discord so I guess there isn't one. Here is the script: public class Test : MonoBehaviour { private WaitForSeconds end = new WaitForSeconds(.5f); private Coroutine check; private int health = 100; private int damage = 0; private Func testRoutine; private void Start() { testRoutine = () => StartCoroutine(PlayRoutine()); SomeAction(); } private void SomeAction() { //Damage Was Taken damage = 5; StartTrackingSomething(); } private void StartTrackingSomething() { if (check != null) return; check = testRoutine.Invoke(); } IEnumerator PlayRoutine() { while(health > 0 && damage > 0) { health--; damage--; yield return end; if (damage < 2 && health > damage + 5) SomeAction(); } } }
Videos are always great. I've noticed you're getting more publicity and likes now. Hopefully it will pick it up more soon. I have a question about flying enemies with wandering AI and was wondering if you are able to help? I've essentially put together a wandering AI script parts along with your main flying Enemy script and it does work but the AI goes mental and Rotates on Z Axis, this also means that the Health bar following the player, also appears to do the same thing. if(isWandering == false) { StartCoroutine(Wander()); } if (isRotatingRight == true) { transform.Rotate(transform.up * Time.deltaTime * rotationSpeed); } if (isRotatingLeft == true) { transform.Rotate(transform.up * Time.deltaTime * rotationSpeed); } if (isWalking == true) { rb.AddForce(transform.forward * movementSpeed); }
Thanks 😊! I think you might just want to lock the rotation on the X/Z axes on the RigidBody if you are adding force like that to keep them vertical until sometime comes when they need to rotate on X or Z axis. That’s just some checkboxes in the Inspector. Let me know if that helps!
@@LlamAcademy Dude, thanks. That definitely has kept it sturdier. I considered the Z but yeah X seems to have also corrected it and allows it to fly. Still got to try and make the flying more natural. Plus the health/damage system but it's coming together slowly enough. Thanks for your help again : ]
For some reason the NavMeshAgent bounding cylinder always drops to the ground. Do you have an idea how to keep it a certain distance above ground for flying enemies? Otherwise they jump over knee high obstacles, even though they are visually above it.
Thanks and greetings from Germany!
Unfortunately the cylinder must be on the ground. That is the representation of the Agent on the NavMesh.
One way to make the flying enemy be able to seamlessly fly over knee-high obstacles you can attach a NavMeshModifier to the obstacle and ignore it from the build for the flying enemy's NavMesh.
Hey... you rock. Thanks for being awesome. Seriously. Love your intro too!
great video
How can i avoid the flying object jump like here?: 0:24
In this case they're climbing up the side of staircase, so eventually there will be some kind of "jump" since they can fly up/down the gaps. You can minimize that by adjusting what they can fly up/down or you can smooth that out some by checking the "corners" property of the NavMeshAgent. If the Y value changes dramatically between two points in a short distance you can lerp the baseOffset of the agent.
Can't wait to see what happens when you introduce episode 11 now that you've run out of fingers.
Ha! I struggled with that one for a little bit!
how do i find navmeshsurface and navmeshmodifier? im using unity 2020
If you mean how to make the NavMesh components, I cover this in part 1 of the AI Series: th-cam.com/video/aHFSDcEQuzQ/w-d-xo.html
Can you consider to make a vid on how to use the enemy-spawner to respawn enemies when entering a trigger or any other kind of event appears.
Also would be nice to set the number of spawns for each enemy-type...
Absolutely! Planning one already on scaling enemy stats and having spawn configurations
By the way this week's video is on that exact topic! th-cam.com/video/UWeZ0js8UwE/w-d-xo.html
Really struggling with this one, im watching it over and over but I cant get the mesh to simply fly over the geometry. Does this only work with meshes built in probuilder?
No. This should work with any meshes. The important part is the bake settings of the surface and the agent configuration. Those two allow the flying agents to “walk over” some meshes that others cannot
@@LlamAcademy I will keep watching until I get it thanks
@@LlamAcademy Ok I see where I got this wrong now, it was the base offset which was the important part, i increased the base offset and it works perfectly!
What I actually would like to implement is something akin to an enemy that is a hybrid of flying but also humanoid scale. Think of something like a gargoyle. It's base offset is quite low but its able to fly over things to reach its destination quicker if need be.
I would also like to know if the flying agent used in this video can also lower its base offset in order to go under things?
@@ty-xq7bl Yeah, you can manipulate the base offset while the game is running and get effects like flying under things. You'll start needing a pretty sophisticated method of determining what it should be doing if you want it to dynamically make those decisions.
For flying AI that can "transform" from one type to another you can see in games like StarCraft 2 and the Viking, it spawns as an Air unit, and only if the ground below it is traversable by the ground type can you make it swap. It doesn't automatically swap from one to another. If that mechanic can work for your game, then I think it is feasible to have 2 NavMeshAgent configurations for the unit and just make it toggle between the two based on the "Air" or "Land" style.
So I found that using SphereCast vs using a Sphere with a collider interacts less with other things that might react to triggers or collision or raycast.
Be careful with that - to achieve a similar result I would expect you to use Physics.OverlapSphere instead of Spherecast. If you spherecast while inside of another object you will not get that object as a hit!
@@LlamAcademy Yep, you are right, I was using Physics.OverlapSphere; I should have double checked before typing. I just remembered having tried using the Sphere child collider and got interactions I didn't want. Raycast for example would still see the sphere's collider, instead of redoing all the systems I chose Overlap.
Thanks so much
Hey Liam, so I can't recall which video it was but you employed a pattern for Coroutines that I thought was amazing:
I then abused the heck out of it and got called out on the GC it created, my guess is the context you were using it in was different. Anyway in the case that it wasn't I felt like I should share a gc minimal version of the same thing:
```cs
private void Start()
{
SomeAction();
}
private void SomeAction()
{
//Damage Was Taken
damage = 5;
StartTrackingSomething();
}
private void StartTrackingSomething()
{
if (check != null)
return;
check = StartCoroutine(PlayRoutine());
}
IEnumerator PlayRoutine()
{
while(health > 0 && damage > 0)
{
health--;
damage--;
yield return end;
if (damage < 2 && health > damage + 5)
SomeAction();
Debug.Log("Health: " + health);
}
}
That will prevent running an existing coroutine while updating its values to suit whatever new values are in play.
you'll see that I check if check is null similar with your pattern but instead of going forward and Stopping check I just return out of the method.
end by the way is WaitForSeconds end = new WaitForSeconds(.5f);
With this you have 0 GC in process by 64 GC from when the Coroutine was started.
Thanks for sharing that! ❤️
@@LlamAcademy Actually I made an even better way with 0 GC. Do you have a Discord? Or is it okay if I post it here again, it looks funky as heck on YT.
@@LlamAcademy EH, never mind, I don't see you posting about a Discord so I guess there isn't one. Here is the script:
public class Test : MonoBehaviour
{
private WaitForSeconds end = new WaitForSeconds(.5f);
private Coroutine check;
private int health = 100;
private int damage = 0;
private Func testRoutine;
private void Start()
{
testRoutine = () => StartCoroutine(PlayRoutine());
SomeAction();
}
private void SomeAction()
{
//Damage Was Taken
damage = 5;
StartTrackingSomething();
}
private void StartTrackingSomething()
{
if (check != null)
return;
check = testRoutine.Invoke();
}
IEnumerator PlayRoutine()
{
while(health > 0 && damage > 0)
{
health--;
damage--;
yield return end;
if (damage < 2 && health > damage + 5)
SomeAction();
}
}
}
Videos are always great. I've noticed you're getting more publicity and likes now. Hopefully it will pick it up more soon.
I have a question about flying enemies with wandering AI and was wondering if you are able to help? I've essentially put together a wandering AI script parts along with your main flying Enemy script and it does work but the AI goes mental and Rotates on Z Axis, this also means that the Health bar following the player, also appears to do the same thing.
if(isWandering == false)
{
StartCoroutine(Wander());
}
if (isRotatingRight == true)
{
transform.Rotate(transform.up * Time.deltaTime * rotationSpeed);
}
if (isRotatingLeft == true)
{
transform.Rotate(transform.up * Time.deltaTime * rotationSpeed);
}
if (isWalking == true)
{
rb.AddForce(transform.forward * movementSpeed);
}
Thanks 😊!
I think you might just want to lock the rotation on the X/Z axes on the RigidBody if you are adding force like that to keep them vertical until sometime comes when they need to rotate on X or Z axis. That’s just some checkboxes in the Inspector. Let me know if that helps!
@@LlamAcademy Dude, thanks. That definitely has kept it sturdier. I considered the Z but yeah X seems to have also corrected it and allows it to fly. Still got to try and make the flying more natural.
Plus the health/damage system but it's coming together slowly enough.
Thanks for your help again : ]