You can find our latest VR courses here: Virtual Reality Mini-Degree
Transcript Part 1
Hi there, welcome to the course. My name is Pablo Farias Navarro and I’ll be your instructor. In this course, you’ll learn to create a room-scale experience where you are a giant dinosaur and you have to fight, throw things at these other dinosaurs that are coming at you.
So this is a lot of fun. You can tear buildings apart. You can go and destroy buildings and try to sort of throw things at these dinosaurs and this experience works with SteamVR-compatible controllers, so that includes the HTC Vibe, which is what I’m using now, but it also works with Oculus Touch and other SteamVR-compatibles of smaller manufacturers as long as they can be mapped to Unity buttons. So that is pretty cool.
Now if you don’t have hand-tracked controllers, at the end of the course, we are going to be adapting the experience to work with a reticle as well. So this will work basically on every single platform, whether it’s desktop or mobile. Of course, the hardware requirements are different on each one but we’re going to adapt it for, so that everyone can play this game.
Something I want to mention is that please be careful when you play this game because it’s very easy to hit things around you, to reach the walls in your room and please don’t hurt yourself. Be very careful when playing this experience. So take care of yourself. And now, well, let’s go and destroy the rest of the city and let’s go now and take a look at the learning goals of this course. Now our learning goals. We’ll be doing a lot of things in this course. So you’re gonna get very familiar with the SteamVR SDK.
We’re gonna learn how to use the hand-tracked controllers, how to set up your play area, different game settings and cameras as well that are involved in the process, but we’re not just going to learn how to use the SDK. We’re also gonna see what Unity has in store for us to use natively. Unity actually will help us with quite a bit of support fro OpenVR-compatible controllers. This includes the HTC Vive and also the Oculus Touch, so you can make this work with Unity, at least reading the input, the different buttons without really using any external SDK.
We’re gonna learn different actions when it comes to the controllers, how to carry objects, how to throw objects, and we’re gonna build of course that full-scale room-scale experience you just saw. At the end of the course, we’re also going to adapt that room-scale experience for mobile VR or reticle-based VR, for example the Oculus Rift when you’re not using the touch controllers, and that will be an interesting process because in a lot of our other courses, we do the opposite. We’d start with a reticle-based experience and then we adapt for the controllers, whereas here, we’ll go the other way around.
So we’ll build a room-scale experience designed for the hand controllers and then we’ll do our best to adapt it, and it ends up being quite fun as well, to a mobile VR or a reticle-based virtual reality.
Now a distinction I want to make, and I’m gonna be repeating this a few times, is that I want to distinguish between OpenVR and SteamVR. OpenVR is an open-source API that anyone can use, any manufacturer can use, to create headsets that are compatible with this API. Now the SteamVR is a runtime where OpenVR-compatible applications can be executed. So that is the difference between both things. OpenVR is a standard and SteamVR is a runtime that you install on your computer and that’s what allows your games to run. Now everything you’ll be learning in this course has applications way beyond game development. With these skills, you can build all sorts of training applications, all the way from mining to healthcare, tourism.
People are building amazing things with these technologies across the globe, and now you will be able to do it as well. So if you have an idea and if you haven’t seen anything like that, it is a good time to jump in and start building things. In my opinion, this is a bit like learning HTML or web development in the ’90s, when not many people really understood what could be done with the web and those who did are pretty much today’s billionaires. So I’m not saying that is going to be the case here but I think it is a great moment to start building things in virtual reality, and that is why I’m doing it as well.
So when it comes to our courses, our main goal is always to empower people to make the best of their own learning style. We don’t try to impose a learning style to anybody. Our courses can be viewed in whichever way suits you the best. Some people prefer to watch everything at once like a Netflix show. Other people like to really pace themselves and watch a couple of videos a week, and other people will spend more time in the source code that you download in the asset files. So it is all really up to you.
And we strongly recommend people revisit lectures and really plan for their success because if you set yourself a goal and you start working on your own projects, you have really high chances of achieving those goals and achieving the creation of a game or an application.
So I strongly recommend you to start working on your own projects and learn as you go and remember that you can watch these videos as many times as you want and you have lifelong access of all of the content.
All right, so thanks for watching this introduction. Without further ado, let’s get started.
Transcript Part 2
In this lesson, we are gonna get the controllers to work in our game. So, to begin with, I’m going to expand here on the origin, and we already have one tracking object, one tracking volume, which is the head, the head-mounted display. We want to have two controllers. So I’m gonna go here and add an empty object for each one of the controllers. So I’m gonna add two empty objects. I’m gonna name one of them Left and the other one Right.
So, these two objects are going to be the tracked objects for our hand controllers. So, what I need to do next is select, let’s start with Left, select Left and go to Add Component here and find the component named Steam VR_Tracked Object. So I’m gonna select that component, and in Index I’m going to select None. So I’m not gonna give it the head-mounted display index that was there by default, and I’m not gonna select a device because that is assigned automatically for you. So, there is this field here, Origin. So I’m going to drag my origin object to that field, and I’m going to do the same thing for Right. So I can just delete Right and just create it again and just rename it Right.
And just to show you real quickly how this works, I’m going to go here and add an inside object. Let’s do a sphere for the Left, and let’s make that sphere a lot smaller than one, like 0.1. 0.1, 0.1, and for the right one, I’m gonna go and add something else. Let’s do a cube. I’m also going to reduce the size of the cube to 0.1. And now I’m going to select my origin, and I’m going to add a controller, which is going to take care of tracking all of those other elements that we created. So this will be a Steam VR_Controller Manager.
So you need to have this one added on the origin. Sorry, this was the wrong one. This is it, Controller Manager, so we added Test Controller by accident. So we need Controller Manager, and see how we have both Left and Right fields here. So I can now drag my Left controller, place it there, and I can drag my Right controller and place it there.
And if I now go and press play, and I’m going to make sure that, let’s do this and maximize and play, and I need to make sure to turn both my controllers on and get the headset over here. We can see that this is one of the controllers, and this is the other one of the controllers. And also see how they disappear when I get it too close to the camera. So that is because we need to adjust the near clipping plane of our camera. So we need to do that as well. So I’m gonna go now here and stop the game. And I’m going to expand on the head here, and the head camera is the one that we see on game mode. The eye camera is what you see in the head-mounted display.
So the near Clipping Plane is going to be the minimum, or it can be something smaller like maybe 0.1 perhaps. But I’ll just set it all to the minimum and go and press play and try that one more time. So let’s get one of the things here, and now I can get it a lot closer to my face, basically. So, that’s how you can add tracked objects, and this could be, instead of a sphere, of a cube, it could be any 3D model that you want. It could be a gun or a baseball bat or anything, a flower. So now instead of having the sphere and the cube, I want us to be able to show the HTC Vive controllers. So I’m going to delete those two things, and now on Left I’m going to add in here an empty object, and I’m going to call this Controller Model.
And in here, in Add Component, I need to find the Steam VR_Render Model. And this will allow me to see the control itself and also to have things such as indicating what button is being pressed, for example, or when I’m touching the touchpad, it will show where my finger is placed. So, in here we have to give this a Shader. And I’m going to click there, ^and I’m going to find the Standard shader, which is a shader that comes in Unity ^that you would have used in the past to create materials. So we need that, and that is for one of the hands. So I’m going to duplicate this and place it on the other hand. And now I’m going to go and press play, bring in the headset and here we go. We’ve got the controller.
And see how I can, for example, press the trigger button, or I can move my finger there on the trackpad. So, that is because we are including this component, this Steam VR_Render component that has access to all of this, it gives us all of these features out of the box for us to use. So we didn’t have to code the behavior of pressing the trigger, for example. We can just use it directly from this object here that came in the Steam VR plugin. So, now that we have the controllers, it would be really cool to be able to hit something or to move something in virtual reality.
So, what I’m gonna do here is create a material for the floor, so it’s not white. So I’m gonna create a folder called Materials, and in here I’m gonna create a new material, which I’m going to name Ground Material. So this will be a dark green, and we are going to move that into the scene view. Let’s keep these cubes the way they are. So I’m gonna add a component to these cubes, which will be a Rigidbody. One of them already has the Rigidbody because I added it before. So, I’m just gonna add it like so. Rigidbody in that one, and now they both have a Rigidbody. So they are just normal Rigidbodies in Unity.
And what I’m going to do is select them and duplicate them, so we have a few of them near us. And now, what I want to do is make my hand controllers, so that they can push them because at the moment I can go through this, and nothing happens. But I want to be able to actually move them. So, for that we need to give our hand controllers a collider and a Rigidbody. Let’s select both of these models here.
So I’m going to give them, first of all, a collider. So it could be, let’s say, a Sphere Collider, and it can be a very small Sphere Collider because your hand wouldn’t be in here. One Unity unit is one meter, so your hand wouldn’t be one meter, it would be a lot smaller. So, we can give this collider a smaller radius, for example, let’s choose 0.1, Radius, and also, they need to have a Rigidbody. But now, the Rigidbody of our hand controllers shouldn’t respond to forces because the position of our hand controllers is given by the tracked volume, by the tracked object.
Basically, your controller is determining the position and the rotation of your model. So, this should be a kinematic Rigidbody. Basically, it won’t respond to forces. We will modify it, transform directly through the Steam VR_Render, sorry, through the parent object here, Tracked Objects. So if we now go and press play, we should be able to push this. So we can push these things, and we can move them like so. So, I guess we should bring them a little bit closer, so that we can do this better.
But as you can see, we’ve just pushed it down, and yeah, so let me show you now what would happen, if you didn’t make them a kinematic Rigidbody. If they were just normal Rigidbodies, they would basically fall with the gravity, and they will be just on the floor, bouncing around, and you’re not gonna be able to move them.
You are gonna be moving just the containing object, basically. But the controllers themselves are just gone. So because it’s behaving like a sphere, basically, it went rolling. That is why you need to set this as a kinematic Rigidbody. So, to summarize here, what we did was, first of all, inside of our origin, we created all of our different tracked objects. So we already had the head, which is the head-mounted display. And now, we also had two more tracked objects. Each one of these tracked objects is a controller, and controllers in this platform have six degrees of freedom, they can rotate about all three axes, and they can move, they can be positioned across x, y and z.
So, the origin object here needs to have this Controller Manager script, which basically tells it, hey, we are gonna have two hand controllers, this is their location. These are the objects that we passed on, these two objects. And these two objects themselves, they have the Steam VR_Tracked Object script, and inside of them, whatever you put inside will be moved because we are moving just the parent here. So, as you saw before, I could place a sphere, I can place a cube, I can place any model exported from Blender or from any other program. It can have any 3D model that I want in there.
And if you want to have the default controllers of the HTC Vive, you have to add this Steam VR_Render Model script, and then you have to specify the standard shader here. So that’s what the whole process was, and if we want these objects to be solid, so that you can push other things around, you have to give them a Rigidbody, a collider first because you always need a collider for Rigidbody.
And the Rigidbody is not going to respond to external forces. So it needs to be set as kinematic. It means that we are gonna be modifying its transform directly, which is not something we are gonna be doing. But the SDKs of the head-mounted display and the controllers will be doing for us. Now, regarding all of these scripts that I’m adding here, all of these components, I don’t want you to think of all these things as black boxes that make no sense. Inside of SteamVR scripts, you can find all of these different scripts.
So, for example, you can go to Tracked Controller, and you can read through the code. So the code unfortunately is not very well commented, if not commented at all. But you at least get an idea of what it is about, and you don’t have to understand all of the code, but at least it will give you an idea of what is happening, of what objects are being called, or how they all relate with each other. For example, the Render Model is here, and you’ll see a few more of the options and a few of the methods. And some of them have public methods that you are able to call from somewhere else.
So, at first it’s going to be a complex code, there is a lot to it. But don’t think of these scripts as a black box. Just have a read at some of this code, and over time, as you are developing more games, and you spend more time with this platform, you become more familiar with what the different scripts do, or what works inside of them. And you might even find parts of the code that you can reuse on your own scripts.
So that’s all for this lesson. I will see you now on the next video.
Transcript Part 3
Hi everyone, welcome to this lesson. Let’s dig in by creating our level for which we are going to bring in a few external assets. We’ll be creating a simple city with buildings made of individual blocks, so that we can tear them apart.
Okay, so I’ve created a new project and I’ve saved my scene in the Scenes folder, and what I’m gonna do now is bring in some textures for the floor. So we are going to start with that. So we want to create a folder called Textures, and upload a couple of images that I’m going to bring in. So I’ve got an image for the grass, like the grass pattern, and also an image that we can use for the streets.
So in here, I’m gonna create a new object, new, where is it, Game Object, Create Empty, which I’m going to call Environment, and inside of that, I’m going to add a plane, and we are gonna also, we’re also going to position ourselves in the origin. So our camera, put that in the origin, and make our plane a lot bigger than that. So I’m going to extend our plane to let’s say 10 on each direction.
So we’ve got a pretty decent-sized plane here, and we are going to give this plane our grass texture here that we brought in. So I’m going to create a material for that. I’m going to create here a new material, Materials folder, and this will be a new material which I’m going to call Grass Material and this material is going to have as albedo our grass texture, and we are going to drag that onto our plane, and rename that to Ground.
Now we do want to have a little bit of tiling here because otherwise these things look absolutely huge. So if you find here the tiling part, let’s do 10 as the tiling, and actually maybe even more, like 20, and that can always be adjusted. Actually I’m gonna go with like a number of 40, 40 here. Okay, so that can be adjusted later as well. And you can play here with the smoothness or the different settings. In this case, I just want to get a little bit less of a reflection, so I’m going to make this less smooth here. All right, cool.
So we have that, and if we want to make it a bit darker, we can also pick a darker color here. I think maybe something like that will do. Let’s make that more greenish, okay. Now for the streets, I’m going to create another plane here and I’m going to add that plane in here and I’m going to create a material for the streets. So this is going to be a new material. I’m going to call this Street Material, and assign the roads the roads texture, the street texture to it and we can give that to this new plane here, and that new plane also can be positioned a little bit above the other one so that we don’t have this area where they are both at the same location. So this can have a position on y of let’s say 0.01. Even that will do.
When it comes to collision, I’m just leave the collider of the ground; I’m not gonna add a collider to the streets. I’m going to remove that mesh collider here, Remove Component, and I’m going to call this Road. Now the size of the road, I want it to look really small, and I’m just gonna do this by eye, by trial and error. I’m not gonna set like a fixed scale and adjust everything in a realistic way. This is just a game and what I’m gonna do is basically move my camera up to a height that is that of a person, like for example, to 1.7, and then I’m going to make it look down a bit, and I’m just going to scale the road down until it looks like the way I want it to look and until it looks small enough for me.
So it’s gonna be mainly by trial and error. So I’m gonna select the road, and I’m gonna change the scale of this road. I’m gonna reduce the scale until it kind of looks like, I want to feel like I’m really like a huge monster here. So I’m gonna set the scale of that to 0.06. I’ll leave it like so, and I’m also going to extend this road all the way to the horizon, so that it will be increased here by 10. So we’ve got a road and the material itself, I want it to be tiled so that it doesn’t have a fixed line. It’s an intermittent line. So I’m gonna select Street Material and scroll down to Tiling, and this would be I think a tiling of y. Let’s try it at state 10. Let’s type 100. Let’s type 150, or maybe even 200, and I think that is okay. So I will leave it like so.
So we’ve got a road there, and what we can do is we can copy that road, and we can duplicate the road, control + d, and whoops, I thought I was duplicating it. Let’s try it again, control + d, and then we can have like five little streets in this way. So this is all just creating like a simple kind of city environment here. So don’t be afraid to modify it or adapt it in a different manner. All right, so we’ve got a few streets there and I’m going to now have streets that go in the other direction, so I’m gonna rotate this. I’m gonna rotate it on the transform here about y, on 90 degrees, and to position this in a, like where the player is, and duplicate that. Whoops, I’ll try that again, duplicate that, and try to get one that I can see. Yep.
So I want to get a bit of a grid in the central area, and you’re not really gonna go anywhere further, so, just add a few streets like that. Okay, cool. So we’ve got now a few blocks, and now we obviously want to have also buildings. So I’m going to bring in more things here. I’m going to get more models that I have here, and I’ve used different programs to create the models. So I will show you how I export the models from Magicavoxel.
So I’ve got a tree here and what I do is go to Export here in the bottom and click obj, which is a format that Unity can handle, and then I’m going to find the corresponding folder for this particular project, and I’m going to go to Assets and it’s, in Unity I’m going to create a folder here in Assets called Models. And so going back here, I’m going to save this in Models. I’m gonna call this Tree Model. And back in Unity, I will now be able to find the tree in here. So let’s, to keep track of where the player is, actually I’m going to select the main camera and I’m going to give it a color here of a color red, so I can know where it is on the map. So let’s see where it, it’s not even showing here. It’s too small, okay.
This is the area I’m interested in. I’m not gonna do stuff besides in this area. So let’s bring in a tree, and as you can see, it’s huge. And we need to also drag its PNG file that comes with this export onto it. Let’s try selecting it and there we go. So it looks good like so, and this tree, as you can see, we have this outer object and also an inner object, and the inner object is the one that contains the model itself, so I’m going to rename the inner one to Model, and the outer one to just Tree. The Model is going to be scaled down. I’m going to make this a lot, a lot smaller than that.
So let’s try, and the reason why it is scaled up, is because one unit in Magicavoxel, usually when you export things into Unity, sometimes the units are just a bit different. So I go here and if I added a cube, you’d see that one unit in Magicavoxel is one Unity unit. So that is why this thing is massive because it is very small in Magicavoxel but each one of these is exported as one unit. So I do need to scale that model down. I’m gonna scale it by 10, so 0.1 here, 0.1, and I think that will do.
So we want to give this a collider. So I’m going to give the outer object, the tree, I’m going to give that one a collider, a box collider, and I’m going to, I need to move this collider so that it matches the model. So let me just select the inner element. So the inner element should be actually in position zero here, and we should just be moving the outer element. So what I’ll do here is give this, is modify the collider manually by clicking here and so let’s bring in the side view and move this collider up and this part up as well and make this match the sides, the correct sides of the tree and let’s bring in the other side view and fix the other side as well. So there we go.
We’ve got a tree now with a collider and we can, we can now move it around, do whatever we want with it, and I actually want to give this a rigid body with gravity so that we are able to grab that and to kick it around or to move it around. So it’s got a rigid body with gravity.
Okay, so now I’ll leave it up to you to decorate this. I’m going to create a prefab with this tree, just in case we make modifications to it. So I’m gonna save this as a Prefabs, and I’m going to move my tree in here and then I’m going to move this inside of Environment, and maybe create an empty game object here called Trees, to place all of the trees in there. And now with my tree selected, I’m going to duplicate it and have a small avenue here with trees. So I’m not gonna be able to build the whole city in the video. I’ll build it offline and then show you the result but I’m just adding just a few trees so that we can get started at least. Okay, so we’ve got the trees now and we also want to have buildings.
Now what about the buildings? The buildings were also created with Magicavoxel. I have already exported them into OBJ files with the corresponding PNG files. So I’m gonna select all of these and all of the files that we exported, I’m gonna select them expect for the tree that we already brought in and I’m going to select here the Models and import this whole thing into my game. So we’ve got, let’s start with the black box, it’s just a big square here, and give it its texture, and then what I’m gonna do here, I’m gonna give this a rigid body and I’m gonna give this a box collider because that will, it will just fit in automatically with the, oh, I thought it would fit in automatically. It didn’t fit in automatically.
We are actually just gonna use the inner element here. So I’m not gonna use the outer element. So I’m gonna expand that and I’m going to just move the default out here. Yes, continue. And I’m going to delete that. Just keep the outside one. Rename this to Black Block, and I’m gonna give this one a box collider which now fits perfectly, and I’m gonna give this a rigid body as well, and I’m going to scale this down to 0.1, 0.1, 0.1.
We could have done that with the tree as well but sometimes I prefer to use the outer object, but in this case, since it’s just a box, I am gonna do it like so. All right, so that is a single element and we are going to make a prefab out of that. So you can do the same with the other buildings if you want to have like multiple color buildings in your city, and now that we have a single block, we can start building actual skyscrapers here.
Okay, now I’m testing this with a virtual reality headset and it is important to test your things on virtual reality as early as possible because when I’m testing now I realize things are still a little bit too big, like the trees are too big, the buildings are too big. I don’t have enough room-scale area to walk to a building for example. So I’m going to reduce everything by probably like 25% or a third of their current size. Okay, you just saw what the game was looking like in virtual reality, and I’m basically traveling back in time now so that we can fix the scale of a few things because the way that we were doing it was just too big. So for the individual block prefab, the current scale now is 0.02. I’ve also scaled down the roads.
The roads are now scaled on x on 0.02. So that is a new number for the roads, and we can, I’ve also changed the grass material and I’ve increased the tiling to 80, and I’m actually going to increase this to 100, and the street material, I’m also going to increase the tiling here to 300 or even 400. So that is so that we have more frequent lights. Now the trees themselves in the prefabs here, for the trees, expanding on and see the Tree Model, I’ve also scaled that to 0.02, and I moved the roads so that we have like a closer grid now around the player.
So now we can resume where we were at, which was in the creation of the buildings. So we’re gonna create our first building and then I will show you a problem that will happen with this when you are working at this size in Unity because Unity wasn’t really made to handle small things like a physics engine. In normal 3D games, elements that have physics are usually bigger, so there are some issues sometimes.
So all right, so we’ve got our prefab here and I was playing around with a physics material before so I’m going to disable that. So all right, so we’ve got our prefab here and to create a building, all you have to do is just, you can just duplicate the object and then you can use Vertex Select which is when you press the letter v in your keyboard to pick the vertex you want to drag around and you can easily position that vertex in the same position as the other vertex so that then you can have bigger areas. So you can do that again, duplicate, and control, I mean, just v and there, and I’m going to do that again, and we can position that in here.
So this allows us to quickly create the floor of the building, and now that we have that floor of the building, we’re gonna place all of those, all of those elements here. Let’s organize our structure a bit, so I’m gonna have here a road game object where I’m going to place all the individual roads, and we’ll do that same thing for the buildings. So let’s create a, I’m gonna keep the buildings separate because they are not really, they are something that will be moving, although the trees will be moving too. Let’s just place it here, okay?
In Environment, this will be Buildings, and in here I’m going to create an object. I’m gonna call this just Black Building, and I’m gonna move all of these elements inside of this object and, and, let’s then duplicate these, control + d, and move the new block up here. So I can press v again, and I can move this down. I can press again control + d, duplicate, and duplicate, place it like so. So I want to show something that will happen once we create a tall-enough building. So I’m gonna go one more and press v to select a vertex and place it there. I think this might be enough for this to trigger.
So what will happen is that when you press Play, some of the buildings will collapse. Well, this one didn’t collapse, but you can see a little bit of a crack there, and what happens is that the physics simulation is not 100% precise, so when you stack, even if you stack a bunch of generic cubes, there is a little bit of movement. So for example, if I select any of these cubes and we pay attention on the y coordinate, when I press Play, there are slight changes on them but they are very, very small, but those kind of adapt and you can have some of the buildings collapsing.
One way to make that a little bit less impactful, you’re still gonna get the cracks, but I saw that the buildings would collapse a little bit less, was to give them a higher mass for starters, so instead of 10, we can enter, instead of one, we can enter 10. So that might help a little bit, or even 100. That will help a little bit to keep them together. So that is something we have to deal with and also if you go to Project Settings and you go to Time, the default physics simulation timestamp is 0.02, so if that is decreased, the simulation is more precise and you get a little bit less of that but then at the same time, you also get higher CPU usage. So that is a bit of a tradeoff you have to do.
All right, so I think it’s clear now how to generate the city, so I’m not gonna do that on camera. Basically, I’ll create a beautiful city on my own, a few buildings of different colors, and what I’m gonna do in this lesson to finish is just add the dinosaurs. So the dinosaurs that you would have seen in the VR video are actually generated in, created in Blender, which is another 3D modeling program and I will show you how I export the models from Blender into Unity.
So basically, the model is here and I make sure to put the origin at the bottom so that then when I set y equals zero, it is positioned on the floor level. Also I apply all the transforms here, so that is all zero. And this is more important when you are using, when you are using backgrounds where you want to bake the lights. You select that inverted triangle and add a UV map but that’s not really gonna affect us here.
Anyway, so I’m selecting my model with A, and then I go to File > Export > FBX, which is a format that Unity can work with, and then make sure to click that Selected Objects here and also check that one, and then you just find the corresponding folder and click Export. I’ve already done so. I’ve already done that, and then in Unity, in Models here, the way you bring it in is quite simple. You just drag it into Unity.
So you’ve got that giant dinosaur, and now there’s only one issue. We have local coordinates selected, and as you can see, the local forward coordinate points up, and I generally like my models to be facing towards the forward coordinate because then you can just tell it to go forward and it’s just easier for us to work with. Otherwise, if you tell this to go forward, it will go up. So the way to sort that out is to place this inside of another object. So I can go and create an empty object. So we’re gonna place that empty object on zero and give it no rotation whatsoever. So that’s just an empty object there. And I’m going to place my dinosaur model inside of that empty object. Position-wise zero, but we’re gonna leave the rotation.
So if we select the parent object, as you can see, we’ve got the forward in the right position. The inside model doesn’t have the forward in the right position, but that’s okay because we’re only gonna be dealing with the parent here. So we’re now gonna close this and forget about the inner child there. We’ll call this Dinosaur and we’re gonna give this a, I think the size, I’m gonna keep that giant size, and, or maybe it’s just way, way too big.
So let’s reduce the inner model. So let’s change the scale here to like half the size at least, and, and now let’s go back to the parent, okay, and we will give the parent a collider. To make it easy, I’m gonna choose the box collider. So let’s bring in the side view and edit our collider, so click Edit Collider there. So this is the area where the dinosaur’s going to be causing collisions, and it’s the area where we can throw things at it as well. So bring the other side view and something like this will do, and the top view, just to have an idea. Yeah, I think that’s fine.
So this is our collider for the dinosaur. We’re also gonna give the dinosaur a rigid body, which is going to be kinematic because it’s not gonna respond to externals forces. We will be controlling its transform using a script. So that’s it for the dinosaur. We’ll make the dinosaur a prefab as well and we are going to position four dinosaurs in here. So we’ve got the player there in the center. We’re gonna have a dinosaur here. Let’s press control + d to duplicate, and another one here, another one here, and another one here, and we are gonna make them all face towards the player and walk towards the player.
I’m gonna create an empty object for my dinosaurs, Dinosaurs, and move them all in there, just to keep this a little bit more organized. Okay, well, that is all for this lesson. So now the challenge for you, the open challenge for you, is to create a city. You don’t need to create a whole city. Just, it really needs to be in the area near the player and maybe a few other things here and there so the dinosaurs can sort of drag around a bit of trees and rubble and other things.
So that is all for this video, and I will see you on the next video with a beautiful city built around us.
Transcript Part 4
In this lesson, we are going to adapt this game for virtual reality platforms that don’t have hand tracked controllers, so this can be the Google Cardboard, the Oculus Rift when you are not using the Oculus touch controllers, and it can also be for platforms that have a pointer like controller, like the Samsung Gear VR, or Google Daydream. Basically, I will be adapting the game to work with Unity’s VR standard assets and some files to work in virtual reality projects that I’ve previously developed in other VR courses, the Zenva VR library. So, we’re going to start here from the beginning.
We’ve got the dinosaurs working, when the dinosaurs find the player, it is game over, and the way the games is going to work for this type of system that have a reticle, basically, is that you’re going to be able to look around, and to use the reticle to grab anything that is around you and then once you click again, you’re going to be throwing the block. So you’re going to be able to grab blocks, and then move around that block, and then throw the block away. So, the very first thing we need to do is position the camera at the height of the player, because at the moment the camera is positioned in zero, pretty much, this actually should be zero here, and the reason being, the reason being, actually it should be in the origin, let’s put this in the origin.
So the reason this is placed in zero is because in platforms that have hand track controllers, the height of the camera is given by the position of the head mounted display, but in platforms that don’t, where the head doesn’t have this kind of position tracking, you need to give it the height that you want the player to have. For example, if you want the player to be at 1.6 Unity units, or two Unity units, you have to move it to that location. But we won’t be using this camera. In fact, we need to import some files to our project.
So I’m going to bring in a few things here. I’m going to bring in first of all the VR standard assets. So you can also find those files in the assets store if you search for a plugin called VR Samples. I think I misspelled that, but I might still find it, no, let’s try again, VR Samples. This is a package created by Unity. Now that is going to include a lot of files, a lot of models. I already have here just files that I normally use. These files have been fished from that other folder, from the plugin, so I’m just going to bring this into my project, and then I’m going to bring in this Zenva VR folder, which includes tools that are developed for other virtual reality courses, and that will make our life easier here.
So the very first thing I want to do is I’m going to get rid of this camera here, and I’m going to expand Zenva VR prefabs, and bring in this VR camera here, and position that in the origin. It already comes to it a height of 1.8, we’re going to leave that, or maybe we’ll lower it down a bit, we will lower it down a bit, but we will decide that once we press play.
So let me show you what’s in this camera. This camera we already have elements of the VR standard assets, we already have a reticle that’s ready to go. We have the VR EyeRaycaster, which is what allows you to work with the reticle to basically select objects in the game, and interact with them. We’ve got the ability to detect input, and this works in all different VR platforms. And we also have a script that I wrote here called Drag Camera, and what that allows you to do is, I’m going to press play to show you, is to use the right button of your mouse to be able to move around like so on game mode, so that makes life easier. Now, we are a little bit too high here, so I’m going to bring the camera down until this feels okay.
So let’s set the coordinates to global, and then bring the camera down a little bit, so let’s see, like what about there? Maybe we can even go a little bit lower, something like that might be more suitable. Okay, so the height here is 0.8, so I’m going to stop the game here and just change this to 0.8. So we’ve got that height now set for us. Cool!
Now what about the reticle? So I think we should be having that reticle there, yep, so we’ve got that reticle there. So basically we need to be able to grab elements that are within our reach, so we need to define how far we should be able to grab these elements, or how far away they can be, and, so I’m going to bring in a cube here, just to have an idea of the units. So this is just this one Unity unit. So I think if we set this number to, even if it’s like two units away, that is quite good, because then we can grab anything in quite a big area, or you can even reduce that to like one or 1.5.
So, we will be using, in order for us to drag objects, we are going to be using another script here from Zenva VR, which is covered in my puzzle game virtual reality course, but I’ll give you a quick overview of the script.
So this script here, actually the Draggable is the one that we need, not Drag Camera, Draggable, Drag Camera is what we are using here to move around. Draggable is a script that uses the VR standard assets virtual reality interactive item component, it works along that component, so that needs to be present in the objects, and this really allows you to grab elements with the reticle and then to, you can drop them as well. And there are events here that we can use to, let’s see where that is located, we’ve got two events that we can hook into when we start dragging something, and when we drop it. So, what we’ll do, is when we drop the item, we’re going to throw it away. So let’s start by just setting this basic behavior up.
So this Draggable needs to be added to whichever blocks or elements in the level we want to be able to collect. So I’m going to go to my prefabs folder, and I’m going to select all the prefabs except for the dinosaur, because I want to be able to grab all the types of blocks and also the trees.
So I’ve selected all of them, and then I’m going to scroll down, add components, drag Draggable, so now they all have the Draggable component, and the maximum distance, the distance where the element’s going to be positioned from the camera, we’ll make that a lot closer, we’ll try that with 0.5 first. So when we grab something, it will be at a distance of 0.5. And the maximum distance that we can grab something from is going to be one Unity units from us. Which as we saw before, it’s a pretty decent distance for the scale of this game.
What happens when you drag something? Let me just show you here what happens when you drag something. When you click something, handle click. When you grab something first, you are checking that you’re not already dragging something else, so you’re checking that you are ready to drag, in case you want to disable that somehow, and we check that distance is not too far away. So if it’s too far away, we leave the method. But if it’s not too far away, we will keep track of the current state so that we are not going to be able to drag again until we drop it.
In this manner as well, we’re going to call an event, and when we are dragging on Update, basically we are going to be positioning the element at our distance from our camera. So wherever we look at, this object will follow the camera forward, by the distance that we specified, as a parameter here, which I am setting as 0.5 Unity units.
So now that we’ve given this components to all of these elements here, that will add it to everyone in the level, basically, all the buildings and the trees, and, see how the VRInteractiveItem script was added automatically, because we were requiring that, from within our own script. Okay, so let’s go press play and see what we get, see what this looks like, so I’m going to press play here, and I’m going to grab one of these, see if I can grab something, if I can click. Yes, so I’m able to grab this, that is just too far away, so we might need to increase the size a little bit.
What happens when I click again? It is just, it is dropped. So where is it being dropped? I think it’s just being dropped on the floor. So we can go, this is a little too far away, so we definitely need to increase the size. So I’m going to grab this one on the top, and I can drop it again, and it will be dropped at my current, hmm, let’s see where it’s being dropped, so I’m not so sure about that. Oh yeah, we’re just dropping it off from that point. And the dinosaur has found us, so we basically lost the game.
So let’s see. The camera has, oh, this needs to be triggered, so that’s my bad, so I’m going to also increase the radius a little bit. Now that it’s triggered it should be fine, and, and the dinosaurs themselves, they should have a little bit more resistance than that, so the maximum magnitude, I’m going to increase that to three. Okay, well let’s implement then, the throwing part.
So I’m going to add another script here, which I am going to call Throwable Controller, or just Throwable. And this is going to be a behavior, sort of like Draggable, and it will make use of Draggable, basically, it will basically require us to have Draggable in place, and I’m going to also place it on the Zenva VR namespace, just because I’ll make it in a way that can be reused in other games, so it’s the sort of script that I would like to take with me and use it in other things as well. So are we going to include the, I’m not sure if we are gonna need this, so I’m not going to include that. But we do need to have the component Draggable. So in order for us to be able to throw something, we need to be able to first collect it, to drag it. So we need the Draggable.
Now I’m not getting auto completion to work, which is usually the case when a new file for some reason is not added here. I’m going to see if pressing Refresh works. Sometimes files don’t get added, so I go to here, Scripts, Add Existing Item, and I make sure to find my newly created script here, and after that it’s all fine, so now I should be able to type RequireComponent, and this is off of typeof(Draggable), and now we know that we have that Draggable component whenever we are doing a Throwable component. S
o I want to get that and place it in a variable. So this will be a Draggable draggable, and on script initialization, so I’m going to use Awake here. Woops, I’m going to get a hold of this component, which I know, it is guaranteed to exist, because I’m using RequireComponent, so this will be Draggable, and what I’m interested in is the action of throwing, of dropping.
So if I go to Draggable, we have an event here that is OnDrop, and when you call OnDrop, you are throwing the item, so whenever I enable or disable this script here, I should either listen or remove the listening of that event. So I’m going to have OnEnable and OnDisable, and I like to remove private as just my own personal coding preference, coding style.
So in here we need to get access to Draggable and OnDrop, we need to add a method here, which will be, we’re going to call ThrowItem, because Throw itself is kind of a reserved word in programming, in C Sharp, because it’s what you use to throw exceptions. Now this complains that it doesn’t exist, because it doesn’t exist, so we’re going to generate it, and now we can, we can throw the item, and how can we do that?
Well first I’m going to write it in pseudo code, so the direction should be calculated, then once we have the direction, we should get the rigid body of the item that we want to throw, which is the current item, the current game object, and give it a velocity, or an impulse, give it an impulse. So what about the, let’s start with the direction part. The direction will be the forward direction of the camera. So let’s create a Vector3 here, and let’s call this dir, and this will be Camera.main.transform.forward. I’m just putting it in a variable, just to make it very explicit.
Then we need to get the rigid body of the item and give it an impulse then. Well let’s create it as a variable, rb, and the rigid body of the item is our current rigid body, so GetComponent, and we should assume that there is a rigid body, so I’m going to add that as well here. Assuming that we have a rigid body. So we have a rigid body. I’m also going to make sure it’s not kinematic, so that it responds to forces, so rb.isKinematic equals false, and now I’m going to give it an impulse. Rigid body.AddForce, then the force will be a, I’ll make it a velocity change type of force, it will speed times direction, and Force Mode will be VelocityChange.
Now the speed needs to be a public variable here. Let’s call this throwing speed, public float speed, I’m going to set a value of 10 by default, or maybe like five, we can adjust it later, and that should give us a basic throwing ability. So in Unity here we’re going to select our prefabs, all of them, with the exception of the dinosaur prefab, and we are going to give this the Throwable script. I’m going to give them all the Throwable script. And I’m going to press play and see what happens now.
So I can move around, and I can grab blocks, and if I press the right click, they get thrown away, but they don’t get really far, and the physics simulation seems like a little bit too abrupt. When you are using the Drag Script camera, it might happen that you grab it, and then it’s like you can’t get rid of it, and then you just press the right button and move and it will be, it will show.
But, so there are a few things here, like first that it falls too quickly with gravity. So, what I’m going to do is disable gravity for when you are throwing something, so that it just goes straight ahead like a bullet, and when it comes to the physics simulation if you want a smoother physics simulation, I’m going to show you what to do as well. You can change the time, of the time step. Although that will have an impact on CPU usage. So let’s start with the first thing, which was to disable the gravity. So in my code here, I’m also going to disable gravity. Rb.useGravity will now be false.
So now things will get thrown straightaway. So if I try, if I try to play this again, you can now, hmm, they should be thrown, thrown straight ahead, I’m not sure why that is happening. Oh yeah, they are kind of just flowing into space, so that is pretty odd, let’s try again. It seems like, they still fall like that, woops, I killed it there. So what I’m going to do is, I’m going to disable the gravity when you collect them, just so that I make sure that this doesn’t, that this will already be active when I throw them. So whenever I collect something, I’m going to use a similar approach to this.
So we already have an event here, this is OnDrag, so I’m going to use the OnDrag event, and this will be, or HandleDragging, and let’s call this DragItem just to keep consistent with the name of the other method, and we’re also going to add that for when we disable our item, so we’re going to make sure to remove that, that event listener. So I’m going to go here, void DragItem, and I’m going to get the rigid body of my item, and I’m going to disable gravity here. And, I’m also going to make it kinematic when we collect it. So that we make sure that this is kinematic when we are dragging it around, which might not have been done, it is not done here, because it doesn’t assume that there is a rigid body, whereas here we do know that there is one.
Now we are getting the rigid body in two different parts, so we should probably move this code somewhere else. We’re going to move this code here to Awake, and let’s call this get draggable component, and the definition of this rigid body variable will be added here as a private variable. And don’t forget the semicolon, and now that we’ve got that, we can just refer to our, we don’t need to do grab it anymore, we just know that it is there for us, and going to get rid of this error console message as well.
So let’s try this one more time, and see what we get now. So I’m going to go here, press play, and, grab any of these elements, and see if I can throw that. So that is much better. That is much better. It could be thrown even faster than that, for sure, and well, we are seeing the fact that it doesn’t have a gravity, it’s making them bounce, which is kind of funny. So what we could do is re-enable gravity as soon as there is a collision. So let’s do that, let’s fix that.
So whenever we have a collision here, OnCollisionEnter, we are going to re-enable gravity. So that we don’t get that blocks floating into space. So let’s press play and try this one more time. So grab something, throw it at the dinosaur, and, that’s good, that works much better. So now if we throw it to another building, for example, it’s just dropping it in there.
Okay, so now what I mentioned before, if you want a more smooth, a smoother physics simulation, just go to Project Settings and Time, and you can change the fixed time step of your physics simulation to a smaller number. So for example in the HTC5, normally this is reduced to one one one one, which is 90 times per second. Basically this is the time per physics time step, which is 0.02. By default, in Unity. The lower the number, the more precise the simulation, but also the higher the CPU usage. 0.02 will take place 50 times per second, so you can calculate that by dividing one second divided by this amount, gives us that there are 50 of these time steps in a second.
Performance wise, this game is quite intensive in physics, so it might be suitable just for higher end phones. Things you can do to reduce that, would be to have less buildings, and also that the buildings that are far away, they could just be full buildings, they will not be blocks, little blocks, so you can’t really destroy them, and then you could, you could, well, the same with trees that are far away, they could just be fixed and static as well, so all these trees, and the things that are far away would be statics. Or they could, the buildings that are far, if they are very far away, they could even be just billboards, like actual 2D elements, like canvases, for example. You could even use like a sky box, but that would need to be quite far away.
Also, obviously to, as we, well we’ve covered in other courses, make sure to reduce realtime global illumination, because that is a very expensive operation, that is when light bounces from one object to another object, which is something that in a game like this doesn’t make a difference, but just adds more CPU.
So to finalize this lesson, I’m actually now gonna show you some footage of this game adapted for reticle usage. Alright, when testing this in virtual reality, everything works fine, but I did find a bug that we need to address. Basically when we take something, the, as you can see, the reticle is on the pivot point, and the pivot point on these blocks is at the very bottom, so, the reticle seems to get and lose focus of the blocks, so that looks very confusing when you are moving something around with the headset as you can imagine. It’s as if the reticle targets the block but then also it goes, targets the horizon at the same time.
The solution here will consist on modifying Draggable so that we adjust the position, considering that there might be a difference between the center of the object and the pivot point, so that if the pivot point is in one of the corners, we will be sent a bit more to the middle.
So I’ll calculate a difference here. Difference between the pivot point, and the center of the renderer. This difference will be a Vector3, let’s call this difference, and it will be transform.position, minus the, so that is the position of the pivot point, minus the position of the center of the renderer.
Now, how can we get that? We need to get the renderer first. GetComponent, and then we get bounds, and here’s center. This gives you the position in space of the center of the renderer. Now we don’t want to be calculating the renderer so often, on each frame, basically, so we are going to cut that, and paste it in here, so we’re going to add that here as another component that we need to grab. This will be renderer equals GetComponent, and well, renderer itself will be defined here as a public, private variable. This will be of type Renderer, name renderer, with lower case, so we are declaring it here.
Renderer used to be used in older APIs of Unity, so I’m going to call this rend instead, just so that we don’t run into any sort of issues, so I’m going to call this rend. And, so we get rend, we get the components, and then, in here, we calculate that difference between the pivot point and the center, and then we’re simply going to add that difference in here. So that we account for it. Whenever, when both are the same, this will be zero, and we’re not going to be modifying this at all. So that’s a good thing about using this script in the more projects you use them, your scripts in, the more that you can polish them, and the better they become.
So let’s go to Unity, and try this out, so I’m going to press play there, and I’m going to grab something and, yeah, so now we can grab our blocks from an area that is closer to center. It is not the exact center here, because we are pointing, if you were able to draw a straight line from your camera to all the way here, we are actually pointing at the center of the block itself, not the center of this face, but that’s fine, that does it for us. I just don’t want to be in one of the corners.
So let’s bring this to maximize view, and just play this one last time so that we make sure that it’s all working okay, in the Oculus Rift, and that means that it will work also on other devices, so that is really cool, I can shoot these things, and, I can defeat all the dinosaurs, and we get all this kind of physics as well. So that’s great, there’s another one there, we shoot as well.
Alright, so that’s all for this lesson, I will see you in the next video.
Interested in continuing? Check out our Virtual Reality Mini-Degree for the latest VR courses.