How to Talk to NPCs! (or Interact with any Object, Open Doors, Push Buttons, Unity Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome I'm your code monkey in this video let's learn how to do a very basic NPC interaction system so this can be just interact with an NPC to talk to them maybe then you open a chat dialog or maybe some kind of shop interface the main goal is to know when the player is near an interactable NPC and then start the interaction with an action although this exact system can be applied to interact with anything not just NPCs so in the end I will also showcase how to use this to open doors and press buttons this is a pretty detailed tutorial I won't cover how to identify nearby objects how to interact with them prioritize closer ones shown into rack UI element and more I will be doing this using a 3D demo but the concepts are equally applicable to 2D as well you just need to use a slightly different function if you prefer a more guided path with step-by-step lectures then check out my complete courses learn how to make a builder Defender game using c-sharp or learn how to make games internally using visual scripting perhaps if you're past the beginner stage and want to make the jump to Advanced then check out my turn-based strategy course to learn how to manage a more complex project and write some good clean code or learn all about Unity with the ultimate TNT overview course which contains over 15 lectures each covering a different two-hour feature of the engine I'm always available in the Q a section answering your questions every single day so check them all out with the link in the description okay so let's build this NPC interaction system here is my demo I have a character in first person and I can walk around pretty basic for the character controller I'm using the free official ENT Stern assets that I covered in other video This is the first person controller and for the visuals over here I'm mainly using the cinti city asset pack then over here for this mini building and that pile of money that is from The Heist pack and for the animations I'm also using a general pack there's links in the description if you want to get them so I can control my character and over here are a bunch of NPCs so let's begin making our interaction system first thing we need is to know if an NPC is nearby so if my player character is standing right here I want to see if this NPC is near me so that I can interact with them so let's begin by making a script so an easy sharp script let's call this the player interact here is the player game object just attach and open okay now here there are seven ways to do that one way would be to check the distance to each NPC so for example I could have a list of transform for the NPC on list I could have something like this then on a private void update I would test Vector 3 dot distance between this transform dot position and the NPC on the list dot transform dot position so I could use this to check if the player is close enough to the NPC ink that would work but that also means you need a reference to every single NPC so this is not a very scalable approach if your game has hundreds of NPCs then you're going to need to add hundreds of references and hundreds of discs and checks so for a much better approach let's not do this and instead we're going to use the physics system so over here we can go inside physics and in here there's a bunch of overlap functions what these do is it queries the physics world and returns all the collectors that overlap that area so this is perfect with this we can test and see if there are any NPCs near the player and if so then we're going to do something over here we have various functions each of them with different shape so for our case for a distance I think sphere makes the most sense so let's use this one this one takes a position so for the position let's use the transform of that position so the player position then for the radius let's use some kind of interact range let's put maybe two units also if we wanted there are more versions to this function for example we could use a layer mask so we could put all of the NPCs in a single layer and only test against that layer that would be one approach the only limitation with that is you only have 32 layers total so if you have too many object types you might run out of layers so in this case let's not use a layer mask let's hit all of the objects and all the layers and then we can cycle through them and check which ones are NPCs so we have this which is going to return an array of colliders let's put this inside the input so if input gets you down let's say for the E key just like in so many PC games okay so you press e key and we get all the collectors let's store them so this returns a con leather ring just for testing let's cycle through all of them and do analog so let's do a four inch collider collider in the collider ring and for each of them do a debug down log on the Collider okay that's it and then over here in the editor all we need to do is make sure that our objects our NPCs already have a collider and up here you can see they do have a caption call leather if they don't have a collider then they pretty much don't exist in the physics world so that function would not work so in order for this to work they must have a collider okay so let's test so here we are I'm far away from the NPCs and if I press the E if they're going with the unlock so you can see a bunch of Road objects so all the ones behind me the capsule so this is the player's capsule and so on so none of them are the NPC since the NPC is way too far away but now let's move forward to the protein PC by a little bit and press the button again and yet now here we do see the NPC alright awesome so just with this we already know if an NPC is within range and now that we know that the next thing is to actually interact with it so let's make another script for that and use c-sharp script call this the NPC interactable let's attach to the NPC now in this case in this demo all of these two NPCs they are both part of this prefab so I'm just going to add the script onto this one okay now let's open and over here let's make a super simple function just for testing and for this one we're going to want to call the function from the player so let's make it public if we don't know why I'm saying this go watch the video on why you should not make everything public you should only make something public when you have a specific reason for it like in this case we want to interact with this function from the player class so we need to make this probably so if only provide interact and up here let's just do a debug download so just say interact okay that's it for this script now back here in the player script so we second through all the collectors okay and on the commanders let's try to get that NPC interactable component so we can go into the collider and we can use try get component we're going to get the component of type NPC interactable so if this succeeds then this collider has an NPC interactable so this is an NPC and if someone went into right so let's just go there and call the interact function okay that's it super simple Let's test so here I am far away from the NPC and if I press the inky and nope nothing happens now as I approach the NPC and press and there you go interact alright awesome so with this we already have the system working exactly as we wanted now we need is to handle the interaction in any way we want so for example over here I've got a nice chat bubble element this was made in a previous video it's just a fun chat bubble with syntax and a nice text writing effect in that video I made this class with a super easy to use static function so we just need to call this and it automatically instantiates the objects such as the text and so on so over here on the NPC interact script let's just do that so just go into that script called the create function let's create on this transform for in low composition let's put chat bubble a bit up and a bit to the side then a nice icon and then some text okay so with this we have a nice chat bubble now again just for fun let's make it play an animation over here on the NPC it has an animator and on the animator it has a basic add-on animation and also a tonking animation the transitions are set up is all based on this parameter so just a trigger parameter called Tonk so when this happens it goes into this and after the exit time goes back into idle so we're here in the code super simple we just need first of all a reference to the animator so the animator animator let's grab it up here on private voidaway just grab the animator get component animator okay so we have the animator and then over here animator and in this case I made that parameter e trigger so let's make the tone trigger and finally for another fun thing let's make the NPC and look at the player over here on the NPC I have a simple script to make it look towards a certain position this is made using unity's animation rigging package it's a super awesome package to let you add Dynamic Logic on top of your animations it's really great really easy to use doing something like this like just rotating the head to face the player is super easy I covered it in detail in another video and in here all I have is the character the character has a rig has a head constraint it's just a basic multium constraint it's constraining the head object towards looking at this object so if I put the animation in preview and I can move around this object and you can see yep the character unlocks straight towards this position so we need is really to place this object on top of the player when the player interacts with it and that's exactly what this script is doing so here just have a public function to look at a certain position and then just interpolates a way to make it nice and smooth this is using alert which is a great way to smooth things also covered it in detail another video so on the NPC let's say he reference to this script in order to call this function so over here let's make that so private that one is an NPC head and look at so over here on let's get it on the awake and then on interact let's call the function in order to look at the position which means that over here we do need the position now we could technically hard code the player reference we could add up here a kind of serialized field and drag the player's reference or we could use some kind of Singleton something like that or perhaps a better approach would be to receive it over here in the function so let's do that since it's much more adaptable so in here let's receive the interactor transform so we transform for the interactor transform then on the player script over here on the player interact let's pass in this transform okay and over here you can look at position let's look at this one dot position but let's add an offset on the Y so the NPC doesn't look at the player's feet so let's add Vector three dot up and multiply it by certain player height so player height let's say 1.7 units and look at that okay great so we had three nice elements on top of our NPC interaction so let's see if our interact code is working correctly with this and triggering all these interesting actions let's see okay here we are and if I'm far away and I press the button nope nothing happens okay great now as I go towards the NPC and I press the button and yep there you go play the animation the nice chat bubble everything looks great then on this other NPC again same thing just look at it and there you go the head rotates place the animation the chat bubble and all of that all right great so as you can see the system is already looking pretty great now we can also add a nice UI element to know when we're close enough to interact for that over here I already have a canvas set up like I usually do so it's an overlay canvas scale with screen size with this okay now inside let's make an empty game object come with the player interact UI then inside let's make a simple visual so let's just zoom out a bit inside let's add a UI image let's also add a text let's put an e all right there it is just a basic UI element we want to show our height depending on if the player is near an interactable object so for that we're going to enable and disable the game object in order to not break it and disable and name on The Parent Game object let's put these inside a container so a container let's just put it on zero zero and drag these ones inside okay so that way the script can say enabled and we can just enable or disable divisions all right so let's make the square to run this so let's make an easy sharp script with the exact same name layer interact UI let's go up here and attach it now here on let's do two basic show and height functions so we're going to need a reference to the container all right there it is super simple just a game object for the container and on show we set active true unhide set of two false here in the editor let's just write the reference okay now here in order to call these two functions now we do want to keep our code nice and clean so what we don't want to do we do not want to run the physics Logic the physics query we don't want to run that on the player interact UI that should say on the player not on the UI script so let's leave it over here on the player script and let's just make a function to expose that logic so let's make it public let's return a NPC interactable and let's call it get interactable object then on this one you do exactly this logic so let's copy so you have this we get component and return the NPC interactable and if we have none then just return null okay so we have this now over here on the UI element we just need to call that so we could make the player a Singleton that would be one approach or alternatively just make a serialized field so let's go with that just make a player interact player interact just make it a serialized film then on proud void update we asked that question so playing track that we get the interactable object and if this one is not known then there's something that can be interacted so let's show and if not let's hide all right so that's it super simple we just need to drag this reference it's over here let's drag the player reference that's it let's test so here we are far away from the NPC and as you can see there's no UI okay great and as I approach the NPC if there goes as I go in range that one does show up so now I know that if I click here no can do it and if I click here if there go interaction okay great now one more thing let's add support for multiple interactions over here I already have two NPCs let's make sure we can interact with both of them exactly as we want to identify them let's go over here to the NPC interactable and let's make a simple let's make it a generalized film a private string let's call this the interact text and then let's make a function to return it so public string get interact text and we're just going to return this then over here in the editor let's go on to this one let's film that in so let's say Tonk with Bob and then for the other one let's say tongue with Alice okay that way we can differentiate between both interactions and on the UI script let's show this so let's go into our UI script and here let's just add another text object below okay just like this over here on UI script let's work with that so let's add using first of all we need the TM Pro over here let's make another serialized film for text mesh Pro you going this is the interact text then on this one when we show let's pass in the object so that over here we can receive the NPC interactable and then we can just go and set the text equals NPC interactable and let's get the interact text okay that's it and now to test a potential issue with this let's go over here to the player interact and let's increase the interact range from two to four we're going to see why in a bit so let's see okay so here we are and let's approach Bob and you better go talk with Bob and if I approach Alice yep there we go talk with Alice okay so it seems like it's working however over here I'm talking with Alice and even if I get close to Bob there you go I'm still talking to Alice the issue here is due to the way that the collisions work it's basically depend on the order in the physics world and not necessarily the closest so let's add that logic to make sure to check all of the interactable objects around the player but make sure to prioritize the closest one over here we have our interaction now let's store in list of NPC interactable and then when we find something with an interactable let's add it to the list so let's add this NPC interactable but let's now return it not yet then afterwards let's cycle through that list and find the closest one alright so here it is so we basically create a list then we sell through all the call letters we try to get the component and we add them onto this list then we cycle through this list again and we check if this is the first one that we're finding if so make this the closest but if there's already a closest NPC if so then let's check the distance and check if the distance between this one is closer than the one to the closest then this one becomes the new causes and then we just return down so this won't test all of the colliders within this array and return only the closest one and with this now we should be able to see the interaction with Alice and Bob depending on which one is closest also by the way quick note you might be wondering why am I not refactoring this code and you'll see one in a bit so don't worry about that let's just test this okay so over here if I approach Bob yep talk with Bob and if I approach analyst yep talk with Alice over here talking with Alice and as I approach Bob yep I can swap between one and the other depending on which one is exactly the closest okay great so everything is working the system now supports multiple interactions within the same range and we only make sure to interact with the closest one finally like I said I don't want to just make an NPC interaction system I want to be able to interact with anything so over here on this side I've got a button and a nice sphere and over there I've got a door with a bunch of cash so I would like to press a button to open this door and grab all that cache so let's do that for that over here I already have some scripts so I've got a simple door interactable this one just got a simple tunnel door which sets the animator in order to open or close the door and then the button also has a button interactable script and over here just changes the color from that sphere mesh render and puts it in another blue or yellow and toggles it okay so to implement this into our interaction system you might think to do the obvious approach which is over here we are trying to get the component of type in PC interactable and if so we interact with it so over here you can just do the exact same thing for all the others so we can try to find a door interactable and if so let's go into the door and turn on the door so here let's make sure to make this public and up here we can talk on the door okay and then for the button then go into the button and let's also expose that one so the push button make it public and over here let's push the button okay so just like this let's see if it works so first of all let's go back to the NPCs and let's talk with Bob okay that one still works now let's try to turn on the button so go and press and there you go it does work and let's go open the door and he appears a bunch of money okay so everything seems like the works so all the logic works the only thing that isn't working is the UI element so I'm near the button but there's no UI element but still everything technically works so this is one possible approach however right now our code is extremely complex we've got a ton of ifs for all kinds of interactable objects and now this player interacts script now this one is tightly coupled with the door and the button so if we were to reuse this script on another game that did not have doors or buttons and everything would break and of course anytime we want to add another interactable object we would need to come back here and add some more code so this approach works but it's obviously not ideal and some of this this specific scenario is exactly where C sharp interfaces become so useful I cover them in detail another video definitely go watch that if you don't know know anything about interfaces now here on let's just make an interface for all of the interactable objects so let's right click create new c-sharp script call it I interactable that's it just make the script don't attached to anything and on this script let's get rid of all of this this is going to be an interface so this is not a mono Behavior we don't want it to be that and this is not a class this is an interface okay so we have our interface and in here we just have two functions so let's do them just like we did on the NPC so we've got a void interact and let's receive a transform for the interactor and then let's also make one that returns a string for the get interact text okay so this is our interface super simple now let's go into the NPC script so we're here on the NPC interactable and on this one let's Implement that interface so we're going to implement the I interactable in this case that's it we already have a void interact and a string at interact text so in this case we don't even need to do anything the interface is already implemented now let's just implement this on the door and the button so over here on the button so let's Implement our interface and now we're going to get our error so let's use to implement the interface so here it is we've got to interact and a get interact text so for this one let's return push button and for the interact let's just call the push button function okay then on the door over here the exact same thing so I interactable let's once again implement the interface for the get interact text return open close door and on the internet What's called the tunnel door okay so all of our objects now implement this common interface so now we can go back into the player interact script and over here instead of doing all kinds of ifs depending on all the types of objects instead let's just test for one so just test for the I interactable interactable so if it does have an interactable component then we go and we just use the interact function just like this so everything else can be removed so that's it as you can see we cut down quite a lot of code and like I mentioned previously let's refactor this function the only reason why I didn't do it a while ago is because it would break when we use other types other than the NPC interactable but now that we are using a common interface now this is super easy so we just need to replace all of these references with this let's also rename the names so interactable and then up here we use this function instead of doing the exact same thing so let's just grab the I interactable and we get it and if the interactable it is not known if not then interactive bone dot interacts okay so that's it super simple except here we see an error so we need to expose the transform so The Simple Solution is to just add a get transform on the interface definition so over here let's make a function that Returns the transform called get transform then you just need to make this on all these so a public transform get transformed and just return this transform so add it onto the button then over here onto the door and on the NPC interactable over here the same thing and on the player interact over here we can use that function so the get transform in order to get the position alright so we have refactored all of our code to work with a generic interactable interface so the button the door the NPC they all share this common interface and then the player interact script only works with this interface now with this let's test and see if everything is already working the last thing is just over here on the UI script so we're here instead of NPC interactable let's receive just an interactable and then it's the exact same thing just get interact text and so on okay so that's it so let's test all right so here we are let's approach the NPC and there you go the UI element shows up and there you go I can talk to Bob let's go over here and yep I can talk with Alice and now if we go over here and I approach a button and there you go I've got the UI element saying to push the button and I push any up it does work and then as I approach the door there you go open and close and yep everything does work all right awesome so this as you can see we can interact with any object of whatever type it's not limited to just NPCs we can interact with anything as long as it implements that interface and has a physical letter in order to find it so adding more and more object types more and more NPCs all of that is super easy now if you're working in 2D all of this works pretty much exactly the same the only difference is over here with the physics overlap sphere if you're working in 2D instead of physics you use physics 2D and then over here you've got different overlaps you've got overlap area box capsule or you also got a circle so that's pretty much the only difference you would use physics CD instead of physics and for the qualities you'd use 2D colors instead of 3D and that's it everything else in this system works exactly the same alright so here is a really awesome interaction system to talk with NPCs push buttons open doors or literally do any interaction you want again if you want a more guided path with step-by-step lectures then check out my complete courses alright hope that's useful check out these videos to learn some more thanks to these awesome patreon supporters for making these videos possible thank you for watching and I'll see you next time [Music]
Info
Channel: Code Monkey
Views: 98,238
Rating: undefined out of 5
Keywords: unity talk to npc, unity interact with object, unity open door, unity interaction, c# interface, unity push button, code monkey, unity tutorial, unity game tutorial, unity tutorial for beginners, unity 2d tutorial, unity 3d, unity, game design, game development, game dev, game development unity, unity 2d, unity 3d tutorial, programming, coding, c#, code, software development, learn to code, learn programming, unity tutorials, how to make a game, overlapsphere
Id: LdoImzaY6M4
Channel Id: undefined
Length: 24min 46sec (1486 seconds)
Published: Wed Oct 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.