Game development on .NET

Unity Navigation – Part 2

dotGame
Unity Navigation – Part 2
5 (100%) 1 vote
(Video Transcript)
Hi guys, welcome to .Game. This is part two of our basic navigation series, I think I probably called it something different every video but [LAUGH] part two of the basics of navigation. In this one we’ll actually take a look at the obstacles, so working with NavMesh obstacles. And then we’ll delve into a little bit more of the code I think and then we’ll set up a sprite to pulse. So, we’ll do a little bit of animation, very, very light, kinda basic intro stuff. So, lets go ahead and get started. We have the scene pretty much exactly where left off in the last video. And in the last one if you we recall, we set up the navigation, we made it so that our character could navigate based off of where we clicked, but there’s really no visual indication of where we’re clicking. And then the other problem is It doesn’t actually avoid obstacles, so we’ll just kind of go through anything and everything, which is obviously pretty bad. So that’s the first thing that we’re going to actually address, which is setting up what’s known as a NavMesh obstacle on our game object.

So, looking at, or well this is gonna be our first one that we wanna play around with, we’ll add it, so, NavMesh Obstacle. These are pretty easy to work with. So, it’s shaped as a box. what we’re actually wanting is a capsule. Excuse me, and we’re gonna want something with a little bit bigger of a radius. So the nano flesh obstacle is very similar in the sense of the radius and the height to the NavMesh agent that we looked at earlier. It does have several other properties that we didn’t really look at. This is actually a center so we can alter where it’s positioned along either x, y or z. In our case, it was actually be positioned perfectly. Because what I want is to cut out a circle around this but not kinda the bottom half that you see here. So having it sit at 000 is actually, absolutely what we want. And I think the radius, we might even be able to, oops, that’s the wrong one, The radius. I think that it’s probably, bring it in just a bit too. There we go, that’s probably pretty good.

All right, so the last kinda property that is different, and not really self-explanatory, is this whole carve thing. So I’m going to click on Navigation. That’s one way, so we can kinda see, we have that blue area. We still have a blue area around where we’ve defined an obstacle, and this can be altered by checking the carve. Now you can see that there’s actually a carve that’s being cut out in that navigation. So, what that is doing is when carving is not turned on the agent will try to steer to prevent a collision, which is really good behavior for say a movable obstacle that you’d want. So we might do that maybe on our little crate over here, but we wouldn’t want them to potentially move the well, that would be pretty bad. So with carving turned on, the obstacle essentially becomes static or stationary and the agent, when they go to plan their route, will plan around that particular object. So that is very, very useful, again, when you wanna do some blocking. Again, in our case, to make sure that they don’t walk through the well but you could think of that also in, say a hallway, or something where maybe you wanna block off the player from being able to progress down that hallway until they’ve met some other criteria and then that object will magically be removed or explode or whatever.

Actually, exploding is a very bad example because I think you actually would end up doing that a whole different way, so really not part of it. But the [LAUGH] point being when you’re trying to avoid a particular area or stop the player from going. So, that’s kind of really all there is to setting this up. If I push Play and then I try to navigate through, again this is with that NavMesh Obstacle, so you can see she kind of dodges it. She doesn’t get perfectly around it but that’s because I had my radius rather slow but she won’t walk on it, she’ll just kinda pass around it, which is perfect. So that’s kind of the basics of setting up the obstacle. Now let’s take a look at the sprite or the sprite stuff. So I’m gonna get off of navigation, just to make this feel a little bit more complete, we’re gonna do another create them, now we merge it, we’ll call this PositionIndicator. All right, so we’re gonna create an empty game object, and we’ll name this, I guess, PositionIndicator, then I’m going to add a component.

And this is going to be a sprite renderer component. And I’m gonna look for a circle which isn’t here and I think that’s just because it’s listed as a texture. So I’ve already imported in the sprite closed circle. And if I change its texture type over to a sprite, and then I hit Apply, actually I see that it really is a circle. So you knew it was processing it as a texture, it’s actually a sprite, which is what we need for this. So coming back over to our sprite render, which is a component, obviously. We’ll pick our circle, we can kinda see it now. And I did a white circle, because it’s kind of a handy trick. So if you have a, A sprite that maybe you wanna apply different coloring to, if you have it white then really you can kind of apply any raw color to it, which is very handy. Technically not need in this, but. It gets the job done. That’s okay, and I wasn’t really sure what color I’d wanted originally. All right, so I’m gonna do the same thing that I do before, I’m gonna put it back over to 00.

Just to kind of reset it, I will bring it up a little bit, so you can look at it. I’m actually, I gonna need to rotate it, so when the player goes to click, obviously we don’t wanna poping up like that, we want it look like it’s flat on the ground. So, will change the rotation, to be negative 90, and then the position is actually going to be about 0.1. The reason I’m setting the position at 0.1, so again, bringing this over here. I don’t want to run the risk of that, basically happening because it’s on the same kind of axis. So if I do 0.1, it guarantees that it’s slightly above the ground. And we won’t run into any of that weird, kinda funkiness. And then the other thing is, I kinda want to bring the scale down. And we’re gonna pulse it up to probably about 0.75 or 1, and I don’t know which one’s gonna work better, but we’ll pulse it up a bit and then bring it back down to this size. I think that kind of sets it up, so I’m gonna put that back to 00 and then I’m gonna add what’s known as an animator component.

And what this is gonna let us do is create an animator controller and ultimately control the animations that would be tied to this indicator. So underneath the position indicator folder in the pre-fabs, I’m gonna create a new one of the Animator Controllers. I’m just gonna call this PositionIndicatorController. And then coming back over to this, I could either click this little object here to pull it up, I’m really not sure why this window is on that quite so large, it’s driving the bonkers or so, or you can drag and drop, okay? Everything else is about what we want, so I’m gonna leave all of that alone. So, coming over to this animator tab, if I right-click, I can create a new state this way. Alternately, with this game object selected, I can go from this route. So I can click Create and then go to our prefabs position indicator. And I’m just gonna create, we’ll call it Idol, it’s just gonna pulse up and down. So when I created this, a couple of things happened. The first thing that happened was, this top bar turned, these little icons turned red.

And then, technically I guess that did too. And then on this side, we have a new kinda node item on this, if you will, Titled Idle. And you’ll see that it’s orange, that means that it’s the default animation that will occur. So the second that this game object is available in the game, it’ll automatically start to run this particular animation. We won’t see anything, because we haven’t actually animated anything but we know that it’s at least there. So, coming back over the Animation tab, if I click on the right thing which would be PositionIndicator, I can add properties to it. So, you notice here, we’re no longer red it’s because we’re no longer doing what’s considered recording. So this little red button right here is basically the recording button, and that’s what triggered this certain stuff to turn red. And what that means is it’s basically paying attention to things that you do. So if we move it, it added some movements, and it added a keepring to it. So we don’t actually wanna move it, we’re gonna wanna scale it.

So if I keep that scaled and then I do, really, technically, I wanna keep everything at 0.5 to start. I can see that this got recorded. If you select on these and then you hit the period button. You can actually move forward a couple of frames. So well, let’s think, what do we want this to be? So I guess, add about, we’ll do 20. 20 frames, we’ll go up to 75. I don’t know if it’s gonna look good, so we might have to tweak it. I’m just gonna bring it over here. I’ll delete it, actually, I just wanna record. So, you can see it kinda pulls through. Let me turn off the recording. I am actually not a fan of doing the recording stuff. I just prefer to enter my values in raw. I just find that I tend to have really weird stuff whenever I record, and I’m guessing that’s just totally user error. Okay, so basically what I’ve done is I’ve set it up so that we start out at 0.5 scale. We go up to 0.75 and then at frame 40, we will come back down to 0.5. So basically, it will look roughly like this.

The other thing that we’re gonna wanna do, so this is where I say that technically this design is probably not the best that you’d wanna do. But it illustrates a couple of points, so you want to be thoughtful when you destroy game objects. So if you’re going to have something that maybe you’re using continuously, might make more sense to deactivate it versus destroying it all together. In this case, we’re gonna destroy it all together because that can still be a very, very handy method to do. So what I want to actually have happen is it’s going to scale up and down, which we’ve already seen. And then at the end of that, it’s actually gonna start fading the visibility down to nothing, and then a few seconds after that, the object itself will be destroyed. They’re gonna have it fade a few seconds after it finishes pulsing. So what you can do is you can mess with the alpha of a color. So I’m gonna go ahead and set this to be, it’s a little bit weird, but I’ll set this to be zero.

And we can see on the screen that it kind of disappeared there, faded away I guess, if you will. What I really wanna do is actually have this be our one. And this one should be a one too, which is perfect. And then I’m gonna go about five frames in. I’ll set this to be zero. Oops, All right, so that should do it. So if I push play, you kinda see a little bit. We’ll go a little slower. We’ll go by key frame by key frame. But you kind of see it starts to fade out at that point, which is what we want. So we’re gonna have it fade out pretty quick. Let’s actually bump it up a bit. And then, we’re just gonna destroy the game object, so it doesn’t really matter. But at least we leave a little bit more gracefully, okay so. I’m checking that. That is our animation I think that we want. So if I push play we should just see it. We see it kind of repeating on a loop, right? It does it, it fades out. But then it pops back up. And that’s really not what we want. We don’t want it to appear right after.

So having that shut off. If you come into the animator controller, and you Double-Click on your animation, You get loop time. So if you uncheck this, it’ll actually stop the looping of the animation. So pushing play again, we see that it ran and then it disappeared. You can also see here that it ran, and then it stopped at the end. And if it was on a loop, it would’ve kinda restarted and kept running. So this is a very handy window also for kinda debugging what’s going on with your stuff. So that, I think, is really kinda, all we need to do to setup the indicator. I’m gonna turn it into a prefab just because we’re going to, The way that we’re gonna do, we’re gonna do destroy it, and recreate a new one, so we don’t really need that. And then, under our player on our script we’re actually gonna add a little bit more to build up on this. So, Well that did not follow my normal formatting convention, but that’s okay. So, I’ll do gameObject. So we’re gonna have a new, gameObject, a public one for the position indicator.

And I’ll show you how you can work a little bit with the inspector. And the inspector is actually very handy to use. So we’ll do the position indicator. And then we’re going to do, inside of our Raycast, so inside of this. If we’ve hit something, we want the gameObject, or really the position indicator to appear in that spot. So where we know we hit something is here and so we’ll do gameObject. And technically, real quick for the record, you would probably wanna fine tune this a bit because this will trigger on any gameObject that has a collider. Which is fine for our game, but if you have, because we don’t have, we’re not really expecting people to click on things without colliders and we haven’t really built it up. Eventually, we’ll probably have to revisit this. But what you could see happening is you’ll have this Raycast hit or succeed, but it might not be a navigation mesh or it might not be a good point for that to go to. So that’s where you can kind of work with layers to get this to be a little bit more detailed.

And like I said, at this point we really don’t need to, but that is an option and something to be aware of, that you can run into. So what I’m gonna do is we’re gonna, again, operate on the notion that anytime this ever happens, the ground has been what’s clicked, so we’re good. And then I’m going to instantiate an instance of this prefab. So I am not instantiating the prefab itself, but an instance of it. And that’s very important to remember that kind of difference. So I’m gonna tell it where we want it, so it’s hit.point.x. So the reason I’m not just providing hit.point is because we want the y axis to be 0.1 afloat, which is what we had originally set, that was 0.01. Which is what we had originally set it in our prefab, which I guess technically doesn’t really matter, but it helps my peace of mind, I guess [LAUGH]. And then we’re gonna just provide it with the rotation. So we’re gonna do a Quaternion and then a Euler, and then we’re gonna do the 90 degree F. So it’s basically that same stuff that we had set in the inspector is kinda how we want this to show up.

The main difference being the x and z location are gonna be based off of wherever our Raycast actually hit. So if we push play, Almost made a mistake. So before we push play, you can see over in movement controller that now we have this position indicator gameObject. Actually I am gonna push play, it’s probably a good error to see. So if we push play and then I click, it gets an error. So, unassigned reference exception. Basically, what that is saying is, we didn’t actually tell it what this is. So you can either can do that in code or if you wanna use the inspector, you can just take the position indicator. So the gameObject we wanna work with and then drag it there. And when I push play again, and I click, we can kind of see that’s it’s there. What’s interesting is in our hierarchy we see it there, it continues to be there and now we have another one and another one. Right, so our hierarchy, the more that a player clicks could get a little bit insane. And actually, yeah, so it depends on the behavior that you want.

So, like I said, the behavior we’re gonna do is we’re just gonna destroy these after a while. You could technically keep the same one and just move it every single time, so you have it kind of fade out and then when the person clicks, it adjusts its position. I’m just thinking, [LAUGH], about how I would rewrite that. So you can do a lot of pretty neat stuff depending on what you want. But you can see, like this is definitely not what we want. We want either a managed version of these so that we always have a set amount or we wanna actually destroy them. But we certainly don’t want it to continue to create and exist. So we’re gonna destroy. The easiest way for us to do that is to create another script. And on this script we’ll call this disposition indicator. Oops, I think I spelled that wrong. Whatever. We’ll just pretend that, no, that’s gonna bug me, position indicator, I did it again, okay here we go. So one thing when you’re renaming your scripts, is you have to make sure that the name of the script actually matches, so in this case, they don’t.

Reload all, all right. Otherwise when one of you goes to do some compiling, you’ll run into issues. So with that there, really all we want to do. We don’t need Update. I’m just gonna invoke a method, so I’m gonna say, after a certain period of time, call this method. And all that method is going to do is destroy the object. So we’ll call it DelayDestroy. Oops. And then we’ll do Destroy. I can’t tell where my IntelliSense went, that’s all right. Invoke. So when you invoked, actually I’m going to copy this so I don’t, you provide it with the method that you want to invoke, and then the time that you wanna wait to invoke it. So in this case, we’re gonna wait three seconds, essentially. And then we’ll Invoke the DelayDestroy. And then that’ll be that. So the last thing to do. It created a new one. How interesting, I have never seen this happen. I think I’m also crashing. I think with how I did it, Unity must have tried to save it differently. And it’s never tried to do that before.

Well, there it is. It’s the bad one, I guess. I guess I will try to do a rename again. Let’s do it inside the [INAUDIBLE]. This is how I normally do it, we normally wouldn’t have to jumped into Unity. Let’s see if that fixed our. Okay, I’m gonna have to look that up after and see what I did that triggered it. Okay, so if I just take the script and then drag and drop it on our position indicator. Hit play. Now, you can see here, it disappears. So we can kinda do that same thing where we put a whole bunch and then we should see them start to destroy themselves after a while. So that is it for our basics of networking part two. Again, probably like the fifth different name that I have given it. Like I said, we’re gonna dive into this a little bit more. I wanna do some stuff with the off-link meshes, and then some more advanced movement. So at some point, we will come back and revisit this topic. So thanks for watching, guys.

 

Read the video

In this episode, we will add the finishing touches to the point and click style movement. We will use NavMesh Obstacles to define areas that our character should not walk through, such as the well. We’ll also show the player where they clicked by animating a simple sprite, instantiating copies of it every time the player clicks and then destroying it once the animation is complete.

Resources


dotGame

dotGame is a blog dedicated to game development with a primary focus on .NET technology. The episodes will focus on tutorials, tips and tricks and interviews. All tutorial project files can be found on the .GAME GitHub repository. Have a topic you'd like to see covered? Great! You can request a topic by opening an issue on the GitHub repository or by emailing dotgame@microsoft.com. General feedback can also be directed to dotgame@microsoft.com.

    Comments to Unity Navigation – Part 2

    • Keep up the great work! I've learned so much from watching your videos. One step closer to mastering Unity!

      Anthony G January 20, 2017 6:24 pm Reply
    • Hi there, when I uncheck the loop time, my animation still loops, and then i loose all animation when inserting the indicator using the script, any advise?

      Lee January 31, 2017 1:34 am Reply
    • @Lee: It’s a little hard to troubleshoot without seeing how you’ve got everything setup. How do you know that it’s still looping if it looses the animation when you create the Indicator? Is it that it loops continuously when you leave it in the scene? Can you post your project out so I can take a look? Also, it would probably be quicker to help you work through this if you either email the dotgame at microsoft dot com alias or open an issue on the GitHub repo.@Anthony G: Thanks – I’m happy to hear that you’re finding the videos helpful! 🙂

      StaceyHaffner February 5, 2017 7:12 pm Reply
    • Stacey,Great videos! I’ve watched Unity’s videos on the same subject, and I prefer yours. Your explanations are clearer, and sample code are simpler.

      RobGreenly March 8, 2017 10:09 am Reply

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Loading...
    1Code.Blog - Your #1 Code Blog