Introduction to Game Development (E18: raycasting)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello in this episode we're going to be taking a look at recasting the unity documentation describes it very well a raycast is conceptually like a laser beam that is fired from a point in space along a particular direction and the object making contact with the beam can be detected and reported I'll give three common examples of where this technique is useful although it does of course have many more applications so in a strategy game you might want to be able to place objects on the terrain to do this you can perform a ray cast from the cameras with the mouse position and detect the point at which the ray intersects at the ground in a combat game when a weapon is fired you could cast a ray going out from the barrel of the gun in order to detect which object was hit finally if you want to know whether or not an enemy is able to see a player you could cast erase from the enemy's position in the direction of the player and see if it reaches the player without colliding with anything else now unity of course suppose for a casting in both 2 & 3 dimensions but the implementations are slightly different we're going to take a look at them both starting with the 3d version all right so I have an empty scene here in unity and I'm gonna start off by creating a new cube object I'm gonna duplicate and move to somewhere else in the scene and then I will also create a new C sharp script called test 1 which I'm going to attach to this first cube and then open up now inside of the update method we can have our ray cast code so we'll start by constructing a new Ray chicken just called ray set this equal to new ray and the constructor takes in a vector3 origin and a vector 3 direction so let's apply it with the position of the object which the script is attached as well as the forward direction of that object then to store information above the raycast collision assuming that it hits something we'll have a raycast hit variable shall call hit info and we won't set this to anything because it will be the responsibility of the raycast method to actually assign to that variable now if we hover over ray casteist we can see that it's struct which means that it's a value type so if we want the raycast method to be able to assign to hit info hopefully recall from last episode that that means we're going to be using the Alt key word so it will see that coming up soon but first of all the raycast method is a static method inside of the physics class so we call that with civics dot raycast and as you can see from this little box here the method returns a bool so true if the Ray hits something and false if it doesn't and we can also see that this method accepts a variety of different parameters so just go through these all you can see there are 16 variations we'll use one of these simpler versions just passing in ray and then using the Alt key word to give it our it info variable all right now we want to know if I'll ray actually hit something or not so it's quite common to surround this method call with an if statement like so and in here we then of course have the logic for what should happen when the Ray hits something now for our purposes let's just make a draw a line from the Ray origin to the hit point so we can use the debug dot draw line method which is just a method for drawing lines inside of the editor the lines will never appear in a finished build of the game as you can see this takes in a vector three start and a vector three end so let's use radar origin as our starting point and hit info dot point as the end position and the third optional parameter we can also add in a color so I'll just use color dot reg let's then add an else statement so if no collision is detected then let's say debug draw a line from Ray dot origin to Ray origin plus rate of direction and we can multiply that by whatever we want the length of the line to be let's say a hundred and we can make the color green now I should mention that when we use the raycast method without a max distance parameter then the Rey is considered to go on forever so just because I'm drawing at only 100 units doesn't mean that the Rey is only a hundred units long if we wanted to restrict it to 100 units we could add a third parameter here max distance and set that to a hundred let's now save this and go into unity and press play so you can see a green line shooting out for a hundred units and if we rotate this configure ray updates and of course most interestingly when we rotate this Fitz facing the other cube then Z line turns red and ends at the hit point all right let's close out of that and go back into the script and explore some of the other parameters that we can pass into the raycast method so one thing that we can pass in is a layer mask so let's create a layer mask variable called mask and we're going to make this public so it shows up in the inspector and we'll pass this in as our fourth parameter all right let's save that and go into unity and here we should now see that we have this mask variable in the inspector we can select which layers the raycast should interact with so as a quick experiment let's create a new layer I'll simply call this test and I'll assign this test layer to our second cube and let's now start up the game so consider the raycast doesn't interact with it now but if we change our mask to accept the test layer then all of a sudden it does collide with this object now I should make it very clear that the array isn't just colliding with the mesh of this object it's colliding specifically with the Collider attached to it so if we remove the box Collider from this then the Ray can no longer interact with it so the object is to have either a mesh Collider or one of the primitive colliders such as the Box Collider of the sphere Collider in order for ray casting to be a possibility now ivory in Abel this so that rehearsing works once again and let's now examine what happens if I turn this Collider into a trigger so I'll enable is trigger and as you can see the raycasting still works exactly the same now depending on what you're doing that may or may not be the behavior that you want so happily there's an easier way to configure this in our script so let's head over there and add in a set parameter which is query trigger interaction so we can write a query trigger interaction and then we can choose from collide ignore and use global so collided obviously the default setting as we saw which does report trigger hits and ignore never reports trigger hits I'll show you in a moment what use global is but let's choose ignore and save that and now heading into unity I'll go into my cube and just remember to set the mask to test so now if we play this and rotate the cube it is colliding with the object as before but now if we change it to is trigger then it no longer collides so use global is just using whatever you have set up in your project settings over here so you go to physics you can see there's the slow query hit triggers that shows that the default behavior is to use hit triggers so going back to monodevelop we have now essentially covered all of the different things that you can actually pass into the raycast method so some of the versions of raycast will take in the position and direction of the Ray as two separate parameters instead of just this one ray object but there isn't any other type of information that you can give the Ray House method this is the lot of them so the only other thing left to explore them is what information we have available to us in our hit info variable so let's write hit info dot to get the full list and there's a bunch of stuff here but the main point is interests are first of all the collider which is also just a reference to the collider that was hit and then the distance so how far between the origin of the Ray and the hit point then there's the normal vector of the surface that was hit which I'll talk about in more detail in test 2 that we'll be doing in a moment and then the actual impact point now important to note is that through the collider we can get a reference to the actual game object so I wanted to over here you could say print hit info Collider game object dot name so now if we run this and I point this at the object you can see it prints our cube one and of course if we can get a reference to the object that also means that we can destroy the object so let's try doing match and say destroy hit info dot collider game object alternative reason also go through hit info dot transform game object let's save that and run this now and so as we rotate this as soon as it hits the object is destroyed of course with our reference to the game object we can also get components on that game object so we can get a script component and then call methods on that script so in essence we can do whatever we want with the object with detected ok that is everything that I wanted to look at for test one so I'm going to save the scene and head over to a single test to which I prepared beforehand and the scene has just got a terrain mesh with a mesh Collider attached and there's also this cube object which I've set up so that the origin is at the base of the cube so you can see if I rotate then it rotates around the base now let's go and char scripts and create a new C sharp script called test2 and what we're going to be doing in this test is recreating the first example that I described where you're trying to place an object on a terrain so let's create an empty game object I'll just give this a name like object placer and I'm going to attach the test to script to that let's then open up test two and we'll get a reference to the Q object that we're going to replacing so let's call this object to place and then we also want to reference to our game camera so I'll make a public camera variable called game camera then in the update method we're going to launch a ray that goes from the camera position through the mouth position so let's write ray can call the three once again but we don't need to configure this ourselves because the camera class actually has a very helpful method can write game camera screen point to Ray which as the some research here returns the Ray going from camera through a screen point and the reason this is so helpful is that the mouse position stored in the input class is stored in pixel coordinates which is a screen point so if we just pass that in there we already have our ray configured and we can go on to create our raycast hit variable once again pause hit info and then let's say if physics dot ray cast plus in our a and our itch info will then say object to place and dot position is equal to hit info dot point let's say slash and try run this will first want to assign our cube to the objective place variable and the main camera to the game camera variable let me just make this game window two larger and press play whoa okay so here we can see that our ray cast is hitting the cube instead of the terrain now obviously the best solution for this would be to create a layer mask and have our terrain object on a separate terrain layer but in the interest of time I'm simply introduce able the box Collider on the cube so now if I press play we should be able to drag this along the surface of the terrain now it would be very nice if the cube would rotate to match the contours of the terrain so let's go back into our script and let's examine this hit info dot normal variable so a normal is simply a directional vector that is perpendicular to the surface of a mesh at a particular point in this case that point of course being where the Ray hits the mesh so we can use this to calculate the correct rotation of our object let's write object to place dot rotation is equal to and now we'll be using a quarter naeun method called catonian dot from two rotation this takes in two vector threes a from direction and a to direction so we're trying to rotate from a upwards direction so the vector three dot up to the direction of the surface normal so hit info dot normal if we save that now go back into unity and run this we should see that the cube rotates to match the surface of the mesh just to give another example of where knowing the surface normal can be helpful if you want a projectile to ricochet or fair surface then you can calculate the direction of the ricochet using the projectiles original direction and the normal of the surface that's everything for test two in the final test we're just going to be looking at how things differ when we're working in a 2d environment so I'll switch over to my third scene which is just a default empty scene and India need to go into 2d mode and then just create a new sprite object we need a image here so I'll just use one of these default UI sprites maybe the knob let's press F to zoom in or mash and I'll add a circle Collider to it I'll then also duplicate this so that we have a target object place that somewhere up there and then going to the script folder I'll create a new C shop script called test3 this one we can attach to our first sprite let's open it up and we do at least all of the stuff we don't want and then in the update method let's start by examining the physics 2d ray cast message so the first thing to notice is that this one doesn't return a bool instead it returns a ray cast hit 2d object and also it forces you to pass in a vector two for the origin and direction there's no version which allows us to pass in a 2d ray so let's pass in transform dot position so even though that the vector three it will just take the x and y coordinates to make a vector 2 and then for the direction will pass in transform dot right okay now this returns a ray cast hit 2d as we saw so let's say ray cast hit 2d hit info is equal to the array class hit 2d return from the message but now since we don't have any bool we don't have any obvious way to determine whether run off we actually hit something so it turns out the way to do this is to say if hit info dot Collider is not equal to null then we know we've hit some things since otherwise there would be nothing assigned to the collider so in that case let's draw another line just with debug draw line going from transform block position to it info dot point and that's use colors of red once again otherwise debug dot draw line from transformed of position to transform dot position plus our direction which is transformed out right x let's say lengths of 100 and then we can use color Green as with the 3d version we are of course able to pass in a max distance to the raycast method so we could pass in 100 here if we wanted let's save this now and run the same unity so as you can see no line is being drawn and the reason for this is that the Ray is actually hitting the circle Collider even though it started inside of that Collider and that's a big difference to the 3d version if you remember in the first example our Ray was actually starting inside of a cube with the box Collider but it just passed straight through the Box Collider now in the 3d version that is the only possible behavior we can't make it collide with a Collider that it starts inside of but with the 2d system we can actually configure that if we go into a mono developed let's set this in the start method we can write physics 2d dot queries starting colliders and if we don't want it to collide with a Collider that it started inside then we can just set this equal to false and now if we run this you can see the green line being drawn there and if I rotate this around then it will turn red as it hits the other sprite all right so the only other things to mention about the 2d system is first of all as you probably noticed physics 2d dot queries hit triggers also exist so we could set that if we wanted and then the other parameters for the Ray casting are such we'll layer masks as with a 3d version and then there's also a min depth and a max depth so all the best is so I just go back into unity is when you're working in 2d mode you thought sprites appear in front of other sprites by changing their Z values so a spiced with a lower Z value will appear in front of another sprite so if I set this with a third value of zero whereas the other one has 1.3 then this one if I drag it over will appear on top so the min depth and Max depth just specify what range of Reds values the raycast will actually interact with and by default the human depth is set to negative infinity and the max depth is set to positive infinity so it will detect collisions no matter what the Z value is which by setting that you can make it only interact with foreground elements or background elements and so on right that is everything for this episode so I hope you are now more comfortable with ray casting and I'll see you in the next episode until then Cheers
Info
Channel: Sebastian Lague
Views: 125,300
Rating: undefined out of 5
Keywords: Learn, game development, unity, code, how to, make games, programming, C#, unity3d, raycasting
Id: fFq5So-UB0E
Channel Id: undefined
Length: 20min 58sec (1258 seconds)
Published: Wed Mar 01 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.