{"id":437,"date":"2021-10-08T11:13:24","date_gmt":"2021-10-08T11:13:24","guid":{"rendered":"https:\/\/globalgoodplay.com\/?p=437"},"modified":"2022-11-03T13:45:01","modified_gmt":"2022-11-03T13:45:01","slug":"learn-to-create-enemy-ai-systems-with-a-few-lines-of-code-in-unity-game-engine","status":"publish","type":"post","link":"https:\/\/globalgoodplay.com\/?p=437","title":{"rendered":"Learn To Create Enemy AI Systems With A Few Lines Of Code In Unity Game Engine"},"content":{"rendered":"<div class=\"elementor elementor-14524\" data-elementor-type=\"wp-post\" data-elementor-id=\"14524\">\n<section class=\"elementor-section elementor-top-section elementor-element elementor-element-acd2c35 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"acd2c35\" data-element_type=\"section\">\n<div class=\"elementor-container elementor-column-gap-default\">\n<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d2e7470\" data-id=\"d2e7470\" data-element_type=\"column\">\n<div class=\"elementor-widget-wrap elementor-element-populated\">\n<div class=\"elementor-element elementor-element-594bf36 elementor-widget elementor-widget-text-editor\" data-id=\"594bf36\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>There are different types of enemy AI that you can create in Unity, from the very basic enemies that move between two points all the way to machine learning where your enemies are learning from the events in the game and behaving accordingly.<\/p>\n<p>In this post we are going to learn about AI in Unity by creating basic and intermediate enemy AI behaviour.<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f753782 elementor-widget elementor-widget-heading\" data-id=\"f753782\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Download Assets And Complete Project For This Tutorial<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6fb8268 single-post-download elementor-widget elementor-widget-wc-elements\" data-id=\"6fb8268\" data-element_type=\"widget\" data-widget_type=\"wc-elements.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"woocommerce\">\n<div class=\"single-product\" data-product-page-preselected-id=\"0\">\n<div class=\"woocommerce-notices-wrapper\"><\/div>\n<div id=\"product-16493\" class=\"product type-product post-16493 status-publish first instock product_cat-uncategorized downloadable virtual product-type-simple\">\n<div class=\"summary entry-summary\">\n<h1 class=\"product_title entry-title\">Unity Enemy AI Tutorial<\/h1>\n<p class=\"price\">\n<style>\n    .single-product div.product .summary form.cart { display: none!important; }<br \/>\n  <\/style>\n<\/p>\n<div class=\"somdn-download-wrap\">\n<form class=\"somdn-download-form\" action=\"https:\/\/awesometuts.com\/product\/unity-enemy-ai-tutorial\/\" method=\"post\"><input name=\"somdn_download_key\" type=\"hidden\" value=\"MTY1NzA0OTU5Mw==\" \/><\/p>\n<\/form>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6771c6d elementor-widget elementor-widget-text-editor\" data-id=\"6771c6d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the downloaded folder you will find the assets for the tutorial, the finished project, and the starter project I prepared for you to follow this tutorial.<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e35fb05 elementor-widget elementor-widget-heading\" data-id=\"e35fb05\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Important Information Before We Start<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-48e07b2 elementor-widget elementor-widget-text-editor\" data-id=\"48e07b2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>One of the labels for this tutorial is beginner, however this is not a tutorial for complete beginners.<\/p>\n<p>I expect you to know how to create basic games in Unity, but you are a beginner when it comes to AI programming in Unity. So it is mandatory that you know how to code in C# and how to use Unity and its interface.<\/p>\n<p>If you don\u2019t know any of these things, you can learn how to code in C# in my C# tutorial series starting with variables, and then you can move on to create your first game in Unity with my Rainy Knifes tutorial.<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-84163be elementor-widget elementor-widget-heading\" data-id=\"84163be\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Starting With Basic Enemy AI \u2013 Shooting<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c28b752 elementor-widget elementor-widget-text-editor\" data-id=\"c28b752\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>One of the most common AI feature is shooting. So let\u2019s take a look at our first example by opening the scene named 1 \u2013 Basic Enemy AI Shooting inside the Assets -&gt; Scenes folder.<\/div>\n<div><\/div>\n<div>I\u2019ve already prepared all the elements we need for this example, such as the enemy, bullet, and the enemy shooter script.<\/div>\n<div><\/div>\n<div>Inside the Assets -&gt; Scripts folder, open the SpiderShooter script in Visual Studio.<\/div>\n<div><\/div>\n<div>First, we are going to create a basic AI shooting where the spider enemy will shoot a bullet ever X amount of seconds.<\/div>\n<div><\/div>\n<div>Above the Start function declare the following variables:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-12a3a6b elementor-widget elementor-widget-text-editor\" data-id=\"12a3a6b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>First we need the bullet that the spider will shoot, that is why we have declared the spiderBullet variable. I\u2019ve already created the bullet and saved it in the Prefabs folder and we will attach it to the appropriate slot in a few moments.<\/div>\n<div><\/div>\n<div>The bulletSpawnPos is the position where we will spawn the bullet, and for that we will create an empty object, position it where the spider bullet is going to be spawned and the attach it in the appropriate slot in the Inspector tab.<\/div>\n<div><\/div>\n<div>The min and max shoot wait time are self explanatory. We are going to randomize the shooting of the bullet and the wait time is going to be a random range between the min and max shoot wait time. And we will use the waitTime variable to keep track when to shoot the bullet.<\/div>\n<div><\/div>\n<div>Before we do all of this, we need to attach the bulletPrefab and the bulletSpawnPos variable. Starting with the bulletPrefab, in the Assets -&gt; Prefabs folder, drag the Spider Shooter Bullet prefab in the Spider Bullet slot for the SpiderShooter script in the Inspector tab:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3c55472 elementor-widget elementor-widget-image\" data-id=\"3c55472\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 1\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/09a1500f2208a881e933868f7f389d068e503d7455dbc57f329ce3608bda5eda.jpeg\" alt=\"Img 1\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4df66bf elementor-widget elementor-widget-text-editor\" data-id=\"4df66bf\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Next, create an empty game object and make it a child of the Spider Shooter object. Name the child object Bullet Spawn Position and set the following values for the Position in the Transform component:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7469f33 elementor-widget elementor-widget-image\" data-id=\"7469f33\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 2\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/55e43413f09007f315fb81c6ba465038684f3b1e12243f699e8e0edffe072c93.jpeg\" alt=\"Img 2\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b9c64d5 elementor-widget elementor-widget-text-editor\" data-id=\"b9c64d5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>This will position the Bullet Spawn Position object where the mouth of the spider shooter are, and when we shoot the bullet it will look like the bullet is coming out of the spider\u2019s mouth.<\/div>\n<div><\/div>\n<div>The last step is to attach the Bullet Spawn Position object in the appropriate slot in the SpiderShooter script:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-220c13e elementor-widget elementor-widget-image\" data-id=\"220c13e\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 3\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/fb7b013836f7c3df02e0708327cf41f4fdfb284dd8df0c70b9d465ef7600aac1.jpeg\" alt=\"Img 3\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e0b4fef elementor-widget elementor-widget-text-editor\" data-id=\"e0b4fef\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Going back in the SpiderShooter script, we are going to create the shooting functionality by adding the following lines of code<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5cff3a7 elementor-widget elementor-widget-code-highlight\" data-id=\"5cff3a7\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5deac7d elementor-widget elementor-widget-text-editor\" data-id=\"5deac7d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The Shoot function simply uses the Instantiate function to create a new copy out of the spiderBullet game object. It will spawn it at the bulletSpawnPos variable position, and it will set the rotation values to 0 for X, Y, and Z using Quaternion.identity.<\/p>\n<p>Inside the Update we will create a timer that will shoot the bullet every X seconds:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a3e57a0 elementor-widget elementor-widget-text-editor\" data-id=\"a3e57a0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Time.time on line 3, is the amount of time passed since the game started. This value always increases every second we play the game, and we can use it to create effective timers.<\/div>\n<div><\/div>\n<div>So, if Time.time is greater than waitTime, on line 5 we will first set a new value for the waitTime by using the current value of Time.time and adding to it the random value returned between min and max shoot wait time.<\/div>\n<div><\/div>\n<div>Let\u2019s assume that the current value of Time.time is 5, and the returned random value between min and max shoot wait time is 3, this means that the new value of waitTime is 8, and given the fact that during that calculation the current value of Time.time is 5, we will need to wait another 3 seconds before we shoot a new bullet.<\/div>\n<div><\/div>\n<div>And to shoot the bullet, we simply call the Shoot function that we created and explained what it does.<\/div>\n<div><\/div>\n<div>Before we test this out, we can also delay the shooting of the bullet by seting a new value for waitTime in the Start function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-aa5048d elementor-widget elementor-widget-text-editor\" data-id=\"aa5048d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The reason why I set a new value for waitTime before we start the game is because the current value of waitTime is zero(0), which means as soon as we run the game the spider will shoot a bullet, and to delay that we set a new value for waitTime.<\/div>\n<div><\/div>\n<div>Let\u2019s run the game to test it out:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5cac990 elementor-widget elementor-widget-text-editor\" data-id=\"5cac990\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>As you can see, after every X amount of seconds the spider is shooting the bullet.<\/p>\n<p>If you don\u2019t like the wait time between each shoot, you can change the values for min and max shoot wait time because we added SerializeField in their declaration which means we can change their values in the Inspector tab:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2cda96d elementor-widget elementor-widget-image\" data-id=\"2cda96d\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 4\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/e0288a4023edaf98f1a565ffe928166457b1c69316a237438452f49186f0f247.jpeg\" alt=\"Img 4\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-bee6d3f elementor-widget elementor-widget-text-editor\" data-id=\"bee6d3f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Lastly, I will leave the first version of the EnemyShooter script below for you to have as a reference to compare your code to mine, or if you want to copy paste the code in your project:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-1a64dae elementor-widget elementor-widget-heading\" data-id=\"1a64dae\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Optimizing Enemy AI Shooting \u2013 Object Pooling Technique<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-92ff1c4 elementor-widget elementor-widget-text-editor\" data-id=\"92ff1c4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>While the shooting functionality works, it can lead to our game being slow if we have too much shooting enemies in the game.<\/p>\n<p>The reason for that is because we are using the Instantiate function which creates new objects every time, plus we are not disposing the bullets that we already created and this can lead to many game objects being in the game, not doing anything or having any functionality yet taking our game resources and this can make our game slower.<\/p>\n<p>To fix this problem, we use a programming technique called pooling. The idea of pooling is to create a pool of objects, in our case a pool of bullets, and when we need a new bullet, we will reuse one of the bullets stored in the pool.<\/p>\n<p>If by any chance all the bullets in the bullet are not available for use e.g. they are currently being used, then we will create a new bullet and store it in the pool and repeat the process.<\/p>\n<p>To create this system, first we need to add new variables in the SpiderShooter script. Above the Start function add the following lines:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e1ee1d7 elementor-widget elementor-widget-text-editor\" data-id=\"e1ee1d7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>First we create a new list that will store game objects. A list is like an array, with the difference that a list is flexible, meaning we can add new and remove old elements from that list.<\/p>\n<p>Between the &lt;&gt; we type the type of object we want to store in the list, in our case a GameObject. This can be modified in case we have a Bullet script for example, and we only want to store game objects that have the Bullet script attached on them, then, instead of typing:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a268c26 elementor-widget elementor-widget-text-editor\" data-id=\"a268c26\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>We would type:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5e82cef elementor-widget elementor-widget-text-editor\" data-id=\"5e82cef\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The canShoot variable will be used to control the shooting so that we don\u2019t shoot two bullets at the same time instead of only one.<\/div>\n<div><\/div>\n<div>bulletIndex variable will represent the index of the bullet in the list that we will use.<\/div>\n<div><\/div>\n<div>And initialBulletCount value will determine how many bullets we will create and store in the list when the game starts.<\/div>\n<div><\/div>\n<div>From this, you can conclude that the list is actually the pool holding the bullets, and since a list is like an array, we can use indexes to access elements in the list.<\/div>\n<div><\/div>\n<div>When the game starts, the first thing we need to do is create the initial bullets and store them in the pool. In the Start function, add the following lines of code:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0d7671f elementor-widget elementor-widget-text-editor\" data-id=\"0d7671f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>First we create the newBullet variable and we don\u2019t set a value for it, which means it is equal to null. We need the newBullet variable so that we can add the newly created bullet in the list.<\/p>\n<p>Of course, since this is programming, there are always multiple ways how you can achieve a certain result. We can rewrite this code so that we don\u2019t have to create the newBullet variable at all:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e361854 elementor-widget elementor-widget-code-highlight\" data-id=\"e361854\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2c982a3 elementor-widget elementor-widget-text-editor\" data-id=\"2c982a3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>We can use Instantiate function as a parameter in the Add function from the list, because the Instantiate function returns the game object it has created, and the Add function of the list stores the object in the list.<\/p>\n<p>To deactivate the newly created bullet, we can use i variable declared in the for loop and access the bullet we just created to deactivate it.<\/p>\n<p>The reason why we deactivate the bullets as soon as we create them is because if don\u2019t do that, they will be spawned in the level from the very start which is not something that we want.<\/p>\n<p>You can test that by removing<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-1471121 elementor-widget elementor-widget-code-highlight\" data-id=\"1471121\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d671df0 elementor-widget elementor-widget-text-editor\" data-id=\"d671df0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>from the code and see the outcome. Rewrite the Shoot function so that it uses the bullets from the bullets list instead of instantiating new ones:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6ee07a8 elementor-widget elementor-widget-code-highlight\" data-id=\"6ee07a8\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c246caa elementor-widget elementor-widget-text-editor\" data-id=\"c246caa\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>We are going to use a while loop to loop through the list and search for a bullet that is not active in the scene e.g. it used SetActive function and passed false as the parameter.<\/p>\n<p>Because of that, every time we call the Shoot function first we need to set the value of canShoot to true. We also set the value of bulletIndex to zero(0) because we will start searching from the first element in the list.<\/p>\n<p>The activeInHierarchy property of the game object returns true if the game object is active in the scene e.g. game, and it returns false if the game object is not active in the scene.<\/p>\n<p>You will notice that we used an exclamation mark in front of the activeInHierarchy property, and the exclamation mark will make what\u2019s after it, the opposite, meaning if activeInHierarchy returns true, then the exclamation mark will make it the opposite which is false, and if activeInHierarchy returns false, the exclamation mark will make it the opposite which is true.<\/p>\n<p>So essentially we are searching for a game object, in our case a bullet, that is NOT active in the hierarchy so that we can activate it and use it. And this is the whole point of pooling technique because we are reusing game objects instead of creating new ones which saves performance.<\/p>\n<p>We are using the bulletIndex to access the specific index in the list, and since we set the starting value of bulletIndex to 0 on line 4, we will first test if the element at index 0 is not active in the hierarchy.<\/p>\n<p>To activate a game object, we simply call SetActive and pass true as the parameter and it will make the game object active in the game again.<\/p>\n<p>Since we are simulating the effect of a bullet, we need to reposition the bullet we just activated so that it falls from the bulletSpawnPos, and this will make it look like the spider is shooting new bullets.<\/p>\n<p>When we finish with that, we need to set canShoot to false, so that we don\u2019t spawn more than one bullet, and we use break to exit outside the while loop.<\/p>\n<p>When the code reaches the break statement, it will simply stop executing the loop, and all the code that is below the break statement will not get executed.<\/p>\n<p>In our case, since we are using the canShoot variable to control the while loop, we can remove the break statements, but I put them in the code for this example just to explain what they are doing and that you can use them for that purpose.<\/p>\n<p>In case we don\u2019t find any bullets that are not active in the hierarchy, then we will create a new bullet and store it in the bullets list. This way, we will only create new bullets if all current bullets are active and being used, and this is very hard to happen when we get to a certain amount of bullets in the game.<\/p>\n<p>Before we test out the game, one thing to note is that I added SerializeField above the bullets list declaration, I did this so that we can see directly in the Inspector tab when the bullets are created and added to the list, so when we test the game make sure that you pay attention to that.<\/p>\n<p>Now run the game and let\u2019s test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a1156bd elementor-widget elementor-widget-text-editor\" data-id=\"a1156bd\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>When started the game we had only two spider bullets in the bullets list, and the more the spider enemy shoot, the more bullets were created in the list.<\/p>\n<p>The reason for this is, we need to deactivate the bullet objects. Inside the Assets -&gt; Scripts folder, create a new C# script and name it SpiderBullet. Open the SpiderBullet script in Visual Studio and add the following lines of code<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-af1d69d elementor-widget elementor-widget-text-editor\" data-id=\"af1d69d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>In OnTriggerEnter2D we are testing if the bullet collides with the ground, or if the bullet collides with the player object, and if that happens we will deactivate the bullet.<\/p>\n<p>Of course, in a real game, you would not use hard code string values instead you would have a more efficient way to compare strings to each other but I am not going to go into that in this tutorial.<\/p>\n<p>Make sure that you attach the BulletScript to the Spider Shooter Bullet prefab inside the Assets -&gt; Prefabs folder.<\/p>\n<p>As for the Ground Holder game object, I\u2019ve set his tag to Ground:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-291eee4 elementor-widget elementor-widget-image\" data-id=\"291eee4\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 5\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/b71986ca5f70d5869bc2de073ab029813c99e7e8e3627479d08caba1eaf0536d.jpeg\" alt=\"Img 5\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ddd1fe9 elementor-widget elementor-widget-text-editor\" data-id=\"ddd1fe9\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>but for your project always double check if you set the tags correctly when you testing tags in your code.<\/div>\n<div><\/div>\n<div>Let\u2019s test the game now:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-98612b4 elementor-widget elementor-widget-text-editor\" data-id=\"98612b4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The result we have now is the same we had in the beginning when we used Instantiate, but the difference now is that the spider enemy is shooting the same way, but instead of creating new bullets every time, we are reusing the ones we already have.<\/p>\n<p>Before we move forward, I will leave the new version of the SpiderShooter script as a reference:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0505913 elementor-widget elementor-widget-heading\" data-id=\"0505913\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Triggering AI Actions With Colliders<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-abd9db1 elementor-widget elementor-widget-text-editor\" data-id=\"abd9db1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>For the first example the spider enemy is shooting with the help of a timer. But what if we don\u2019t want a functionality like that in our game. Let\u2019s say we want to trigger the enemy to attack if the player is passing by.<\/p>\n<p>We can do that in couple of ways, one of them is using a collider. Attach a Box Collider 2D on the Spider Shooter game object in the Hierarchy tab, check the Is Trigger checkbox and set the following values for the size and position of the collider:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5b8da64 elementor-widget elementor-widget-image\" data-id=\"5b8da64\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 6\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/d19785f5e011553c642bf493fe1203bd35faafc88491712e13088abae1c1b533.jpeg\" alt=\"Img 6\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-090f817 elementor-widget elementor-widget-text-editor\" data-id=\"090f817\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Since we are not going to use the timer functionality, we can remove the Update function and all the code that is inside. In the Start function we will only leave the code that will create the initial bullets when the game starts:<span style=\"font-size: revert; color: initial;\">Since we checked the Is Trigger checkbox for the Box Collider 2D that is attached on the Spider Shooter, we can use OnTriggerEnter2D to detect collision between the player and the spider enemy, when they collide, the spider enemy will shoot.<\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-861cb4c elementor-widget elementor-widget-text-editor\" data-id=\"861cb4c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>I have already prepared the player game object and I\u2019ve created a prefab out of it. In the Assets -&gt; Prefabs folder, drag the Player object in the Hierarchy and run the game to test it:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-010f967 elementor-widget elementor-widget-text-editor\" data-id=\"010f967\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>As soon as the player entered the collider of the spider the spider started to shoot. One thing to keep in mind here is that we are using OnTriggerEnter2D to detect collision and shoot, depending on what you want to do this might not be the solution you are looking for.<\/p>\n<p>Because if the player enters the collider and stays inside, then the spider will shoot only once:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c88b2ae elementor-widget elementor-widget-text-editor\" data-id=\"c88b2ae\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>You can fix this by using OnTriggerStay2D instead of OnTriggerEnter2D. The difference between the two functions is that the OnTriggerEnter2D registers a collision only when the object enters the trigger, which happens only once. Because for the function to register another collision, the object needs to exit the trigger, then enter it again.<\/div>\n<div><\/div>\n<div>But OnTriggerStay2D registers collision when the object enters the collider and as long as the object is staying within the bounds of the collider it will register.<\/div>\n<div><\/div>\n<div>Remove the OnTriggerEnter2D and add the OnTriggerStay2D function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2cf2041 elementor-widget elementor-widget-text-editor\" data-id=\"2cf2041\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Run the game and let\u2019s test it out:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-35713e2 elementor-widget elementor-widget-text-editor\" data-id=\"35713e2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>First, when the player entered the collider the spider shooter started shooting a lot of bullets, this is something we need to fix. Second, only when the player is moving while he is within the bounds of the collider does the spider start shooting.<\/p>\n<p>\u201cBut teacher you said that OnTriggerStay2D registers collision for as long as the player stays inside the bounds.\u201d<\/p>\n<p>Yes I did handsome stranger. The issue here is, we need to attach a Rigidbody2D component on the spider, and we need to set the Sleeping Mode option to Never Sleep:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7d361c2 elementor-widget elementor-widget-image\" data-id=\"7d361c2\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 7\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/1275f5c76b0ae1cc0078828c4ff5ad696a6a6908960ec99ac00aa1a4897eb869.jpeg\" alt=\"Img 7\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-71bd6f6 elementor-widget elementor-widget-text-editor\" data-id=\"71bd6f6\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The Sleeping Mode option set to Never Sleep will keep the collider detection trigger always active, which means that now as long as the player is within the bounds of the collider it will detect collision.<\/div>\n<div><\/div>\n<div>Before we test it out now, don\u2019t forget to set the Gravity Scale to 0 because we don\u2019t want gravity to affect the spider shooter since he is a static enemy and doesn\u2019t move.<\/div>\n<div><\/div>\n<div>Run the game and let\u2019s test it out now:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a0447c8 elementor-widget elementor-widget-text-editor\" data-id=\"a0447c8\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The collision now works as intended, but we still have the issue where the spider is shooting like crazy, which not something that we want.<\/p>\n<p>We can fix this by implementing the same timer technique we used in the first example.<\/p>\n<p>Inside the OnTriggerStay2D add the following lines of code:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0678867 elementor-widget elementor-widget-text-editor\" data-id=\"0678867\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now we detect collision with the player object, we check if Time.time is greater than waitTime and only then we shoot. Of course, we reset the waitTime value so that we wait again and don\u2019t shoot more than one bullet at the time.<\/div>\n<div><\/div>\n<div>Run the game and let\u2019s test it out now:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0e0e80c elementor-widget elementor-widget-text-editor\" data-id=\"0e0e80c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Now we have a working logic that will trigger after X amount of seconds for as long as the player, or any other target game object, stays within the bounds of the collider.<\/p>\n<p>The last trigger option, which we mentioned, that we can check is OnTriggerExit2D:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2b87a0d elementor-widget elementor-widget-text-editor\" data-id=\"2b87a0d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>OnTriggerExit2D will detect collision only when the game object exits the collider bounds. When the target game object enters the collider bounds, nothing will happen, but as soon as he exist the bounds the collider will detect that and it will fire the function in the code:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6770269 elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"6770269\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-be8bf5b elementor-widget elementor-widget-text-editor\" data-id=\"be8bf5b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Of course, you would use all three trigger detection functions in different ways depending on your needs, I am only showing you the options that you have at your disposal.<\/p>\n<p>As a reference I will leave the new version of the SpiderShooter script below:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d2a8251 elementor-widget elementor-widget-code-highlight\" data-id=\"d2a8251\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-89027f5 elementor-widget elementor-widget-heading\" data-id=\"89027f5\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Triggering AI Actions With Raycasts<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4294c13 elementor-widget elementor-widget-text-editor\" data-id=\"4294c13\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Another way how we can create AI behavior is using raycasts. The idea of a raycast is to create an invisible ray in the shape of a line, circle, or a box, and when the target game object touches that ray, collision will be detected and you can perform actions based on that collision.<\/p>\n<p>We are going to reuse the same script with the same shooting functionality, but we are going to change the way how we detect shooting, so you can remove the functions that detect collision between the enemy and other objects.<\/p>\n<p>Now, to create a ray we use the Physics2D class, and it goes like this:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c51ca8e elementor-widget elementor-widget-code-highlight\" data-id=\"c51ca8e\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ef25565 elementor-widget elementor-widget-text-editor\" data-id=\"ef25565\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The code on line 3 will create a ray in the shape of a line. The first parameter is the starting position, I\u2019ve used the current position of the spider as the starting position.<\/div>\n<div><\/div>\n<div>The second parameter is the direction where the ray will go, Vector2.down is a shortcut for writing Vector2(0, -1), this has to do with the normalization of the vector that you can read more about by clicking here.<\/div>\n<div><\/div>\n<div>The third parameter is the length of that ray. We can visually represent the length of the ray using Debug.DrawRay.<\/div>\n<div><\/div>\n<div>In the Update function below the current code that creates the ray, add the following line:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-18e554b elementor-widget elementor-widget-code-highlight\" data-id=\"18e554b\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a90f467 elementor-widget elementor-widget-text-editor\" data-id=\"a90f467\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The DrawRay function doesn\u2019t have the length parameter to determine the length of the ray that we will draw, because of that we can multiply the direction with the length of the ray, which we did for the second parameter: Vector3.down * 10f, and this will draw a ray in the down direction with the length of 10. The color parameter is the color of the ray that will be drawn on the screen.<\/p>\n<p>Let\u2019s run the game and see this in action:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-214286a elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"214286a\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ee11095 elementor-widget elementor-widget-text-editor\" data-id=\"ee11095\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The red line you saw in the preview above is the ray that is drawn with the help of DrawRay function.<\/div>\n<div><\/div>\n<div>From the structure of the code you already figured our that the Raycast function will return a bool value, meaning it will return true if the ray colliders with an object or false if the ray doesn\u2019t collide with the object.<\/div>\n<div><\/div>\n<div>If we try to shoot by adding:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b3276da elementor-widget elementor-widget-code-highlight\" data-id=\"b3276da\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5bb0bbc elementor-widget elementor-widget-text-editor\" data-id=\"5bb0bbc\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>This will shoot infinitely because the ray will hit the ground object and detect collision, but we only want to detect collision with the player object. For that we can use layer masks.<\/div>\n<div><\/div>\n<div>Above the Start function declare the following variable:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-be72a62 elementor-widget elementor-widget-code-highlight\" data-id=\"be72a62\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-29438e8 elementor-widget elementor-widget-text-editor\" data-id=\"29438e8\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the Raycast function add the collisionLayer as the last parameter:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-888ab7c elementor-widget elementor-widget-code-highlight\" data-id=\"888ab7c\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f87c465 elementor-widget elementor-widget-text-editor\" data-id=\"f87c465\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The idea of the collisionLayer variable is that the raycast will only detect collisions with game objects that are on a specific layer. Add a new layer and name it Player:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a4f4703 elementor-widget elementor-widget-image\" data-id=\"a4f4703\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 8\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/8015bff8baa367d7647136c043c1bceaa35af0da51932ceb2be50178e7c736e1.jpeg\" alt=\"Img 8\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-964f2d0 elementor-widget elementor-widget-text-editor\" data-id=\"964f2d0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Now change the layer for the player object to Player layer:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5531247 elementor-widget elementor-widget-image\" data-id=\"5531247\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 9\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/ed0af400f6f89572c70126b56a55ea107564b80944172cdf8431089b03b36412.jpeg\" alt=\"Img 9\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b0bead2 elementor-widget elementor-widget-text-editor\" data-id=\"b0bead2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now select the Spider Shooter object and in the Inspector tab for the SpiderShooter script, select the Player layer for the Collision Layer variable we created in the script:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2090f49 elementor-widget elementor-widget-image\" data-id=\"2090f49\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 10\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/26493253e31e0cea4b04d9b381b268c4d5bd50a74105149cf2839ada0a039a68.jpeg\" alt=\"Img 10\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-75e397e elementor-widget elementor-widget-text-editor\" data-id=\"75e397e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Now the raycast will only detect collisions with game objects that are on the Player layer. Let\u2019s run the game to test it:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-25f01c4 elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"25f01c4\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3860ba0 elementor-widget elementor-widget-text-editor\" data-id=\"3860ba0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The collision works but again we have the same problem we had with OnTriggerStay2D which can be fixed in the same way by adding a timer functionality.<\/div>\n<div><\/div>\n<div>We already did that a couple of times during this tutorial so I am not going to demonstrate it again as you can do that by yourself, plus I will leave you with the fixed version of the script down below for your reference:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7f82153 elementor-widget elementor-widget-code-highlight\" data-id=\"7f82153\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-00a3d0d elementor-widget elementor-widget-text-editor\" data-id=\"00a3d0d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now when it comes to raycasts they are a wide topic, because we have a raycast that creates a line, we also have a box shaped raycast and a circle shaped raycast.<\/div>\n<div><\/div>\n<div>They all work in the same way but they are shaped differently. You can research more about raycast and you will find examples how to use them, I am not going to cover every form of a raycast in this tutorial because it will go off topic since we are interested in creating enemy AI behaviour.<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-98bba7f elementor-widget elementor-widget-heading\" data-id=\"98bba7f\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Shooting In Player\u2019s Direction<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d02fd9b elementor-widget elementor-widget-text-editor\" data-id=\"d02fd9b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>So far, all the AI examples we saw make the enemy shoot in one direction. But what if we want the enemy to shoot in the player\u2019s direction, for example you have an enemy with a gun and you want it to shoot the player no matter where the player is in the level.<\/p>\n<p>For that, we need to make the enemy rotate towards the player\u2019s direction first, and then fire a bullet in that direction.<\/p>\n<p>We are going to use the same shooting functionality, but you can remove the current code from the Update function and the LayerMask variable declaration since we don\u2019t need raycasting for this example.<\/p>\n<p>What we do need is a reference to the player\u2019s Transform component because want the enemy to rotate towards the player.<\/p>\n<p>Above the Start function declare the following variable:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4556401 elementor-widget elementor-widget-code-highlight\" data-id=\"4556401\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-630a830 elementor-widget elementor-widget-text-editor\" data-id=\"630a830\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the Awake function, we will get the reference to the player\u2019s Transform component:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-1ecc999 elementor-widget elementor-widget-code-highlight\" data-id=\"1ecc999\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-73297b4 elementor-widget elementor-widget-text-editor\" data-id=\"73297b4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Since we are using FindWithTag function, make sure that the player object is tagged with Player tag.<\/div>\n<div><\/div>\n<div>To make the spider enemy face the player\u2019s direction, we need two more variables. Below the playerTransform variable, declare the following variables:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-dc52cf3 elementor-widget elementor-widget-code-highlight\" data-id=\"dc52cf3\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4be61cd elementor-widget elementor-widget-text-editor\" data-id=\"4be61cd\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>First we need to calculate the direction where the player is facing, for that we are going to use the direction variable, then we need to calculate the angle by which we need to rotate the enemy to make it face the player\u2019s direction, for that we will use the angle variable.<\/div>\n<div><\/div>\n<div>Below the Shoot function, we are going to create a function that is going to calculate the direction and the angle, and make the enemy face the player:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f7d2c97 elementor-widget elementor-widget-code-highlight\" data-id=\"f7d2c97\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ee25d14 elementor-widget elementor-widget-text-editor\" data-id=\"ee25d14\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>To calculate the direction of the player, we simply subtract from the player\u2019s current position the current position of the enemy.<\/div>\n<div><\/div>\n<div>To calculate the angle we use the Atan2 function from the Mathf library. Atan2 function will return an angle between two points in radians, that is why we multiply the returned value with Rad2Deg which will convert radians into degrees. This is how we will get the angle between the two points.<\/div>\n<div><\/div>\n<div>And to rotate the enemy towards the player, we use the AngleAxis function from the Quaternion class. AngleAxis will rotate around the given axis by the given degrees.<\/div>\n<div><\/div>\n<div>The first parameter are the amount of degrees by which we will rotate, and the second parameter is the axis around which we will rotate. Since this is a 2D to make the spider rotate towards the player\u2019s direction we use the Z axis which is what Vector3.forward represents.<\/div>\n<div><\/div>\n<div>And for the degrees we use the calculated angle and we added 90 degrees to it to make it rotate towards the player\u2019s direction.<\/div>\n<div><\/div>\n<div>Make sure that you call the FacePlayersDirection in the Update function:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4b6b7d6 elementor-widget elementor-widget-code-highlight\" data-id=\"4b6b7d6\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e0c86df elementor-widget elementor-widget-text-editor\" data-id=\"e0c86df\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now run the game and let\u2019s test it out:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d244b44 elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"d244b44\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d46221c elementor-widget elementor-widget-text-editor\" data-id=\"d46221c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Wherever the player goes, the spider enemy is rotating in that direction. Now to shoot the bullet in the direction the spider is facing we need to make a couple of changes.<\/div>\n<div><\/div>\n<div>First, in the Assets -&gt; Prefabs folder, select the Spider Shooter Bullet, and in the Inspector tab locate the Rigidbody 2D component and set the Gravity Scale value to 0:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b630456 elementor-widget elementor-widget-image\" data-id=\"b630456\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 11\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/7220c15fa2528ebf94c4c19d0aec31873cbf447b4a424b06cff24bd783abc5e4.jpeg\" alt=\"Img 11\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ee6e3fa elementor-widget elementor-widget-text-editor\" data-id=\"ee6e3fa\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>If we want the bullet to move towards the direction where it is fired, then we need to turn off the gravity affect it, otherwise the gravity will pull the bullet down.<\/p>\n<p>Next, open the SpiderBullet script, and below the class declaration add the following lines of code:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-1699a07 elementor-widget elementor-widget-code-highlight\" data-id=\"1699a07\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0c6ed92 elementor-widget elementor-widget-text-editor\" data-id=\"0c6ed92\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>You can already assume what we are going to do with both of these variables. But before we proceed with that, we need to attach the Rigidbody2D component to the appropriate slot in the Inspector tab.<\/p>\n<p>You can drag the Spider Shooter Bullet object in the slot and it will register its Rigidbody2D component:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3fbd938 elementor-widget elementor-widget-image\" data-id=\"3fbd938\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 12\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/69285150e1797e07d142feb4b62e0f1f2c6bf4a37ea23b757d70d2eb93003643.jpeg\" alt=\"Img 12\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4a0c1d0 elementor-widget elementor-widget-text-editor\" data-id=\"4a0c1d0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>To shoot the bullet, we need to create a function:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ec89900 elementor-widget elementor-widget-code-highlight\" data-id=\"ec89900\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a3b4044 elementor-widget elementor-widget-text-editor\" data-id=\"a3b4044\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>This function is going to shoot the bullet in the given direction multiplied with the moveSpeed. The moveSpeed variable has the SerializeField property so we can change the speed in the Inspector tab whenever we want.<\/div>\n<div><\/div>\n<div>We also need to stop the movement when the bullet gets deactivated inside the OnDisable:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-48fc6eb elementor-widget elementor-widget-code-highlight\" data-id=\"48fc6eb\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4d1cf1c elementor-widget elementor-widget-text-editor\" data-id=\"4d1cf1c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The reason for this is when we deactivate the game object, that will not affect the movement speed he already has, it will just deactivate it, and when we activate the object again it will continue to use the speed the object had in the moment of its deactivation, and this can mess up our shooting system.<\/div>\n<div><\/div>\n<div>Now open the SpiderShoot script. Inside the FacePlayerDirection function add the code that will shoot the bullet after X amount of seconds:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-57478d6 elementor-widget elementor-widget-code-highlight\" data-id=\"57478d6\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d082360 elementor-widget elementor-widget-text-editor\" data-id=\"d082360\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>As you can see, we are using the same approach we used so far. Of course, you can also trigger the shooting like we showed in the previous examples.<\/p>\n<p>Now to shoot the bullet, we need to make a couple of changes. First, we are going to change the declaration of the bullets list from:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-eda2d86 elementor-widget elementor-widget-code-highlight\" data-id=\"eda2d86\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9b8ee00 elementor-widget elementor-widget-text-editor\" data-id=\"9b8ee00\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>to<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-608d8c6 elementor-widget elementor-widget-code-highlight\" data-id=\"608d8c6\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ef4628e elementor-widget elementor-widget-text-editor\" data-id=\"ef4628e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The reason for this is because we are going to use the Rigidbody2D component of the bullet to make it move e.g. to shoot the bullet. We already created the ShootBullet function inside the SpiderBullet script, and in order to access that function we either need to use GetComponent, which can be performance heavy, or we can store a reference to the SpiderBullet class itself and simply access the function from the stored variable which is more efficient.<\/p>\n<p>Before we proceed, inside the Start function we need to modify the code that is storing the bullet game objects in the list:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-04d1f3b elementor-widget elementor-widget-code-highlight\" data-id=\"04d1f3b\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-eb8396d elementor-widget elementor-widget-text-editor\" data-id=\"eb8396d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Because we are storing SpiderBullet references in the list, when we create the bullet game object we need to use GetComponent to get a reference to its script and store it in the array.<\/div>\n<div><\/div>\n<div>We also set a new value for the waitTime variable to prevent the bullet shooting as soon as the game starts.<\/div>\n<div><\/div>\n<div>We also need to modify the Shoot function so that it uses the ShootBullet function from the SpiderBullet script when we want to shoot the bullet:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e713f90 elementor-widget elementor-widget-code-highlight\" data-id=\"e713f90\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7d4ae9c elementor-widget elementor-widget-text-editor\" data-id=\"7d4ae9c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the previous examples when we spawned the bullet, we used Quaternion.identity for its rotation, but this time we are using transform.rotation which is the rotation of the parent game object e.g. the spider.<\/div>\n<div><\/div>\n<div>We need to use the spider\u2019s rotation so that the bullet is also facing the player when it gets instantiated or activated again.<\/div>\n<div><\/div>\n<div>To shoot the bullet, we simply call its ShootBullet function passing transform.up as the parameter.<\/div>\n<div><\/div>\n<div>One new line of code we added in the Shoot function is the code on line 33. If we don\u2019t find any deactivated bullets in the game, we will create a new one. And in order to shoot the new bullet we need to access it by subtracting 1 from the total count of the bullets in the list.<\/div>\n<div><\/div>\n<div>Save the new changes we made to the script and run the game to test it out:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-8d88ccb elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"8d88ccb\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7a2c8b1 elementor-widget elementor-widget-text-editor\" data-id=\"7a2c8b1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now we have totally different AI system where the enemy is following the player\u2019s movement and shooting bullets towards his direction. As I already mentioned, you can change the speed of the bullets to make them faster and with that make the game more challenging.<\/div>\n<div><\/div>\n<div>I will leave the new modified SpiderShooter script, as well as the SpiderBullet script down below for your reference:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3897644 elementor-widget elementor-widget-code-highlight\" data-id=\"3897644\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c76fc34 elementor-widget elementor-widget-code-highlight\" data-id=\"c76fc34\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-03e6601 elementor-widget elementor-widget-heading\" data-id=\"03e6601\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Enemy Jumping AI<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9ad6620 elementor-widget elementor-widget-text-editor\" data-id=\"9ad6620\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Moving forward, in the Assets -&gt; Scenes folder open the scene named 2 \u2013 Basic Enemy AI Jump Attack. Inside the scene you will see a small spider in the middle, which is going to be our enemy for this example, and you see the player object.<\/p>\n<p>I have prepared the animations of the spider as well as the script and I added some code that will animate him so that we don\u2019t have to do that because that\u2019s not the goal of this tutorial.<\/p>\n<p>The idea of the Spider Jumper is to make him jump and try to kill the player while he is attempting to jump over the spider.<\/p>\n<p>If you checked out the SpiderJumper script that I already prepared you will notice from the variables I\u2019ve prepared that we are going to use a timer to make the spider jump.<\/p>\n<p>But first, let us create the Jump function:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-af1f1bc elementor-widget elementor-widget-code-highlight\" data-id=\"af1f1bc\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0c9fbce elementor-widget elementor-widget-text-editor\" data-id=\"0c9fbce\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>You can declare the Jump function below the HandleAnimations function. As you can see we are using the same approach as with SpiderShooter.<\/div>\n<div><\/div>\n<div>When we jump, we set canJump to false to prevent double jump, and then we add velocity to the rigidbody\u2019s Y axis to push it upwards.<\/div>\n<div><\/div>\n<div>You are probably wondering why didn\u2019t we just used a timer like we did with SpiderShooter, and the reason is that we need to detect if the Spider Jumper is on the ground as well as if a certain amount of time has passed.<\/div>\n<div><\/div>\n<div>Because of that we have another function that is going to handle the jumping:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-70b75c0 elementor-widget elementor-widget-code-highlight\" data-id=\"70b75c0\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2767681 elementor-widget elementor-widget-text-editor\" data-id=\"2767681\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Inside HandleJumping is where we are actually going to jump. If Time.time is greater than jumpTimer, then we are allowed to jump, but we also need to test if the spider is on the ground as we already mentioned which we are doing on line 9.<\/div>\n<div><\/div>\n<div>If the magnitude of the rigidbody\u2019s velocity is 0, that means that the spider is not moving. If you don\u2019t know what is magnitude and how it works, you can learn about that by clicking here.<\/div>\n<div><\/div>\n<div>The last step is to call the HandleJumping and HandleAnimation in the Update function:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e574a17 elementor-widget elementor-widget-code-highlight\" data-id=\"e574a17\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-815bfc7 elementor-widget elementor-widget-text-editor\" data-id=\"815bfc7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now run the game and let\u2019s test it out:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ec1df1d elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"ec1df1d\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2946c5e elementor-widget elementor-widget-text-editor\" data-id=\"2946c5e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>You are probably wondering how the enemy jumping AI example is different from the enemy shooting AI example that we first introduced.<\/div>\n<div><\/div>\n<div>Well, I am glad you asked that handsome stranger.<\/div>\n<div><\/div>\n<div>This example shows you that depending on the type of the enemy, you can use your own logic to implement the enemy AI. The first enemy was shooting, which is common in a lot of games, for that enemy you implement the shooting logic.<\/div>\n<div><\/div>\n<div>The second enemy was jumping and that way preventing the player from jumping over him. The AI logic we used for this enemy is similar to the first, but in the game it looks so much different.<\/div>\n<div><\/div>\n<div>Of course, you can also implement the trigger and raycast logic for the Spider Jumper same as what we did for the Spider Shooter, but again this comes back to what are you trying to achieve in your game and what is the outcome you are looking for.<\/div>\n<div><\/div>\n<div>I will leave the full version of the SpiderJumper script down below for your reference:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2cddf99 elementor-widget elementor-widget-code-highlight\" data-id=\"2cddf99\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<pre class=\"highlight-height language-csharp line-numbers\" data-line=\"\"><code class=\"language-csharp\">\n\t\t\t\t\t\n\t\t\t\t<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-aaad7b6 elementor-widget elementor-widget-heading\" data-id=\"aaad7b6\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Enemy AI Movement<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-da74f71 elementor-widget elementor-widget-text-editor\" data-id=\"da74f71\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>All examples we saw so far are using static enemies e.g. enemies that don\u2019t move and only shoot or perform another form of attack.<\/p>\n<p>For this example we are going to see how we can make the enemy move around the level.<\/p>\n<p>Inside the Assets -&gt; Scenes folder, open the scene named 3 \u2013 Basic And Intermediate Enemy AI Point A To Point B Movement.<\/p>\n<p>Inside you will see a prepared level and a prepared enemy. I have also prepared a script called GuardPointToPoint and attached it on the enemy object.<\/p>\n<p>When you open the GuardPointToPoint script in visual studio you will see that I\u2019ve already prepared a few variables and one function that will animate the enemy.<\/p>\n<p>To make the movement work, we need to add a few more variables. Above the Awake function, add the following lines of code:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-761a040 elementor-widget elementor-widget-text-editor\" data-id=\"761a040\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>The movementPoints variable declared on line 2 is an array of Transforms which will be the movement positions laid out in the level where the enemy can move.<\/div>\n<div><\/div>\n<div>The currentMovementPoint is the position where we are currently moving towards.<\/div>\n<div><\/div>\n<div>The currentMovementPointIndex is going to store the index of the current position from the movementPoints array. In regards to previousMovementPointIndex we are going to compare it to the currentMovementPointIndex every time we want to change the movement position to make sure that we don\u2019t get the same movement position.<\/div>\n<div><\/div>\n<div>And the moveSpeed variable is self explanatory.<\/div>\n<div><\/div>\n<div>First we are going to create a function that is going to handle the movement of the enemy:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-eb5d357 elementor-widget elementor-widget-text-editor\" data-id=\"eb5d357\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>We are using Vector2.MoveTowards to make the enemy move towards the currentMovementPoint e.g. the current destination the enemy is moving towards.<\/div>\n<div><\/div>\n<div>The function requires three parameters. The first parameter is the origin e.g. the starting position, the second parameter is the target position e.g. where we are going to, and the third parameter is the speed by which we are going to get to the target position.<\/div>\n<div><\/div>\n<div>Next, we use the Vector2.Distance function to calculate the distance between two points. And we are calculating the distance between the current position of the enemy and the currentMovementPoint e.g. our destination.<\/div>\n<div><\/div>\n<div>If that value is less than 0.1 that means the enemy has reached the target point and now we should change the currentMovementPoint to a new position in the game.<\/div>\n<div><\/div>\n<div>To do this, we need to create a new function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3646d21 elementor-widget elementor-widget-text-editor\" data-id=\"3646d21\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Again, we are using the while loop but this time we passed true as the parameter which means the loop will run forever. However, we have a condition where we will break out of the loop.<\/div>\n<div><\/div>\n<div>That condition is if the currentMovementPointIndex is not equal to the previousMovementPointIndex, which means we don\u2019t want to get the same movement position as the previous one.<\/div>\n<div><\/div>\n<div>Let\u2019s say the value of previousMovementPointIndex is 3, and we try to randomize the value of currentMovementPointIndex on line 6 above, if the Random.Range returns the value of 3, then we would get the same position, because of that we have the condition test on line 8.<\/div>\n<div><\/div>\n<div>If that condition is not true, then the loop will run again, randomizing the value of currentMovementPoint again, and it will continue to do so until the condition on line 8 is true which means the currentMovementPointIndex is not equal to previousMovementPointIndex.<\/div>\n<div><\/div>\n<div>When that happens we will set the previousMovementPointIndex to be equal to currentMovementPointIndex so that we can test again for the same condition on line 8 and make sure we don\u2019t get the same movement position.<\/div>\n<div><\/div>\n<div>Next, we set the currentMovementPoint to position of the element at currentMovementPointIndex in the movementPoints array. And after that we use the break keyword to break out of the while loop.<\/div>\n<div><\/div>\n<div>To make this work, we need to call the SetMovementPointTarget in the Start function to set the first initial movement point:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-dc03168 elementor-widget elementor-widget-text-editor\" data-id=\"dc03168\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>And we need to call the same function inside the MoveToTarget when we test if the distance between the current enemy position and the currentMovementPoint is less than 0.1 so that we can set a new movement point when we reach the previous one:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b2f28ca elementor-widget elementor-widget-text-editor\" data-id=\"b2f28ca\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>One more thing we need to do is add the code that will handle the facing direction depending on where the enemy is going:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-504fc2f elementor-widget elementor-widget-text-editor\" data-id=\"504fc2f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The logic is simple, based on the position X of the enemy and the current movement point, we will change the facing direction.<\/p>\n<p>When the enemy\u2019s position X is greater than the position X of the current movement point that means that the player is on the right side and he is going towards the left side. In that case we set the Scale X to a positive number, because by default how the enemy sprite is created he is facing the left side.<\/p>\n<p>And if the position X of the enemy is less than the position X of the current movement point, then we set the Scale X to negative value to change the facing direction of the enemy.<\/p>\n<p>To make this work, we are going to call the HandleFacingDirection in the Update function<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a9715d7 elementor-widget elementor-widget-code-highlight\" data-id=\"a9715d7\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7af315c elementor-widget elementor-widget-text-editor\" data-id=\"7af315c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Before we can test this out, we need to create empty game objects and position them in the level where we want the enemy to move:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e243116 elementor-widget elementor-widget-image\" data-id=\"e243116\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 13\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/44bf626ce1fd31444a9a9a064f133b7e1d7d5acfc067a450e7504a13aee41464.jpeg\" alt=\"Img 13\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-43f36d3 elementor-widget elementor-widget-text-editor\" data-id=\"43f36d3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>When we are done with that, we need to add the movement points in the movement points array we created in the GuardPointToPoint script:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-71897cc elementor-widget elementor-widget-image\" data-id=\"71897cc\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 14\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/2de677f7f3d9caa509474bf6bf6cdfb2357ad58e2a1c5033568fda6d394162e2.jpeg\" alt=\"Img 14\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9acb105 elementor-widget elementor-widget-text-editor\" data-id=\"9acb105\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>I\u2019ve attached the points from the Hierarchy tab in the Movement Points slots in the GuardPointToPoint script, but you can also tag the movement points and get a reference to them from code by using their tag.<\/p>\n<p>Run the game and let\u2019s test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-96b5c31 elementor-widget elementor-widget-text-editor\" data-id=\"96b5c31\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>As soon as the enemy reaches the end of the current movement point a new one is calculated and the enemy starts moving towards that movement point.<\/div>\n<div><\/div>\n<div>What\u2019s really smart about this set up is that we can have as many movement points as we want, we just need to add them in the movement points array and then the script will one movement point at random and make the enemy move towards it.<\/div>\n<div><\/div>\n<div>I will leave the full GuardPointToPoint script down below as a reference:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-24dcd9a elementor-widget elementor-widget-heading\" data-id=\"24dcd9a\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Moving Towards Player Target<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4d75e29 elementor-widget elementor-widget-text-editor\" data-id=\"4d75e29\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the example we created, the enemy is moving from one point to another and this behaviour can be good if you want to have a patrolling enemy, or if you have a part of your level where the player needs to pass and you have an enemy that moves in that part of the level and so on.<\/div>\n<div><\/div>\n<div>But how can we make the enemy patrol between points, and when he detects the player he moves towards the player?<\/div>\n<div><\/div>\n<div>There are, of course, multiple ways how we can achieve this. One of the ways is to detect the player using a collider, and when that happens switch the moving target towards the player object.<\/div>\n<div><\/div>\n<div>In the Hierarchy tab select the Guard enemy game object, and change the size of its collider and also make the collider a trigger:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-18b4f29 elementor-widget elementor-widget-image\" data-id=\"18b4f29\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 15\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/a57704430eee87cc4a9a0a49a89552e28753bb258b17816996fa9892c99aaa4c.jpeg\" alt=\"Img 15\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9686f13 elementor-widget elementor-widget-text-editor\" data-id=\"9686f13\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Next, in the GuardPointToPoint script, above the Awake function add the following variable:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-de50640 elementor-widget elementor-widget-text-editor\" data-id=\"de50640\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>In the OnTriggerEnter2D function, we are going to detect when we collide the player and make the enemy move towards the player, and in the OnTriggerExit2D function we will detect when the player leaves the bounds of the enemy\u2019s collider and we will stop chasing him:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-cb69d42 elementor-widget elementor-widget-text-editor\" data-id=\"cb69d42\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>In OnTriggerEnter2D we compare the tag of the game object the enemy has collided with, and if it\u2019s equal to the Player tag, then we will set the currentMovementPoint to the position of the player.<\/p>\n<p>In OnTriggerExit2D we do the same thing, except that this time we call the SetMovementPointTarget function to set a new movement point for the enemy.<\/p>\n<p>As for the chasePlayer variable, we are going to use to determine if the enemy should move towards the player game object or towards one of the movement points laid out in the level, and we are going to do that in the Update function:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-bb9a2a0 elementor-widget elementor-widget-text-editor\" data-id=\"bb9a2a0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Run the game and let\u2019s test it out:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-7016556 elementor-widget elementor-widget-text-editor\" data-id=\"7016556\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>I\u2019ve moved the player outside the bounds of the camera on purpose so that we can see what is happening from the Scene tab. As soon as the enemy detected the player with its collider, it started moving towards him.<\/p>\n<p>Of course, in this example, I only coded the movement AI, but depending on your game, the enemy will deal damage to the player when it reaches its destination.<\/p>\n<p>You can do this by calling the attack animation, or you can create a child game object for the enemy and attach a collider and a damage script on it, and when the child object collides with the player it will deal damage to him and so on.<\/p>\n<p>I will leave the new modified GuardPointToPoint script down below as a reference:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0008c14 elementor-widget elementor-widget-code-highlight\" data-id=\"0008c14\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3af5055 elementor-widget elementor-widget-heading\" data-id=\"3af5055\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Creating Enemy AI Behaviour With Raycasts<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c102bf1 elementor-widget elementor-widget-text-editor\" data-id=\"c102bf1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Another way how we can create enemy AI behaviour is using raycasts. We already saw raycasts and we used them to detect the collision with the player.<\/div>\n<div><\/div>\n<div>We can apply the same principles in this case, but instead of making the enemy attack the player, we are going to make the enemy move.<\/div>\n<div><\/div>\n<div>First, in the Assets -&gt; Scenes folder, open the scene named 4 \u2013 Intermediate Enemy AI Raycast Movement.<\/div>\n<div><\/div>\n<div>Inside I\u2019ve already prepared the enemy and the platform he will be moving on. I also created EnemyRaycast script and attached it on the enemy.<\/div>\n<div><\/div>\n<div>As always, we need to add the variables we need to make the raycast movement logic work. Open the EnemyRaycast script and above the Start function add the following variables:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-fc32a55 elementor-widget elementor-widget-text-editor\" data-id=\"fc32a55\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>When it comes to the movement, the variables that we will use and how we will use them is very similar no matter if the movement is done using physics, Transform component, raycasts and so on.<\/p>\n<p>Because of that, from the name of the variables you can already assume for what we are going to use every variable that we declared.<\/p>\n<p>First, change the Start function to Awake, and add the following lines of code:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-fba4027 elementor-widget elementor-widget-text-editor\" data-id=\"fba4027\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Since we are using raycasting, we will need the origin position where the ray is will start, for that we are using the groundCheckPos variable.<\/div>\n<div><\/div>\n<div>And we get a reference to the groundCheckPositionVariable from the child game object that we will attach to the enemy object.<\/div>\n<div><\/div>\n<div>For that we used the GetChild function from the transform, which will get the child at the specified index, and since we only have one child game object for the enemy we passed 0 as the parameter.<\/div>\n<div><\/div>\n<div>As for the moveLeft variable, we will use it to determine the movement direction of the enemy. And when the game starts we will randomize it so that sometimes the enemy will start by moving to the left side, and sometimes it will start by moving to the right side.<\/div>\n<div><\/div>\n<div>To move the enemy we are going to create a function that will handle that for us:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ab52e65 elementor-widget elementor-widget-text-editor\" data-id=\"ab52e65\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>First we get the current position and the scale of the enemy, then if we are moving to the left side, which we control with the moveLeft variable, then we will subtract from the enemy\u2019s current position moveSpeed multiplied with Time.deltaTime to smooth out the movement.<\/div>\n<div><\/div>\n<div>We will also change the Scale of the enemy to make it face the moving direction. Since the left side is the negative side in Unity, we set the Scale X value to negative.<\/div>\n<div><\/div>\n<div>And if we are moving to the right side are doing the opposite of what we did for the left side. Then we assign back the modified values to the transform.position and transform.localScale.<\/div>\n<div><\/div>\n<div>The idea with the raycasting is to create a ray that will check if the enemy is on the ground, if the ray doesn\u2019t detect that the enemy is on the ground, it will change the movement direction from left to right and vice-versa.<\/div>\n<div><\/div>\n<div>To do this, we are going to create a function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-14b9a8a elementor-widget elementor-widget-text-editor\" data-id=\"14b9a8a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>We are using the Raycast function from the Physics2D class to cast a ray. The first parameter in the function is the starting point of the ray, the second parameter is the direction where the ray will go, the third parameter is the length of the ray and the fourth parameter is the layer mask on which we are checking the collision.<\/div>\n<div><\/div>\n<div>We are storing the returned value in the groundHit variable that we declared, and then we are checking if the the groundHit is null. There are two ways to perform this check, one of them is this:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-09809c1 elementor-widget elementor-widget-text-editor\" data-id=\"09809c1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>and the other is this:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-02512ad elementor-widget elementor-widget-text-editor\" data-id=\"02512ad\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Both checks perform one and the same test. This means if the ray doesn\u2019t collide with the ground anymore, then change the moving direction and we do that by setting the moveLeft variable to the opposite of its current value.<\/p>\n<p>We know that the exclamation mark makes what\u2019s after it the opposite, so if the current value of moveLeft is true, and when we type:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-20977f6 elementor-widget elementor-widget-text-editor\" data-id=\"20977f6\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>that means that we are setting the moveLeft to the opposite of the value true, which is false.<\/div>\n<div><\/div>\n<div>At the end, on line 8 we are using Debug.DrawRay so that we can see the ray in the game when we test it.<\/div>\n<div><\/div>\n<div>Before we move in the editor, make sure that you call the HandleMovement and CheckForGround functions in the Update function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f843754 elementor-widget elementor-widget-text-editor\" data-id=\"f843754\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Going in the Unity editor, there are couple of things we need to do. First, create an empty child object for the Zombie Enemy and set its position to the following values:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c70d836 elementor-widget elementor-widget-image\" data-id=\"c70d836\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 16\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/9d1f8795e3acdc2a57f3c8733eb22ab08779885fb34c1271f080bc4ed4b80423.jpeg\" alt=\"Img 16\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-17a9fd6 elementor-widget elementor-widget-text-editor\" data-id=\"17a9fd6\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Next, create a new layer and name it Ground, then select the Zombie Enemy game object, and for the Ground Layer in the Enemy Raycast script select the Ground:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2e8a586 elementor-widget elementor-widget-image\" data-id=\"2e8a586\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 17\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/ff8e8acfa0840520b7e1042591eeffcc6b26cc8fd9f177b175913e76b0632341.jpeg\" alt=\"Img 17\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-fb78ec2 elementor-widget elementor-widget-text-editor\" data-id=\"fb78ec2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>I\u2019ve already set the Layer for the Platform game object to Ground, so you don\u2019t need to do that. Now run the game and let\u2019s test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-147ffed elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"147ffed\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-8b371f4 elementor-widget elementor-widget-text-editor\" data-id=\"8b371f4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Again, depending on the needs of your game and what type of enemies you have, you can always tweak the logic to your own needs and make the enemy detect and attack the player using raycasting, or make the enemy shoot using raycasting as we already saw, and so on.<\/div>\n<div><\/div>\n<div>I will leave the full EnemyRaycast script below as a reference:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d772b34 elementor-widget elementor-widget-heading\" data-id=\"d772b34\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">NavMesh Enemy AI<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3a17a35 elementor-widget elementor-widget-text-editor\" data-id=\"3a17a35\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>So far we covered 2D enemy AI examples. Now we are moving to 3D and we are going to see how to create 3D AI enemy behaviour.<\/div>\n<div><\/div>\n<div>Before we begin, I want to say that everything what we did so far is also applicable to 3D games as well. Of course, we would need to do a little tweaking to the scripts to make the game object move in 3D space, but the point is that we can use the exact same techniques.<\/div>\n<div><\/div>\n<p>In this part of the tutorial however, we are going to use a different way of creating enemy AI with the help of Unity\u2019s NavMesh system.<\/p>\n<p>First, in the Assets -&gt; Scenes folder, open the 5 \u2013 Intermediate Enemy AI Navigation Movement scene.<\/p>\n<div>If you see the level in 2D view, you can switch it to 3D view by clicking on the 2D button right below the Scene tab:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2831067 elementor-widget elementor-widget-image\" data-id=\"2831067\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 18\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/49844a656ad09565725fd4f5c69ca9a51b90e42939c71f7df3c0f849d2a1cc97.jpeg\" alt=\"Img 18\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-67ff2fc elementor-widget elementor-widget-text-editor\" data-id=\"67ff2fc\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>So what is a NavMesh?<\/div>\n<div><\/div>\n<div>NavMesh is Unity\u2019s navigation system that allows us to \u201cbake\u201d the game level, or level parts, which essentially represents the process of calculating the level surface to detect where are the walkable areas for that level.<\/div>\n<div><\/div>\n<div>Of course, there are multiple parameters that we can tweak in order to make sure that every higher surface on the level is not walkable, or to detect where are the wholes or gaps in the level where the player can\u2019t walk on and so on.<\/div>\n<div><\/div>\n<div>To bake the level, we need to open the Navigation tab which is located under Window -&gt; AI -&gt; Navigation:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ad04e3b elementor-widget elementor-widget-image\" data-id=\"ad04e3b\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 19\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/03cf1c3ad25bcaafe802a7f707be1f59d9d3372bd28e48bc5940ac52f3d911e9.jpeg\" alt=\"Img 19\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-8b85544 elementor-widget elementor-widget-text-editor\" data-id=\"8b85544\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>To bake the Ground we have in the level, first we need to make it Navigation Static. This means that we tell Unity that this object can be navigated.<\/p>\n<p>To do this, select the ground object in the Hierarchy tab, and in the Inspector tab click on the drop down list where it says Static, and from the list select Navigation Static:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a093fe5 elementor-widget elementor-widget-image\" data-id=\"a093fe5\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 20\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/e1bfdd4924170d0f1e4563db4f514f327055a5d5078ac1273f128a785416371b.jpeg\" alt=\"Img 20\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-fb4aa3d elementor-widget elementor-widget-text-editor\" data-id=\"fb4aa3d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Next, in the Navigation tab, click on the Bake tab, and then click the Bake button:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-293ba29 elementor-widget elementor-widget-image\" data-id=\"293ba29\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 21\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/c9444dfeac977848344d6990ac4bc2a3ba5728624fb535f7f63dff453002a595.jpeg\" alt=\"Img 21\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-533d70c elementor-widget elementor-widget-text-editor\" data-id=\"533d70c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>When you finish, you will notice that the Ground object has a blue color on it, if you don\u2019t see it, make sure that you opened the Navigation tab and that the Show NavMesh checkbox is checked:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f7a62ae elementor-widget elementor-widget-image\" data-id=\"f7a62ae\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 22\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/a27f3e258a24d127c94eccd88590a3055d362429fba9347003296961fdf270cf.jpeg\" alt=\"Img 22\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a99f9f4 elementor-widget elementor-widget-text-editor\" data-id=\"a99f9f4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Before we can make our player game object move, we need to attach the Nav Mesh Agent component on him. Select the player game object in the Hierarchy, and in the Inspector tab click on the Add Component button and filter for nav mesh agent and attach it on the player:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5a871aa elementor-widget elementor-widget-image\" data-id=\"5a871aa\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 23\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/c307529825a7e972dbda974c4c2e6cd5e00bb7f0cf17ac7ee6774abb8d589504.jpeg\" alt=\"Img 23\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e9f6a30 elementor-widget elementor-widget-text-editor\" data-id=\"e9f6a30\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now open the EnemyNavigation script, and above the class declaration add the following line:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-8700e90 elementor-widget elementor-widget-text-editor\" data-id=\"8700e90\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In order to access the NavMesh system, we need to import the AI library from Unity.<\/div>\n<div><\/div>\n<div>Moving forward, above the Start function, add the following lines:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-bd278ac elementor-widget elementor-widget-text-editor\" data-id=\"bd278ac\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>To make the player object move, we need a reference to his NavMeshAgent, and the destination variable is going to be the position where we are going.<\/div>\n<div><\/div>\n<div>In the Awake function get a reference to the variables and set the destination where the NavMeshAgent will move:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4436de4 elementor-widget elementor-widget-text-editor\" data-id=\"4436de4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>To make the agent move, we only need to call its SetDestination function and pass the destination position, and since we have baked the level, the agent will calculate the shortest path it takes for it to reach the destination and move towards it.<\/p>\n<p>Let us also animate the player\u2019s movement:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-87620b0 elementor-widget elementor-widget-text-editor\" data-id=\"87620b0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>You will notice that the nav agent has a velocity property on line 8. We can use that to test the speed of the agent. If the magnitude of its velocity is greater than 0, that means the agent is moving, and if its equal to zero then the agent is not moving. We can use this to animate the player\u2019s movement.<\/div>\n<div><\/div>\n<div>Before we test our game, go inside the editor, create an empty game object, name it Destination and position it anywhere in the level, but keep it within the bounds of the Ground game object so that the nav agent will be able to reach that position.<\/div>\n<div><\/div>\n<div>Next, select the player game object, and drag the Destination game object in the Destination empty field for the Enemy Navigation script:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-1760fae elementor-widget elementor-widget-image\" data-id=\"1760fae\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 24\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/224ac6ed8ea4f2861fcaecb956aac43a55d1e0306e9afc9b7d1394bf13a74fc1.jpeg\" alt=\"Img 24\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b915e2b elementor-widget elementor-widget-text-editor\" data-id=\"b915e2b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Let us now run the game and test it out:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9a693f4 elementor-widget elementor-widget-text-editor\" data-id=\"9a693f4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Since we set the destination for the agent in the Awake function, as soon as we run the game, the agent started moving towards the destination. And since the agent was moving, we also animated the player with the help of the velocity property of the agent.<\/div>\n<div><\/div>\n<div>As soon as the agent reached the destination it stopped moving, which is the default behaviour of the agent component. If we want the agent to move to another destination then we need to call SetDestination function and provide the new destination.<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-dafc940 elementor-widget elementor-widget-heading\" data-id=\"dafc940\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Changing Agent\u2019s Destinations In The Level<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a79e13c elementor-widget elementor-widget-text-editor\" data-id=\"a79e13c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>To make the nav agent move from one point to another point we can use a similar technique like we did in the Guard enemy example.<\/div>\n<div><\/div>\n<div>For that, we need to remove the destination variable, and instead of it, declare the following variables above the Awake function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9c26555 elementor-widget elementor-widget-text-editor\" data-id=\"9c26555\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the Awake function we are also going to change the code that will set the destination for the nav agent:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6a58c71 elementor-widget elementor-widget-text-editor\" data-id=\"6a58c71\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>To set a new destination for the agent, we are going to create a function similar to the one we created in the Guard enemy example:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5c35834 elementor-widget elementor-widget-text-editor\" data-id=\"5c35834\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Again, using the power of the while loop we are going to pick a random destination from the destinationPoints array, if the random destination is not equal to the current destination, that means we have a new destination for the agent, and then we will break out of the while loop.<\/div>\n<div><\/div>\n<div>But before we can set a new destination, we need to make sure that the agent has reached its current destination:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d7d2b47 elementor-widget elementor-widget-text-editor\" data-id=\"d7d2b47\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>We are using the magnitude of the agent\u2019s velocity to check if the agent is moving, if the magnitude is equal to 0, the agent is not moving which means he reached his destination.<\/div>\n<div><\/div>\n<div>Before we go in the editor to create the destination points, call the CheckIfAgentReachedDestination function in the Update function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-3a61ab2 elementor-widget elementor-widget-text-editor\" data-id=\"3a61ab2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>In the editor, make sure that you create a few empty game objects and lay them out in the scene but within the bounds of the level so that the agent will be able to reach them.<\/div>\n<div><\/div>\n<div>When you are done with that, attach those empty game objects in the Destination Points array in the Inspector tab for the Enemy Navigation script:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b827c61 elementor-widget elementor-widget-image\" data-id=\"b827c61\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 25\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/aa3e55c4c8cb153f0589d2d49bc88aff1ccce5e418008c64a3888e780586aff9.jpeg\" alt=\"Img 25\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-517d3e1 elementor-widget elementor-widget-text-editor\" data-id=\"517d3e1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Run the game and let\u2019s test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5691290 elementor-widget elementor-widget-text-editor\" data-id=\"5691290\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Every time the agent reaches his current destination, we set a new one for him. Now there are multiple ways how we can check if the agent reached his destination.<\/p>\n<p>In our current example we are using the magnitude of the agent\u2019s velocity. We can also check the remaining distance the agent has left:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-41fe42b elementor-widget elementor-widget-text-editor\" data-id=\"41fe42b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The remainingDistance will returna float value representing the distance that is remaining until the agent reaches its destination. The stoppingDistance represents the distance between the agent and its destination when the agent will stop moving.<\/p>\n<p>We can set that value in the Nav Mesh Agent component:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c4e525e elementor-widget elementor-widget-image\" data-id=\"c4e525e\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 26\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/3dcf34c1275493ecb25e7d0cb6e04061418735ec1469c77d89b8634edebe6784.jpeg\" alt=\"Img 26\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a7aaa0b elementor-widget elementor-widget-text-editor\" data-id=\"a7aaa0b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The current value is set to 0, this means the that stopping distance from the destination is 0, but if we set the value to 5 for example, this would mean that the nav agent will stop when the distance between him and the destination is equal to 5.<\/p>\n<p>We can also use the pathPending property to test if the path is currently in the process of being computed e.g. we provided the path and the agent is calculating how to reach it, and we can use hasPath to test if the agent currently has a path that\u2019s in the process e.g. the agent has a destination to be reached:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-bd08162 elementor-widget elementor-widget-text-editor\" data-id=\"bd08162\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The reason why you might want to perform these tests is because a distance check isn\u2019t always accurate since the steering behavior portion of the NavMeshAgent may actually still be working even if the distance is less than the stopping distance, so keep that in mind.<\/p>\n<p>I will leave the full version of the EnemyNavigation script below as a reference:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d2c7448 elementor-widget elementor-widget-heading\" data-id=\"d2c7448\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Setting A Random Destination Within The Baked Area<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5b2fd17 elementor-widget elementor-widget-text-editor\" data-id=\"5b2fd17\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>We can also generate a random destination for the agent within the baked area of the level.<\/p>\n<p>Remove all the current code from the EnemyNavigation script except for the Animator variable and the AnimatePlayer function, and then add the following variables:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5a379bb elementor-widget elementor-widget-text-editor\" data-id=\"5a379bb\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The variables are pretty much the same except for the NavMeshHit which represents result information for any queries we perform on the NavMesh. In the Awake function we are going to get the reference we need:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-65d7d28 elementor-widget elementor-widget-text-editor\" data-id=\"65d7d28\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Again we are going to use SetNewDestination function to set a new destination for the nav agent, but this time we are going to take a different approach:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d7da6d6 elementor-widget elementor-widget-text-editor\" data-id=\"d7da6d6\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The SamplePosition function of the NavMesh class will find the nearest point based on the NavMesh within a specified range.<\/p>\n<p>The first parameter represents the sourcePosition e.g. the starting position from which we are going to get a random point.<\/p>\n<p>To calculate that position, we are using Random.insideUnitySphere which will return a random point inside or on a sphere with a radius of 1.0. We multiply that value with the maxWalkDistance variable because that is the max amount of distance where the agent can walk, and then we add the current position of the enemy to that value.<\/p>\n<p>This means, that we are going to search for a point within the nav mesh baked area from the position of the agent e.g. the enemy, with the radius of insideUnitySphere multiplied with the maxWalkDistance.<\/p>\n<p>Then we pass the navHit variable where the SamplePosition will store the information that will be returned. The out keyword used before the navHit variable means that we are passing the navHit variable as a reference to this function.<\/p>\n<p>If you don\u2019t know what is a reference and what does that mean, you can learn about that concept by clicking here.<\/p>\n<p>The next parameter represents the distance from the sourcePosition parameter in which we are going to search for the random point.<\/p>\n<p>And the last parameter is a LayerMask variable that represents the layer of the game object on which we perform this check. By passing -1 we are including all layers, but if you want to check for the nav point only on a specific nav area, you can use layers for that.<\/p>\n<div>After that we are checking if the currentDestination is not equal to the new random destination we generated with the SamplePosition function, and we are using the navHit variable for that.<\/div>\n<div><\/div>\n<div>As I already said, the navHit variable will have all the information in regards to the SamplePosition function, so we can access the random position by calling the position property of the navHit variable.<\/div>\n<div><\/div>\n<div>If we have a new position, then we will set the currentDestination to that position and pass that value to the SetDestination function of the nav agent.<\/div>\n<div><\/div>\n<div>We are going to reuse the function from the previous example where we checked if the agent has reached its destination:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-abc2a2e elementor-widget elementor-widget-text-editor\" data-id=\"abc2a2e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>And as a last step, we need to call the CheckIfAgentReachedDestination in the Update function:<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b995206 elementor-widget elementor-widget-text-editor\" data-id=\"b995206\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Run the game and test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a6b62f9 elementor-widget elementor-widget-text-editor\" data-id=\"a6b62f9\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>I will leave the new version of the EnemyNavigation script below as a reference:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-03f4b30 elementor-widget elementor-widget-heading\" data-id=\"03f4b30\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Nav Mesh Agent Speed, Rotation, Stopping Distance And Other Settings<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-583ee01 elementor-widget elementor-widget-text-editor\" data-id=\"583ee01\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>While testing the examples we created so far, you probably noticed that the enemy object was rotating in a weird way, and you also noticed that he was moving in a certain speed.<\/p>\n<p>But we didn\u2019t define any of those settings, so how come is the enemy moving without us doing anything on that part?<\/p>\n<p>Well, as you can already assume the movement and everything related to it is controlled and performed by the Nav Mesh Agent.<\/p>\n<p>We can, of course, edit those settings. We can change the speed of the agent, we can also change the speed by which he will rotate, we can even change the stopping distance length from the agents destination and we talked briefly about it.<\/p>\n<p>All of these settings are located on the Nav Mesh Agent component itself:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-c9fff36 elementor-widget elementor-widget-image\" data-id=\"c9fff36\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 27\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/11e7a7657d549cd9f9b339c0ea9a5cfe70566fdfc81135bfbda548f9d5e2ef2b.jpeg\" alt=\"Img 27\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-8664c4b elementor-widget elementor-widget-text-editor\" data-id=\"8664c4b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>The first option on the nav agent represents the agent\u2019s type. The agent type is controller in the Agents tab in the Navigation settings:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-87caac0 elementor-widget elementor-widget-image\" data-id=\"87caac0\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 28\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/501cbbc02c5cab6310b779c89c772ae6cdff8cdd60d8304fc26c6d4c39a0f7c0.jpeg\" alt=\"Img 28\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-36e7d65 elementor-widget elementor-widget-text-editor\" data-id=\"36e7d65\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>As you can see the agent type has properties that we can change, and these properties affect how the nav mesh is built e.g. how the navigation area will be baked.<\/p>\n<p>We can click on the + button to create a new agent type:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a1ce3d5 elementor-widget elementor-widget-image\" data-id=\"a1ce3d5\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 29\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/eb45001f0fdc3b6bcfa6e1b3558e7cc38f5b3b2ccd8a72447c24e5343d9f1d2f.jpeg\" alt=\"Img 29\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d995316 elementor-widget elementor-widget-text-editor\" data-id=\"d995316\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>We can now create a new agent type by changing the values for the settings.<\/p>\n<p>The name represents the agent type name.<\/p>\n<p>Radius is the radius of the agent type. If we create an agent type for a lion, then we would set the radius to a larger value because the lion is a large animal.<\/p>\n<p>The height represents the height of the agent type, so if we have a tall game character like a dragon for example, we would set that value to a higher number.<\/p>\n<p>Step height represents the height of the each step the agent will make. If we have a dragon in the game, then the step height would be pretty large.<\/p>\n<p>And the max slope represents how well the agent will climb angled surfaces. Depending on the type of the agent you will adjust this value accordingly.<\/p>\n<p>I am going to create a sample dragon agent type:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-77eabe8 elementor-widget elementor-widget-image\" data-id=\"77eabe8\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 30\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/f21cf0179d80d5026806fb7539616502cc7de167a24da0276fc233406d9179dc.jpeg\" alt=\"Img 30\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ea829d5 elementor-widget elementor-widget-text-editor\" data-id=\"ea829d5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Now that we have two agent types, we can click on the drop down list for the Agent Type property on the Nav Mesh Agent and select our desired type:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b18ea2b elementor-widget elementor-widget-image\" data-id=\"b18ea2b\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 31\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/a357ce1f8400bfae558d34cec6f5232353f3aef0b1e0d6c0323676a7ce62c262.jpeg\" alt=\"Img 31\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-af79dc4 elementor-widget elementor-widget-text-editor\" data-id=\"af79dc4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Of course, we would need to rebake the level based on the type of the agent we have selected to enable that particular agent to walk and navigate in the level, so keep that in mind.<\/div>\n<div><\/div>\n<div>In regards to other options they are straight forward and self explanatory. You can even hover over every individual option and see the explanation for what it is used.<\/div>\n<div><\/div>\n<div>I am going to change the value of the angular speed property which will make the agent rotate faster:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4eb0747 elementor-widget elementor-widget-image\" data-id=\"4eb0747\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 32\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/a87e90b0be7981d2d2c8160ed4386f570b0e53a82d7e0b857324e92f919f6d9f.jpeg\" alt=\"Img 32\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6efc720 elementor-widget elementor-widget-text-editor\" data-id=\"6efc720\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Now when the enemy turns to go in another direction in the game it will look more natural.<\/p>\n<p>Run the game and let\u2019s test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-d354ada elementor-widget elementor-widget-text-editor\" data-id=\"d354ada\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>You can play with the other settings on your own such as the Speed which will make the agent move faster, or the Acceleration which will make the agent\u2019s starting speed faster and so on.<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-54d8d66 elementor-widget elementor-widget-heading\" data-id=\"54d8d66\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Navigating Between Obstacles<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-8dac291 elementor-widget elementor-widget-text-editor\" data-id=\"8dac291\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>So far we only made the agent move in a empty level so to say. With this I mean that we didn\u2019t have any obstacles in the level like walls.<\/div>\n<div><\/div>\n<div>Because of that, in this part of the tutorial we are going to take a look at how can we make the nav agent navigate between obstacles in the level<\/div>\n<div><\/div>\n<div>I am going to reuse the script we created in the Changing The Agent\u2019s Destinations In The Level part of the tutorial, so make sure that you copy the whole script.<\/div>\n<div><\/div>\n<div>Now going in the editor, in the Hierarchy tab you will see a game object called Obstacles. The game object is not active in the game so make sure that you activate it and when you do you will see the obstacle child objects laid out in the level:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b1a744d elementor-widget elementor-widget-image\" data-id=\"b1a744d\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 33\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/637773d182501993bc4cc666cc220c3e14e29b29e52569c3a6b7d6040471f47d.jpeg\" alt=\"Img 33\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-bd6230f elementor-widget elementor-widget-text-editor\" data-id=\"bd6230f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Before we can bake the level with the obstacles, we need to make the obstacles Navigation Static. Select every obstacle in the Hierarchy tab, and in the Inspector tab click on the Static drop down list and make them Navigation Static:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-31a5445 elementor-widget elementor-widget-image\" data-id=\"31a5445\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 34\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/bbb8cbb073cc9590aa1843de4c347c6ee75dafdd5250b259a752519dde2eb5a5.jpeg\" alt=\"Img 34\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0d8aa3a elementor-widget elementor-widget-text-editor\" data-id=\"0d8aa3a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now that we made the obstacles Navigation Static, we can go in the Navigation -&gt; Bake tab and click the Bake button. When you do that, you will notice that around the obstacle objects there is no blue color when you have the Show NavMesh checkbox checked:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b145a66 elementor-widget elementor-widget-image\" data-id=\"b145a66\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 35\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/95fa4cb1c96509854d87f78df59e1f1d336a63a90091d6c229ae9affdac7e033.jpeg\" alt=\"Img 35\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f47e0d5 elementor-widget elementor-widget-text-editor\" data-id=\"f47e0d5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>This means that the obstacles are counted as such, and because of that they are not counted as a walkable area in the level, that is why we don\u2019t see the blue color around them.<\/p>\n<p>Of course, by changing the settings values, like the Step Height settings which determines the height the agent can climb on:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e73a635 elementor-widget elementor-widget-image\" data-id=\"e73a635\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 36\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/d52a1178b6a78c124784ed9ffbe1f4e8872d3454852246f5285f941e7c8f3eba.jpeg\" alt=\"Img 36\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-614c90e elementor-widget elementor-widget-text-editor\" data-id=\"614c90e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>and after that when we bake the level we will see that the obstacles are now counted as a walkable area because their height is less than the Step Height value so now the nav mesh system thinks the player can walk on the obstacles:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-642517f elementor-widget elementor-widget-image\" data-id=\"642517f\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 37\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/8bae3912109834185371ae0078fa05a6c7af40e5e36e9e7c0f55d9cc3adfc707.jpeg\" alt=\"Img 37\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-02c0f58 elementor-widget elementor-widget-text-editor\" data-id=\"02c0f58\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Another way how we can denote that an object is an obstacle is by attaching the Nav Mesh Obstacle component.<\/p>\n<p>Before we do that, select all obstacle child objects, and click the Static drop down list and make sure that the objects are not marked as Navigation Static:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-68e5fcb elementor-widget elementor-widget-image\" data-id=\"68e5fcb\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 38\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/8295df75c29e8b917c132f2355c14411c093efacdef3071e61e8c9f70a2324ed.jpeg\" alt=\"Img 38\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-6b00697 elementor-widget elementor-widget-text-editor\" data-id=\"6b00697\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Since the obstacle child objects are not Navigation Static anymore, make sure that you rebake the level again so that they are not counted as obstacles:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-4abc06e elementor-widget elementor-widget-image\" data-id=\"4abc06e\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 39\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/75489c43a07fa77f31b4d378508e77b01f56afb946238a5438b4ab28c47cae54.jpeg\" alt=\"Img 39\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a9084f8 elementor-widget elementor-widget-text-editor\" data-id=\"a9084f8\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>Now select all the obstacle objects again, and in the Inspector tab click on Add Component button and filter for nav mesh obstacle:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-47ce4dc elementor-widget elementor-widget-image\" data-id=\"47ce4dc\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 40\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/4b1823379017296b1a47ade2c682ba3acbc0d9fe57568756ec39799adc85f4ee.jpeg\" alt=\"Img 40\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0c64d97 elementor-widget elementor-widget-text-editor\" data-id=\"0c64d97\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>To make the obstacle objects counted as obstacles by the nav mesh system, select all the obstacle objects and in the Nav Mesh Obstacle component check the Carve checkbox:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0ef5fca elementor-widget elementor-widget-image\" data-id=\"0ef5fca\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 41\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/62ea2b240afa4ee3b8df8dc009f4d1319276896b90ba871ce16694b1e3e12c5d.jpeg\" alt=\"Img 41\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5976718 elementor-widget elementor-widget-text-editor\" data-id=\"5976718\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>When you do that, you will notice now that around every obstacle in the game there is no blue color:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-cdb45c4 elementor-widget elementor-widget-image\" data-id=\"cdb45c4\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 42\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/3b829b6a5ec3948a83d415c30254b5959e78468a797d2c0a2f53505badb7e783.jpeg\" alt=\"Img 42\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9dadc25 elementor-widget elementor-widget-text-editor\" data-id=\"9dadc25\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>By changing the size property in the Nav Mesh Obstacle component you will also change how large of an obstacle the nav mesh system think a particular game object is:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-ba42cc8 elementor-widget elementor-widget-image\" data-id=\"ba42cc8\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 43\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/4402327aa5d23114ecf13f041645e558c0e364836ea1a8aaa375c150c879a415.jpeg\" alt=\"Img 43\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-101c712 elementor-widget elementor-widget-text-editor\" data-id=\"101c712\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Before we test this out, make sure that you lay out the destination points near the obstacles so that you can see how the nav agent is avoids the obstacles.<\/p>\n<p>Now run the game and let\u2019s test it out:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-fd3c590 elementor-widget elementor-widget-text-editor\" data-id=\"fd3c590\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Of course, the larger you set the size of the Nav Mesh Obstacle component for a specific obstacle object, the further away from the obstacle the player will be as he is not able to walk on that area.<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-5faf828 elementor-widget elementor-widget-heading\" data-id=\"5faf828\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n<div class=\"elementor-widget-container\">\n<h3 class=\"elementor-heading-title elementor-size-default\">Moving Towards Player With Nav Mesh Agent<\/h3>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-e0d1e03 elementor-widget elementor-widget-text-editor\" data-id=\"e0d1e03\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>To make the nav agent move towards the player we just need to feed it the player\u2019s position. And to do that, we first need to detect the player\u2019s presence near the enemy.<\/div>\n<div>As you can assume, this can be done in multiple ways. We can use colliders, raycasts, or even calculate the distance between the player and the enemy and if the player is within a certain distance we can make the enemy chase the player. I am going to use colliders for this example to detect the player\u2019s presence.<\/div>\n<div><\/div>\n<div>Select the enemy object in the Hierarchy tab, and attach a sphere collider on him. Check the Is Trigger checkbox and set the following values for the Center and Radius property of the sphere collider:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-35661b6 elementor-widget elementor-widget-image\" data-id=\"35661b6\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 44\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/275cb20f31677dee1a6538c9e9c1cff33f8b3ca825e616f64f21ae9f88ecad9a.jpeg\" alt=\"Img 44\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f02177b elementor-widget elementor-widget-text-editor\" data-id=\"f02177b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>I am also going to change the Stopping Distance to 2 for the Nav Mesh Agent component:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-79b9f8f elementor-widget elementor-widget-image\" data-id=\"79b9f8f\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 45\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/c74ed6255d92103ee52339ca061c4ad5a1aa570fdd8525410e4a93de5a96e124.jpeg\" alt=\"Img 45\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-f756425 elementor-widget elementor-widget-text-editor\" data-id=\"f756425\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>This will make the nav agent stop near the player\u2019s position instead of stopping exactly at the same position where the player is.<\/p>\n<p>For this example I am going to use the same version of the EnemyNavigation script as we did in the previous example e.g. the EnemyNavigation that uses destination points in the level to move.<\/p>\n<p>Above the Awake function add the following variable:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-b285e8f elementor-widget elementor-widget-text-editor\" data-id=\"b285e8f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Next, we need to create the functions that will detect when the player enters the sphere collider and when he exits the sphere collider<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-9eda867 elementor-widget elementor-widget-code-highlight\" data-id=\"9eda867\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"prismjs-tomorrow copy-to-clipboard \">\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-bc5a9c0 elementor-widget elementor-widget-text-editor\" data-id=\"bc5a9c0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>In OnTriggerEnter we are testing if we collided with the player. If that is true, then we will set the destination for the nav agent to the player\u2019s position and we will set the moveToPlayer variable to true.<\/p>\n<p>In OnTriggerExit, we are doing the opposite. We set the moveToPlayer value to false, and we call SetNewDestination to get a new moving destination in the game.<\/p>\n<p>Lastly, we need to modify the CheckIfAgentReachedDestination function so that the enemy has one behavior when it is going towards the player, and another behaviour when it is going from one destination point to another:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-0fa54b4 elementor-widget elementor-widget-text-editor\" data-id=\"0fa54b4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<div>When we reach the player\u2019s destination I only added the Debug.Log statement so that we can see that the enemy has indeed reached the player. When you implement this in your game, depending on your project, you will add your own logic what you want the enemy to do with the player when it reaches its position.<\/div>\n<div><\/div>\n<div>Going back in the editor, from the Assets -&gt; Prefabs folder drag the Lian You game object, which we will use as a player in this example, in the level:<\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a7d3ae8 elementor-widget elementor-widget-image\" data-id=\"a7d3ae8\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n<div class=\"elementor-widget-container\"><img decoding=\"async\" title=\"Img 46\" src=\"https:\/\/glossingdress.com\/lib\/img\/all\/551\/2e5e217e73f323d3f3fd195d7b133b5bac6491c267c092b65097222f82c8682f\/0fe8470c4a5c5b03f0cd5968c5ef860fb182c0d2cf345365cb5831ec8658e6ce.jpeg\" alt=\"Img 46\" \/><\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-a7f71a3 elementor-widget elementor-widget-text-editor\" data-id=\"a7f71a3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>Now let\u2019s run and test the game:<\/p>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-094270e elementor-aspect-ratio-169 elementor-widget elementor-widget-video\" data-id=\"094270e\" data-element_type=\"widget\" data-settings=\"{\" data-widget_type=\"video.default\">\n<div class=\"elementor-widget-container\">\n<div class=\"elementor-wrapper elementor-fit-aspect-ratio elementor-open-inline\">\n<div class=\"elementor-video\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"elementor-element elementor-element-2906feb elementor-widget elementor-widget-text-editor\" data-id=\"2906feb\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n<div class=\"elementor-widget-container\">\n<p>As soon as the player was within the sphere collider\u2019s bounds, we detected the collision and the nav agent started moving towards the player.<\/p>\n<p>When he reached his destination we saw that he didn\u2019t stop exactly at the position of the player, instead he stopped near the player because of the Stopping Distance value.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/section>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>There are different types of enemy AI that you can create in Unity, from the very basic enemies that move between two points all the way to machine learning where your enemies are learning from the events in the game and behaving accordingly. In this post we are going to learn about AI in Unity<\/p>\n","protected":false},"author":1,"featured_media":584,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-437","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/posts\/437"}],"collection":[{"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=437"}],"version-history":[{"count":2,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/posts\/437\/revisions"}],"predecessor-version":[{"id":583,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/posts\/437\/revisions\/583"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=\/wp\/v2\/media\/584"}],"wp:attachment":[{"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=437"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=437"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/globalgoodplay.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=437"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}