Make A Game Like Pokemon in Unity | #30 - Improving NPC Behavior

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

This is part 30 of my Pokemon Game tutorial series in unity. In this video, we'll improve the behavior of our NPCs. We'll block the NPCs from walking through solid objects, and make them face the player while talking.

If you're new to this series, this a series where we'll create a Turn-Based RPG like Pokemon in unity using Design Patterns and Good Game Development Practices. I'd love hear what you think about it :)

Here is the entire playlist.

👍︎︎ 1 👤︎︎ u/GameDevExperiments 📅︎︎ Nov 14 2020 🗫︎ replies
Captions
hey everyone welcome to part 30 of my pokemon game series in unity so in this video we'll make a lot of improvements to our npc so if i go stand in the way of the npc's walking pattern so you can see that it won't work and if i move from its way then it will start walking again and another improvement is if we go talk to the npc it will actually turn towards us while talking all right and we'll also fix some other issues that we have right now so let's implement all that special thanks to all my patreons for making the series possible by becoming a patreon you can support me in the making of the series and get access to some cool rewards like the complete project files of the series which also contains some advanced features that are not covered here so let's start the video so first let's look at an issue that we have right now so here we have two npcs and if i go talk to one of them you can see that even the other one stops moving right but we don't want that only the npc that we are talking to should stop moving so this is happening because in our npc controller we are not running the update function if the dialog is showing right so we need a better way to handle this so what i'll do is in the npc state i'll add another state called dialog and in our interact function before showing the dialog i'll actually set the state to dialog okay so let me add the braces here and before showing the dialog i'll set state to npcstate.dialog okay and once the dialog is over we need to set the state back to idle but right now we don't have a way to know if the dialogue is over so let's go into our dialog manager and in here we need a way of knowing if the dialogue is over right so what i'll do is in the show dialog function i'll add an action called on finished and i'll set its default value to know it so that it's not compulsory okay so let me actually store it in a private variable so that we can access it outside the function okay so while assigning the dialog i'll also assign our action okay so now when the dialog is over and after we close the dialog i'll also call on dialog finished dot invoke okay so now to the show dialog function we can actually pass an action and once the dialog is over it will actually be called right so let's actually pass an action from our npc controller so after passing a dialog i'll pass the lambda for the action and inside the lambda i'll set the state back to idle right we want the npc state to go back to idle once the dialog is over and i also set the idle timer to zero so that we don't use any previously stored value okay so now in our update function we can remove this line that checks if the dialog is showing and since we have this if condition here we will only run this if the state is idle right but when interacting we'll set it to dialogue so this will not turn so now only the npc that we are talking to will stop moving and all other npcs will keep moving like before okay so let's test that okay you can see that when i talk to this npc this one is still moving right so that issue is fixed so next let me show you another issue that we have right now so if i stand here you can see that the npc just walked through us right so we can also test this by changing the pattern so let's say i want this npc to move eight tiles to the right and then come back by eight tiles okay so eighth tile will be somewhere over here and then pc will walk through the house okay let's test that so yeah you can see the npc is walking through the house so the problem is we are only checking if the target tile is workable but we should also check if all the tiles in between are also walkable right otherwise the npc will walk through such solid tiles so let's look at how to fix that inside our character class right now we are only checking if the target position is workable all right so instead of that here i'll create another function called this path clear which will also check for all the tiles in between not just the target tile okay so this will take the target position just like our is workable function so in this function how can we check if all the tiles in between are workable so what i'll do is i'll create a box like this from this style to the target tile and i'll check if all the tiles on that box are workable right so we can actually create such a box by using physics2d.boxcast so inside this function i'll create a physics 3d dot box cast okay so for the box cast we need to pass the origin size angle direction and distance also so for the original just pass transform dot position which is the current position of the character and full size i'll pass 0.2 by 0.2 and for the angle i'll just pass 0 since we don't want it to be angled okay so next how can we get the direction and we also need a distance so how can we get the direction and the distance so for that i'll calculate a difference vector between the target position and the current position okay so i'll create a vector called diff and this vector will be the difference between the target position and the current position right so now since this is a vector it will have a length and a direction okay so we can get the direction by calling diff dot normalized so what this will do this will return another vector with same direction as that of diff but the length will be one right so when you normalize a vector it will have the same direction but it will have a length of one so now here for the direction i can pass our direction vector and finally for the distance i can pass the length of the difference vector right so to get the length i can call diff dot magnitude okay so now we are creating a box cast from the player's current position to the target position right but there's a problem if you look at the box that i draw earlier you can see that i didn't start the box from the player's current position right instead i started it from the next style so this is because if we start from the current position then that box will collide with the character itself okay so it will collide with the character itself and we won't be able to walk so we should always start the box cast from the next tile so how can we do that since we know each tile is one unit we can simply add one in this direction right so what i'll do is to the transform.position i'll add my direction vector okay so since the length of this vector is one we are actually adding one unit in the direction we want right so this is all we have to do to start from the next style but since we're adding one to the origin position we should also subtract one unit from the magnitude right so the distance should be one less than our difference vector okay so now we have created the box cast we want and just like we did for our overlap circle we can also pass layers to our box cast to make the collision more efficient right so if you look at the next parameter we can pass a layer mask for it so i'll just pass solid layer plus the interactive layer okay so this boxcast will return true if there is actually a collider in the area of the box right so we can check if the boxcast returns true okay so if it returns true it means the path is not clear right it means there is some collider in between so in this case we will return false specifying that the path is not clear and otherwise i'll return true specifying the path is walkable okay so now in our move routine instead of calling this walkable function i'll call is path clear okay so let's just if this is working so yeah you can see that this npc doesn't walk through the house anymore instead it skipped to the second pattern right so next let's check if it can walk through the player so it can walk to the player right this is because we are only passing the solid layer and the interactable layer to our box cast right but if we look at the player game object it's actually in the default layer so let's actually add a layer for the player so we can pass that okay i'll add a new layer called player and i'll assign the player game object to that layer i don't want to put the child object in the player layer since we have camera as a child object so now in our game layers script we also need to add the player layer right so let's go to our game layers and here i'll add another layer called player layer let me create a property to expose it okay so now we can assign it in inspector and finally in our box cast we can also pass the player layer right so now the npc shouldn't be able to walk through the player also so in order for this to work we also need to add a rigid body and a box glider to our player so first let me add rigid body it should be 2d and i'll set the body type to kinematic and next i'll add a box color 2d okay so let me just edit the size of the box glider okay so that looks good so now if we test the game the npc shouldn't be able to walk through the player okay let's test that all right so if i go stand here you can see that the npc cannot walk through us and it just skipped to its next pattern right so next what i want to do is if the path is not clear i don't want the npc to skip to the next pattern so the problem is if it skips a pattern then it'll work in a pattern different from the one we specified right so then we won't have control over where all the npc can go okay so let's prevent that so in our npc controller inside the bog core routine i only want to increment the current pattern if it actually walked in the previous pattern right if the previous pattern was successful so how can we check if it actually walked in the previous pattern so what that what i'll do is first i'll store the current position of the character in a variable called overposition okay and after calling the move routine i'll check if the current position of the character right now is not equal to or position okay so if the old position and current position are not equal it means the character actually parked in the previous pattern so in that case we will increment the current pattern and otherwise we won't right so in case the character did not block in the previous pattern then we'll wait for time between pattern again and we'll try to walk in the same pattern once again all right so let's test this all right so immediately you can see that this npc doesn't walk in the second pattern so it means the first pattern it's not skipped and it's actually trying the first pattern again and again okay so let's also test with this npc so you can see that if i stand in its way it doesn't use the next pattern right it'll just keep trying the current pattern again and again and if i just move out of its way then it will start walking again okay so that's working fine so next time on the npc to face towards the player when we go and talk to him okay so right now you can see it's not facing towards us so let's implement that so in our character script i'll create a public function called look towards okay and this function will take a target position so basically it will make the character look towards the target position we pass all right so in order to implement that first we need to find the difference between the x and y coordinates of the position of the character and the target position okay so i'll create a variable called x diff in order to store the difference in the x coordinate and to find the difference i'll say target position dot x minus transform dot position dot x okay so since we're dealing with tiles here i want the difference in number of tiles right so i want the difference to be like two tiles or three tiles like that so for that we can use math dot floor on the coordinates before actually subtracting them so let me do that so now we'll always get the difference as an integer instead of a decimal value okay so now let's also find the pi difference all right so next i'll check if x difference is equal to 0 or y difference is equal to 0 okay so why am i doing this the look towards function will only work if either one of this is zero so let me explain what i mean by that so our characters can only look in four directions right it can only look down up left or right and cannot look in any diagonal direction so when we are passing the target position we can pass a position like this uh this this okay so positions like this will work but let's say if i pass a position like this okay a character won't be able to look to this position right this is because we only have sprites for top down left and right directions so for a position like this there will be a wire difference but the x difference is zero right since the player and the position is in the same x coordinate and if we take a position like this it has an x difference but the wire difference will be zero right but in case of positions like this both the x difference and y difference are not zero so in order to block such positions we will only turn the character if either one of this is zero right and otherwise i'll just print an error in the console saying that you can't ask the character to look diagonally all right and in case if either one of this is zero then we can turn the character by setting the movix and moving value of its animator so just like we do in the mooc routine we can set the mo x and move i of the characters animator in order to turn the character right so let me copy this and i'll paste it over here and for the x value i'll pass the x difference and for the y value i'll just pass the y difference so we have an error here saying x difference and y difference are actually double so that's because here i'm using math instead of math if that was a mistake so i'll change it to math f so that this becomes float and the error is gone all right so now we can call this function from the interact function of the npc controller okay so in the interact after setting the state to dialogue i'll call character dot look towards and we have have to pass the player's position right so for that what i'll do is i'll take a transform in the interact and i'll call this parameter initiator okay so this is the transform of the game object that initiated the interaction so in this case it's the transform of the player so now in the look towards function i can just pass initiator dot position okay so now we have an error over here so this is because interact is a function that is defined inside the interactable interface right so we also have to add that parameter over here okay and finally when calling the interact function from the player controller we have to pass the transform of the player so i'll just pass the transform and all the errors should be gone okay so now when the player goes and talks to the npc it'll actually look towards the player while talking all right so let's test that all right so if i go talk to this npc you can see that it turned towards us when talking and we can also try from a different direction and yeah you can see it's turning towards us all right so we have made lots of improvements to our npc so i'll stop the video here if you think the video is helpful please leave a like on the video and consider subscribing to my channel that'll really help me a lot so i'll see you in the next video
Info
Channel: Game Dev Experiments
Views: 3,117
Rating: undefined out of 5
Keywords: make a game like pokemon in unity, how to make a game like pokemon in unity, make pokemon in unity, make pokemon game in unity, how to make pokemon game in unity, make a pokemon game in unity, unity pokemon game tutorial, unity 2d npc dialogue, unity rpg npc
Id: -M_tDVLx9Qg
Channel Id: undefined
Length: 23min 42sec (1422 seconds)
Published: Sat Nov 14 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.