In this workshop, we’ll build a complete game using the PlayCanvas engine while learning the best practices for project management. From development to publishing, we’ll cover the most crucial features such as asset management, scripting, audio, debugging, and much more.
PlayCanvas End-to-End : the quick version
AI Generated Video Summary
This Workshop covers the basics of Play Canvas and guides you through building a game in three phases: scene setup, interactivity, and polishing. Play Canvas is a web-first game engine that runs on your mobile device or browser, making it fully cross-platform. It provides its own hosting solution for easy sharing of your game. The Workshop covers topics like importing assets, scripting, physics, animation, debugging, user interface, audio, and publishing.
1. Introduction to Play Canvas Workshop
This workshop will cover the basics of Play Canvas and guide you through building a game in three phases: scene setup, interactivity, and polishing. You'll learn about importing assets, scripting, physics, animation, debugging, user interface, audio, and publishing. Play Canvas provides its own hosting solution for easy sharing of your game.
Hi, everyone. My name is João and this is the workshop for Play Canvas End to End, the quick version. So Play Canvas End to End, the quick version. Quick, not so quick, because it will be around 2 hours of workshop. But yeah, we'll still be able to build a full game in this 2 hours.
So the way that we will structure this workshop is, so just to do some brief introductions, but then I'll talk about Play Canvas. So I'll just talk about, you know, the basic features that we have, you know, like the everything you can do in Play Canvas. And we'll go into the actual core of the workshop where we'll build a game together.
So I split that into 3 different phases. Phase number 1 is like just a general scene set up, so we'll start just importing some assets, placing some stuff around, some obstacles, some ground. We'll talk about that in a second. And we'll talk about launching and like testing your game out. Phase 2 will be about interactivity. So we'll go over scripting, question scripts, we'll go about the event system that we have in Play Canvas, also about how to do physics with rigid bodies. We'll talk about the animation system as well. And then some debugging capabilities using Chrome. And then phase 3 will be about polishing and publishing. So we'll create just some final touches on user interface, how to do audio, and then we'll be able to publish that to the world. We'll be able to do that using Play Canvas' own hosting solution, so you don't need to have anything on your own, you just press a button and you'll have a firmware link to your build of the game, and then you can share it with anyone that you want. And then we'll do some wrap-ups towards the end.
2. Play Canvas Project Phases
We'll be using a Play Canvas source project that already contains all the assets and boilerplate code. You can fork the project at any phase if you get lost and start from there. The final project with full documentation will also be available for reference. You can choose to listen and learn or build along with me.
Now, the way that we'll be doing the different phases there in the actual game is that we'll – I prepared a Play Canvas, like a source project that already contains all the assets and the boilerplate stuff that we'll need, and what you guys will be able to do is actually is you take that and make a fork out of it, so you'll be able to copy that as your own project and then make whatever you want with it. I'll be doing the same thing, so I'll be starting from the same like, starter project, and then together we'll build up to the final game. Now each of the phases, we also have a project for those, so let's say that you're in the middle of phase one and you kinda get lost. It's okay, just wait for phase two, and then you can clone, you can fork a project starting at phase two, and then same thing for phase three. If you get lost in the middle of the scripting stuff on phase two, just wait and I'll send the link for phase three, and then you can fork phase three and restart from there, so you have these three kind of like, checkpoints that we can go along the way, and also the final project, like the end thing, with full documentation, with all the features, will also be available for you guys to take a look at, so see the entire thing done as well. So you can also just sit back, take a coffee, tea, water, whatever you fancy, and just listen out how to build the full thing, or you can build out, like together with me as you go through it.
3. Introduction to João and Play Canvas
Hi, I'm João, a software engineer at Play Canvas. Games have been my passion, and I have launched indie games like Step and Menard. Find me on Twitter and GitHub for more.
So first, let's briefly talk about who I am. So, hi, my name is João, I currently work at the Play Canvas team as a software engineer, you can also find me on Play Canvas official forums as JPaulo, and again, as I said, currently I I work as a software engineer at Play Canvas before, I was working at Amazon Alexa and before that I was working at SAP. So I do have kind of like a back end, you know, like a not game-related until I moved to Play Canvas, but games have been my passion since like the beginning. I think there's a story that many people share I guess in the gaming space. So, games is the thing that made me really like want to go as a career as a software I do have a few indie games launched. So, I have step and Menard, which did, you know, have a little bit more of success. So Menard did reach, I think was top 10 puzzle games in a few countries on iOS when it was released. So that was pretty exciting. And Step was a game that was picked as a for the Google indie games showcase a few years ago. So there was a whole event about it as well, which was pretty cool. You can find me on Twitter as the John Paul and also on GitHub. I'll talk a bit more about why GitHub is important for us at PlayCanvas. But yeah, feel free to follow, I follow back. You know, like all that nice policy for follow, follow back. So yeah, cool.
4. Introduction to PlayCanvas
PlayCanvas is a web-first game engine that runs on your mobile device or browser, making it fully cross-platform. The PlayCanvas engine contains all the core functionality for a PlayCanvas game or application, including vectors, math, loading meshes and textures, and GPU shaders. It is open source and available on GitHub. The PlayCanvas editor is collaborative by design, with a powerful backend that handles asset processing and compression. It supports code editing with built-in intellisense and has zero build-time. It also includes WebXR support, a Git-like version control system, and advanced graphic features. The PlayCanvas editor has a small file size and supports user interface, audio, animation, physics, and more.
So let's talk about a bit of a PlayCanvas. So PlayCanvas is a web first game engine. So as you can see from the editor there, we have on the right is very similar to a few other game engines that we have in the market. But again, the cool thing about that is that it's running 100% on your mobile device, on your browser, right? Which does mean that you can like, you can use it on a mobile device as well. But you can it's fully cross platform out of the box. So you can use it on. You can use it on on Windows, Mac, Linux, anything that you can run a browser on. You can run PlayCanvas. Maybe it even works on Raspberry Pi. I don't know if it has WebGL. Anyway.
The PlayCanvas is really spilt into two main things. So first is what we call the PlayCanvas engine. So the PlayCanvas engine is what contains all the core functionality for a PlayCanvas game to function, or application to function. So it has stuff like vectors and math and quaternions, mathematics, and like loading meshes and textures and loading that GPU shaders. So all that stuff is on the PlayCanvas engine, which is fully open source and is on GitHub. That's why GitHub is important to us. So you can you can help over there right now GitHub.com slash PlayCanvas slash engine. And you can you can make contributions yourself, you can check out what we've been doing and you can also use it like to to to learn a little bit more about how to make like game engine architecture. You know, how do we do that. The final build of the PlayCanvas engine is only 335 kilobytes zipped. So that means that when you make a PlayCanvas game and then you ship, for people to download or and to play, the PlayCanvas footprint is only 335 kilobytes. Again, that's zipped. Once you unzip it, it's a little bit more, and that's a little bit over a megabyte, still pretty small. So our footprint is very small. It is available as a standalone so you can the PlayCanvas engine without the PlayCanvas editor, which we'll talk about in a second. And so the PlayCanvas engine is on npm so you can use it from there. You can also just download the minified version and use for that.js, a single file, just import it. And go ahead. Or you can build from source. You can download the open source right there, npm install, npm run build, there you go. You have it there, you can use it from there.
The Play Canvas editor itself, very similar, again, to many other game engines that currently are out there. So we have the hierarchy list on the left. We have a toolbar also there on the left where you can just select what tool you want to use. You have the project assets there in the front bottom, where you have all the assets that were inserted, that were imported into that project. You have the inspector there on the right where you can inspect your selected entity. So, for instance, in this case, I'm selecting the light entity. So you have the basic information such as the name. Is it enabled? You can add some text. Then you have the transform of position, rotation, and scale. And then you also have the components, which I'll talk about later about them. But basically you define the behavior. So in this case, I added a light component and then you can select what type of light is it. Color intensity. Does it do shadows? Is it not do shadows? Like how often to update the shadow map.
5. Useful Links and Game Introduction
In this part, we'll explore some useful links for PlayCanvas, including the PlayCanvas GitHub repository, examples browser, API reference, and tutorials. We'll also introduce the game we'll be building, which involves a character navigating obstacles, eating food, and managing time. The game includes physics, dynamic food items, animations, and a simple UI. To get started, make sure you have a PlayCanvas account and fork the food run starter kit. Then, open the editor and navigate to the game scene.
All these things you can select there on the inspector. Some useful links. Just, you know, general PlayCam useful links. So I have this awesome PlayCanvas GitHub as well, which is a curated list of like some cool stuff that you can do with PlayCanvas. Some of them have sources as well. So you can check out like how those things were made. We have an examples browser where you can check out again like how to use the engine and all sorts of crazy stuff. And you have the API reference and tutorials. You have the froms and have a Twitter as well. So Twitter is pretty cool as well. We do like to retweet and help out the community as well. So, you know, just give us a shout out. If you have a cool project, I'll be sure to retweet and spread the word about your project. Cool, right. OK, with all that boring stuff out of the way, let's actually go ahead and build something.
So the the game that we'll be building is this one. I'll open up here just so you can see what it what it is. So this is what I was talking before about your own about having a build hosted by PlayCanvas. So this is a PlayCanvas.as website. And from here you can you can host any village. This is the game that we'll be building. It's a pretty simple one. So you have your character moving around, you have some obstacles that you cannot really cross, and then you need to eat some food. And then as you're eating foods, the time increases and have a certain time to, well, eat all the foods. And one of the game, very silly game, is just to eat as much as you want. And if the time runs out, let's let's leave the time to run out a bit. The time runs out, time's up, nice. There's some audio effects there as well. Just says time's up. And then you press the button to go again, resets the score and then you start over again. Pretty simple stuff. But, you know, we'll be touching a lot of different things here. Let me go back to the slides. Cool. So, so again, this is just a screen of what we'll be building. So if you break down what this game actually is about. So we have a ground entity there which has some physics. We have some obstacles which need to somehow block the player from going. So we need, again, some physics collisions on that. We also have some food items that keep popping up. And as you can see there, the food is not always the same. So we have cakes and apples and bananas and stuff like that. So, and it's dynamically placed. And also have the player which is, of course, dynamic as well and has some animation on it. We also have a very simple UI there on the top left, which contains, just has the time remaining and a count of the score. Cool. Now let's get going then. So we'll start at phase one. So hopefully by now, most people have the PlayCanvas account. And then if you don't, just go head to playcanvas.com and create your new account. Should be pretty straightforward. Very easy, very fast. And then we'll start with the food run starter kit. So I'll send this link on Discord, and I'll also send this link here on the chat. Which is this one right here. So just open that up. It's public, so everyone should be able to see that. And from here, let me close chat, right. So from here, we can go ahead and fork it. So to fork a project, simply go here and click on the fork button. So the owner should be, like, this should be your name, should be your account there. And you can call it whatever you want. So I'll call it food run my own food run. Just click on fork, just wait a while for the backup systems to duplicate the project. So duplicate everything, scenes, assets, scripts, everything. And it will create your own copy of the project. So here we have. So now I have my own food run that you can do whatever you want with it. So like, every one of you have your own. If you're having any issues at all with it so far, just just send a message on chat or on Discord. I'm seeing those. There's nothing. I'll assume everyone's kind of following along. I won't be too fast on it. I'll give you guys some time. But once you have the fork done, you have your account, and you have your fork done, just click here on the editor. So it's just checking if there's anything. So I'll close my other tabs here. It doesn't get in the way. Just check if there's anything, nothing on Discord. Nothing on chat so far. Cool. Right. So once you-. So this is the first thing that you see when you open the Uplay Canvas editor. So you're greeted here with the list of scenes. So by default, when you create a new project you'll have a blank scene. In this case, we already have a game scene here. So we're going to go ahead and open up. And now we're good to go.
6. Creating the Ground Plane and Applying a Material
We'll start by creating the ground plane. We'll make it 25 by 25 and apply a texture to it. We have predefined primitives to use, and we'll choose the plane. We'll also create a material for the plane and apply a grid pattern texture to it. The material is not yet being used on the mesh.
So as I said before, so here on the left we have the hierarchy, we have a toolbar here, here we have all the assets. On the right we have the inspector. Here we have the viewport, that is what we currently have, which again is nothing. We have actually-. No, we have a camera and we have a light source. Right? Now again, so this is like the starter project for the FoodRun game, which means that already added here on FoodRun, already added all the assets that we'll be needing for the project. So for instance, if you open Arena and you open textures, you already have some nice textures here, some prototype textures. Now all of the assets that we're using here are from the amazing Kenny, of course. I think most people here might know who he is. I think that's an amazing creator doing some fantastic stuff. And it's all CC0, of course, but all the licensing and source information are there, so just to link back to their amazing work. So we have the Arena with some textures. We already have some sound files as well that we can link later. We already have the model as well, which contains, which has the fbx file here. We have some animation clips as well. So everything is here that we'll need. And you know, as we go through the workshop, we'll go through all of those together. But moving on, we also have the script, a folder called Script Templates here. So of course, like building the entire code for that thing in two hours together while we're sharing screen might not be ideal. So already, have the boring code is mostly done, you know, like hooking up game managers and like coding the simple game logic is mostly already there. But we'll need to do some stuff throughout the workshop to fix it up. We'll do that together. But again, don't worry about those for now. I'll tell you when you need to use those. For now, just leave them there on Script Templates. Also, I do have some notes here just so I don't lose myself. So if you see me like looking down, writing down, I'm just making sure that I don't lose anything. So yeah, cool. With that, I think we can get started. Hopefully most of you have created your own fork and already have it. Let me check the chat. Okay. Can I get at least one yes I'm able to do it? Just so I can go ahead. I want to be sure that... Awesome, thanks. Awesome. Thanks, Mike. Thanks, Rick. Oh, awesome. Thank you. Ah, amazing. Great response. Thank you, guys. Cool. So let's start then. Let me just grab my mouse here so it might be a little bit easier. Cool. So let's start from the biggest thing. There's one more chat. Sorry. I'm just watching. That's totally okay, right? Yeah, totally fine. Glad you're with us. Cool. So let's start creating just the ground plane. Right. So let's start creating a new entity here. Son of root. We call that arena. So we have the arena here and let's create the ground plane. So if you go here for a new entity, we have a lot of like predefined stuff and one of them is primitives. So we have stuff like boxes and capsules, cones, et cetera. We will want a plane, which is again, just two triangles, just a simple thing for us to define a plane. And let's make it big to cover a lot of things. We'll make it actually 25 by 25, 25 by one by 25. So plane canvas Y is up. So we have a big plane here. And let's create a material for that as well, so let's apply a Texture to it. So if you go on Food Run here on arena, we already have some nice textures here, so let's create a new material there. Let's actually do some nice project management. So we'll not create it here, on arena, let's create a new folder. Let's call that one Materials. Let's create a new material here. So then on the Assets panel right here, let's create a new asset. Let's call it- Let's create a new material. Let's call it Ground Material. And this is, as I mentioned before, plane canvas supports full PBR. So physically-based rendering materials. So we have stuff like ambient, diffuse, specular, you even have clear coat, which is useful for like cars and stuff, pretty cool. We have emission, opacity, blah, blah, blah. This one is pretty simple. We just want like a nice- Let's actually refer back to our image here. Might be useful. So we just want like this nice grid pattern right here. So just like apply a diffuse here. So if you open up the diffuse drawer here, we can apply any texture here. We can also apply some tinting, some color. So let's then open the- Click on the textures folder here and let's use sector 8. I think it's a nice one here. Because I did it before, right? So when we applied here- Oh well, of course we applied to the material but the material is not being used on the mesh yet.
7. Customizing the Plane and Creating a Player
To customize the appearance of the plane, we can add tiling and change its color. By dividing the size of the plane by two, we can achieve seamless tiling. To add color, we can adjust the tint property in the material. A greenish tint, represented by the hex code 59D1DD, gives the plane a grass-like appearance. However, other colors or textures can be used. Now, let's create a player.
Let's jump back to the plane and let's be sure to use the ground material on that plane. So we can either drag and drop here on the world so this works or here on the material slot on the inspector. So let's draw here, let's drop here because this is a pretty cool feature. Right, but this is looking very big, you know it's stretching across the entire thing. So let's add some tiling here. So a good number that will work here since this is two by two is if we take then the 25 and then divide by two. So if you take 25 and then divide by two which works by the way here, this will tile seamlessly here then and this will also line up perfectly with our grid. So each tile here is exactly one unit, one meter, whatever you want, one unit across, which is pretty cool. So now we have our thing here but it's looking very white, right? This is looking too bland. So let's give it some color. So again, if you go back to the material and then diffuse, we can click on tint and then we can add any color that you want. So we'll be able to change to any color that you want. We'll just multiply the colors together. So a good number that we have there is that nice greenish tint, which makes it look like kind of a grass. So the number for that is 59D1DD, have it written down. So this is the same color that we have there on the example, right, that we have here. So again, if you want to use the same number is 59D1DD, so that's the hex code for this nice green tint, but you can put whatever you want. You can also use another texture if you want. Not even use a texture, but cool. We have our plane here. Let's go ahead and create a player.
8. Creating Player and Obstacle Entities
To create a player, we'll create a new entity and add a mesh to it. We'll also create a material and assign it to the mesh. The material is a PBR and can be customized with different settings. We'll create a template for the player entity, which will be useful for placing it in multiple locations. We'll follow a similar process to create an obstacle entity, using a box shape as the simplest obstacle.
So to create a player, let's create a new entity then. Not on the arena, because the arena will be putting the static stuff. Let's create a new entity, son of root. Let's call it player. So the player entity currently doesn't have anything. Let's put that mesh that we have. So here again on foot run, character, medium FBX. So this is what happens if you take any FBX file and you simply drag it into to play canvas, I didn't touch this at all. This is the raw files downloaded from Kenny website. This is what we'll create for you. So it will upload the raw FBX file and to convert that to all the files that internally play canvas needs. Now there are two more important ones here. One of them is the like the material that it uses. So this is just like important raw material which is doesn't have that texture on it. But well, it's the material of the settings that it had. And this one with the, this prism diagonal. I forgot now the name for this symbol right here. But it's okay. Square. Rotated square. And this is important because this is the template. Now we'll talk a little bit more templates in a second, but this is the asset that contains the model and the material. Everything kind of bundled together will be on this one. So this is the one that we'll be wanting to use whenever we're importing models in. We'll use this one. So then what we can use is you can take this one and we can just drag it into the scene. So we can drag it here, but I actually want to be a child of player. So I can just drag it in here. So I'll be dragging to the player entity there. Now we have the model there. Now, of course, it's still... By the way, if the camera is kind of all wrong, you can press F. You cannot really see that, but I just press F and you zero in on whatever you're selecting. So if you're selecting the arena and you press F, you go to the entire thing. If you press the... If you use another character, zoom in there, very useful feature. So now we have the R asset there, but of course it does have the material yet. So let's create a new material as well. Again, let's do some nice project management. Let's create a new folder, not to create it anywhere. Let's call it materials. Let's create a new material there. Let's call it PlayerMaterials. Of course, we could just take the material that was already imported, this one, and just edit this one. But I think for our use case, we'll be creating our own so that we can tweak some more things. So then let's assign this material to the mesh there so we just drag and drop. Doesn't look too different, but that's okay. So let's select the material. Let's go under Fuse and then let's select one of the textures. So on this particular Kine Asset pack there, it comes with four different textures and all of them already have the correct UV mapping for this particular model. So we can use whatever one we want. So I'll be using Zombie Sea but I think it looks pretty cool actually. So I have this nice zombie here already applied there. And as I said, the material is a PBR, so it's physically based rendered, which means that we can change a lot of different settings for whatever look that we want to have. So if you open the Specular Drawer here, we can do some more things as well. So we can have different specular tinting if you want that gives some nice, interesting effects. But what I want to touch on is actually the glossiness. Because if you go ahead final, the last parameter here, glossiness, and we put it like all the way over there, kind of looks like a plasticy thing, like this looks like a plastic doll, which could be something that you're going for, you know, it gives a nice specular highlight there for the light, right? So this is the light being reflected. But I think for this one, I don't really want that effect. I want something more diffused as if, you know, like as if it was a person or like a character or like some plastic that you're moving around the board. So if I bring the glossiness down all the way to zero, it kind of does this like more diffuse effect, which again, it's something that you want. You go ahead and do whatever you want. If you want like that plastic look, might even look cool, anyway. So right, we have that done. So let's create a template for this. So it's very useful as you're developing things. If you're like going to place them in multiple different places to create templates for it, which in another game engine, it's also called the prefab, which is something you can just like drag and drop and already contains all the material mappings already contains like all the hierarchy that you set up. So let's create a template for the player, which currently doesn't have much. We only have like a player entity with the model here, but we'll do some more stuff later, right? So on the character folder, let's create a new folder here. Let's call it templates. Again, we want to have a nice project management here. And the way that you create templates in Play Canvas is the following, you select the entity that you want to have to create a template from. So in this case, player, so the player entity, right-click, template, new template. This will create a new template in whatever folder you're currently on the asset, on the asset panel here on the bottom. So just create a new player template on my templates folder in the characters sub-folder. So again, so it's on foot run, character templates, have the player template right there. So if we delete this, oh no, you just drop it back in and have the full thing exactly how we had, had this setup before. Cool. Now let's, let's go back to, to the, to what we're building, right? So we have the, the, the, the player there. We have the ground. Let's create some obstacles. Now to create obstacle. Again, it will be similar to, to what we just did because we'll also be creating a template out of that. So let's create a new entity. Let's call it obstacle or whatever you want to call it. And then from that, let's create, let's create a box shape. That's the simplest obstacle that we have, right. So right here is just like some box shapes. Let's just create a box out of it. So on obstacle, let's create a new primitive box.
9. Creating Obstacles and Food
In this part, we create a box obstacle and customize its appearance. We also create a new material for the box and give it an orange color. The box is then added as a child of the Arena entity and a template is created. We also place some obstacles around relatively randomly. Next, we create a food entity that can be picked up to increase time. The food entity is placed in the scene and a model is added to it.
Try that box. Let's move it a bit forward here so that it doesn't get in the way. It's easier to see. You can also see like the shadow map. They are being updated. Pretty cool. Let's raise it up a bit. So that's above the ground. So the value that you want is 0.5. So by default, the primitives are one by one by one. So if it's 0.5, we get it halfway there. Let's make it a bit bigger. Let's scale up two on X and two on Z. Just it's slightly bigger there but not too big as well. Not going above because we want to see what's behind the obstacles. It's just really something that they won't be able to go across.
Now let's also create a new material for this because right now, this is using like the default material, which is just pretty bland. Let's go on Arena, Materials. So the same photo that we have the ground material, let's create a new material for that. So let's call it the Box Orange or something. It'll be orange, spoiler alert. Let's drag that in. It doesn't change much because it's the same color. But now the box is using our custom material. Let's go ahead then and we won't be using a texture for it but we can just give it a color. So whatever color you want. So here I wanted to have the nice orange thing. I think it works very well with this greenish blueish background here. So the nice color for that is FBB057 to give this nice orange tint. But again, you can use whatever color you want. This is just color that I used FBB057. And you have it there. Let's create a template out of that. So in Arena... Yeah, because this will be part of the Arena, right? Yeah, this makes sense to be part of the Arena. Let's place the obstacle as child of Arena as well. So our Arena now has like the ground plane and also has an obstacle. Let's create a template out of it. So let's create a new folder. Let's call it Templates. And an obstacle, let's create our template out of that. So now you know the drill. You're pros at this already. So just right-click on the entity, Template, New Template, on the folder that you want. Like if you create on the wrong folder, just like move about... like we'll do the heavy lifting. I'll like, the referencing will be correct, then you need to worry about that. But yeah, so if you create it on the wrong place, just move it to the correct folder. So we have here on Arena, then templates we have on the obstacle. Cool. And by the way, when you do that, this one is already linked to this. So if we move this, if we change this template, like it will be applied. So we don't need to worry about that. What we'll do, let's also take this opportunity to put some obstacles around. So of course here, I made this pattern of... whatever. It's kind of nice, there's a symmetry to it. But you can do whatever you want. So in this case, I'll just like be placing those around relatively randomly. So I'll put this here. And then. So you can right-click and say duplicate, or you can do Cmd D, or I think in Windows is Ctrl D, to just duplicate. And then you can move about however you want. So let's just put some around. And I think this is a place where you can let your game design passion shine. So we can build some corridors if you want. You know, you can build some nice structures of different areas that you want. In my case, it's pretty boring just having some around. I'll put one more there. Yeah, okay. Cool, there we go. So just some scattered. Be interesting to see what you guys come up with. So again, like once this is done make sure to take a screenshot, post on a Twitter, and take a look what you guys come up with here. Cool, so now we have our obstacles. What else can we do now? Let's create the food, right? So we have the food entities there, which we can pick up to increase time. That's very important as well. So let's create one of that. So again, on root, let's create a new entity. Let's call it Food. You can call it Food or Collectible or whatever you want. So it's right now placed right there. Let's move the player back a bit because it's on the center. It's moving back a bit there. That's fine, just whatever you want. Just so it's not just out of the way. And then let's put in a model. So on your Food run asset folder here, you have the Collectibles folder. And within here, we have the models. And again, this is the raw FBX imports.
10. Creating Templates and Adjusting Lighting
To create a template for the apple, we scale it up and create a new template out of it. We can create templates for other models as well. To improve the look of the scene, we can adjust the ambient light or use cubemaps for environment mapping. By creating a new cubemap asset and defining six images, we can give lighting and an environment to our scene.
If you just download Kenny, take the FBX file, drag it in. This is exactly what you have. It create a folder for you, which contains all the assets that you need. It have the mesh information here. All the different materials that you need as well with already all the tinted information. Again, I changed nothing out of this. This is plain import. And you'll have the diamond. I think that's a good name. You have the diamond shape right here, which again is our template. And this is what we want. This is what we want to use right here. So let's take... Shall we take apple, banana, or cake? Let's take apple. It's a more healthier option. So let's take this one. Let's drag it in as a child of food. And it will be there. It's looking kind of small. And we want to be able to see it later. So let's select the model entity here. Let's scale it up. So on the toolbar here on the left, you can select the scale. And then if you click on the... If you click either of this, you can scale up in any of the axes. But if you click on the middle there, you can scale all of them up together in a different fashion. I think this is kind of what we want. We want to make kind of big. Yeah. I think that this is a big apple. Cool. Now, since we have that, we're good to go. Let's create a template out of that. Let's go on collectibles. Let's create a new folder. Again, you know the drill. You're pros, project management, blah, blah, blah. Templates. Then on food. On the food entity, let's create a new template out of it. Cool. Again, in this phase we're doing project setup. We're creating all the different little aspects that you need for the game. In a real world scenario, you would have something like an image from a designer or something that explains the game play. It would be like breaking down all of that. That's kind of what we're doing. We're breaking down the core game play, creating templates for it. Then we'll go from there on phase two. We have now our food. Now, again, I did add some other models here. So you can go ahead and create some new templates. I won't go through all of those, but it'll be a pretty similar process. Just create a new entity, add your model. Again, the diamond shape one. Increase the size a bit so it kind of makes sense. And create a new template out of that and just place it on the templates folder here. Again, I'll just use the Apple for now. Cool. Now, if we compare this with this, it's looking a little bit different. So these shadows right here... So we have the shadows, but they're not really that strong as we have here. These are pretty like strong shadows, looking kind of gray. Also, our background is this monocolor. Yeah, that's not really something that we want. We want to kind of improve the look of that. So you have this nice like greenish thing, which kind of looks nice. So the way that we can do that in Play Canvas is... So we support two different kinds of environment light. This is what we're missing, environment lights. So if we open here on the toolbar, the last option there, settings, the little cog, you can open... So we have a lot of interesting settings here, like some editor settings, stuff like grid divisions, camera, near and far for the editor, locale stuff, you can select the engine. So a lot of cool stuff that you can do here. But what I want to touch on, is the rendering drawer. So the rendering, you can select your ambient color, you can select like tone mapping, you can select gamma, you can, we have fogs as well, so like linear exponential, you can set like a target resolution that like all your things will be kind of based around. So a lot of interesting things here, very technical. But the thing that we're worried about here is the ambient light, it's environment light, this is what we want. So if we just, the simplest one would be just changing the ambient light, right? Because if you just like bring that up, okay, that's already looking kind of better, because now the shadows are not that strong. You know, if you put it all the way down, we either have the main light or we have nothing. So if we bring that up, we have like this kind of stuff, right? But I think you can do better. So we do support cubemaps for environment mapping, so this is what we're talking about environment mapping. And you already have that right here. So if you open on food run environment, we have... This six faced... Might have seen this kind of images before. So we have six images which define a cube which we can use that to give lighting and to give like an environment to our scene. So we can very easily do that by the following. So on environment, let's create a new asset. Let's call it a cubemap, so new asset, cubemap. Let's call it environments. And then here you can see that there are the slots for six images, which again will define that cube.
11. Phase One Wrap-up and Phase Two Introduction
We learned how to create and manage assets, use templates, and utilize the launch tab for testing. The launch tab allows us to see the game from the camera's perspective and make real-time changes. The Editor Link feature connects all tabs with the launch.playcanvas.com link, enabling collaboration and testing across devices. We also discussed the phase one wrap-up and provided a project link for phase two, where we will explore physics, scripting, and animation.
Right? So if you take a look at each of these images, their names are already like pretty self-explanatory on what they want. So this for instance is the back one. This is the bottom. This is front and et cetera, which exactly those names right here. So we have a bottom, we have a back we have front blah, blah. So if we take any of these, for instance, the first one is the back one. If we take this one and just drag it to the back it will automatically see, Oh, you have more images here. All of those have the same names. So I'll just apply all of those here. Now we have like the, our cube map already set up there. And once we do that, we do want to click this button right here. This magic button. You may need to scroll down a bit. Pre-filter cube map. So what this will do is. Basically, create different MIP maps for those textures so that we can properly use. So Play Canvas properly uses it on environment mapping. So just click the button. And then if any of these textures changes it will need to delete. And then re generate that will no changes. So this is fine. Now, if you go back to the settings here on the little cog on the left we can just use this environment cube map as the skybox. So we just pick that, drag that in the skybox. And then, ooh, okay, here we go. So now we have something there. So now we have that nice... It's using the environment to calculate the ambient light so it's not like a fixed color. And we already have this nice background here. Also, here on the settings you can change the MIP level. MIP level is basically the amount of details that will be there. So if you use MIP level 1, we'll be using the raw texture. Which, if you try to stretch it out across the entire thing, you'll need a massive texture. And as you can see this is kind of looking not so great if you're using MIP level 1. You only need like 8K textures to make this look great, which you might want. But in our case, our images are pretty small. So let's cheat a little bit and let's use a smaller MIP levels or a higher MIP level for a smaller texture size. So that's three. So then it kind of blurs out and you cannot really see the details. And it looks kind of nice. Cool. So this is the end of phase one, actually. Yeah, so with this, we have already our project kind of set up. Let's go back here to the slides. So what did we learn? We learned how to create and manage assets. We learned about creating and using templates. Oh, we didn't use the launch tab. Let's use the launch tab, actually. So as your building stuff, you will be able to see, like okay, what I'm actually building. So if you go here on your viewport, there's this small launch button here. And if you click that, it will open up a new tab, load up the game. And this is exactly what the camera is seeing. So if you go here and then we select the camera... So this is what the camera is seeing. Right there. So this is what we call the launch tab. And this is like your game running, right? So if you have scripts, once you have scripts, this will be the actual game running. While this is just like the editor, right? Now the cool thing is that if we move some stuff around... So let's say I don't really like this obstacle here. I want to move it around. I want to put it here and I want to put this one here. As you're moving stuff around, your launch tab will automatically change as well. Okay, we couldn't really see that. Let's move the apple, the food. So if the apple actually was right there and you jump back, so it automatically moves. So this is called Editor Link. So every single tab that has this in open with the launch.playcanvas.com, will be connected. And as you can see, this connection is like on the internet itself, which means that if you're building a mobile game and you will open exactly this link on your mobile device and you log in with Play Canvas there, it's super easy. You can check the differences on a mobile device as you're doing the changes on the editor. It's real time. And this is, again, what I was talking about before about collaboration as well. So if you have like some people testing, some people building, like all these people connected together on the same scene and you can all test together. Okay, like, what do you think about this? Okay, what about this? Is this color better? And then everyone kinda sees in real time as you're making changes. So this is the launch tab. Yeah, sorry, I forgot about that. Okay, now we have the phase one wrap up. So we talked about the launch tab and we talked about the editor link, right? Before we move on, so actually as we move on, so to next phase. If there are any questions or anything like that, please do drop them on chat either on zoom here on or on Discord. Otherwise, I think we are good to go. So for phase two, again, as I promised before, we have the project just for that. So I'll be dropping the link for it on, on things here. So you can use this project. You can fork from this project if you got lost in a way and you want to start exactly from this stage, exactly from the stage, just go ahead and fork this project. Let me place it here. Let me also paste on this code. So now, so that's phase two, right? So for me, yeah, I'll just like continue from this and for you guys as well, like you can continue from your current project or if you think it's not looking that great, you can like feel free to fork it as well. Cool, let's go, right? Now for phase two, we'll be introducing other cool stuff. Now we'll be doing physics, we'll be doing scripting, we'll be doing animation. Oh, lots of things go through, paper is big. Cool, so let's start with physics. First thing we'll do about physics is let's start from the same thing that we started on the phase one, which is the ground.
12. Adding Collision and Rigid Body Components
To add collision to the plane, we need to add the collision component and import the physics module called Ammo. After adding the collision, we adjust its size to match the model. We also add a rigid body component to make the collision rigid. The same process is applied to the obstacles. By creating a collision and a rigid body component, we ensure that the obstacles cannot be passed through.
Let's just give, make sure that the plane has a collision on it. Because right now, it only has a render component on it, right? So here, if we select the plane entity, it only has the position, rotation, scale information. It does have a render, it has a render information, but there's no collision on it. So let's add that. Now, the way to do that is we simply need to add components, which will add behaviors to this entity.
The one that we want is collision. So if you just click here on component, you can see like all the components that we support. So you have stuff like audio stuff, which we'll talk to you on later. You can have cameras, elements. So this is for like UI stuff. You have model for rendering. We already have a render component, so we can't add that again. We have scripts, which we'll touch on later. What do you want is collision.
Now if we select our plane again with the collision, now it doesn't have the scary red button anymore because now we already have Ammo there. Just forget about it now. We're done. We're set up. We have Ammo. Now let's just make sure that the physics collision is the same size as the model itself because when we create, we can see here. So this is the preview of the collision. But we needed to go across the entire thing. Let's make it big as well. It uses half extents. So half extents is half of the extent. So if our scale is 25, we just want to be 25 divided by 2. So that would be 12.5. And also the same thing on z. So plan point divided by 5. So you can do it or within this extent, oh sorry, 25. Let's also bring down the Y. Read it down. Y can be like something. Yeah, this should be fine. So that's really small. Yep. So now we have a collision. Now the thing that we also need for a collision is a rigid body. Because if you only add a collision, this will be treated as a trigger, which means that things will, like, go through it. But it'll just, like, it'll just let you know that it went through. But we also want to, we actually want to make it so like, this is a rigid thing that you cannot really go through. So we'll add a new component called rigid body.
Now rigid body needs a collision to work, right? So let's keep it a static. So we'll not be moving the arena about. But let's increase the friction to 0.5. So that the player doesn't just, like, slide about as it walks around. Let's put it at 0.5. Restitution is fine at 0.5, because things are not really, like, bouncing around. But let's increase the friction. If any of these things are like, oh, what is this? What is static on render? What is layers? You can just hover with your mouse, and then it'll give you a nice tool explaining what it is, and a link to the API reference to it with more information. So this is, for instance, the layer documentation for the Render Component. Very easy, just hover with whatever thing you don't really understand. Oh, what is friction? Oh, this is friction. What is restitution? Hover, click on API reference. It'll give you a job of explaining much better than I could. So let's just move forward.
So we have now the collision for the plane. Let's also add collision to the obstacles then, because you cannot really go through them, right? So the obstacle, any of the obstacles that you created, if you did a template, this will work just fine. Let's create a collision there. So same thing, create a collision. Let's make sure that it covers the extent, right? So I think this should be one. Yes, it should be one because I made it with two. Right? Cool. There you go. So now it's covering the entire size of the obstacle there, the entire model. But again, we also want to add the rigid body thing. Right. Make sure that it's actually a rigid thing. Let's just add a rigid body. Let's keep friction and restitution the default values. And again, let's keep it as static because we want to really be moving that. We'll create new types of rigid bodies later. So the player won't be a static rigid body. Moving on. So you can see when you created new stuff, since this is a template, it highlights with this blue tint and gives you here on the top this template instance override information. So this means that this instance of the template has some modifications which the raw template does not have. And then we can either keep it like this, only this one has these changes, or we can apply to all the different templates that we duplicated there. It's very, very cool that you can also press view diff here to see exactly what changed.
13. Adding Collision and Rigidity to Game Entities
We added collision and rigid body components to the obstacles and food entities. The collision component allows us to detect collisions with the player, while the rigid body component ensures that the obstacles cannot be passed through. We also added a collision component to the player entity, using a capsule shape to enable rotation and movement. The player entity also has a rigid body component for interaction with other objects. We applied these changes to the respective templates to ensure consistency. Now, let's move on to scripting by using the player controller script template.
Oh, so now we have collision and rigid body, so there's new components there. Okay, this is exactly what we want. When you press apply all, it applied to the template which will then apply to all the instances of the template, right? So now, if you select any other of the obstacles there, all of them will now have the collision and rigid body which is exactly what we want, so very easy to apply that to all of them.
Cool, now let's add a collision also to our food there because, again, referring back to our gameplay, once you collect the apple or the cake or whatever, something happens, so we need to check when does that happen. So let's add a collision to our apple as well. So, selecting the food entity or whatever you call it, let's also add a collision. So, same thing, add component, collision. Now, for this one, we don't really want the player to bump on the apple or banana on the floor and bounce back. We want to actually pick it up. So it's not a rigid body, it will just have a collision. But with this, we'll be able to add a script which will allow us to know when a player collided with that. So with this, you can select the type of collision that you want. I think for this example, a sphere works very nice. Let's just increase the size of the sphere a little bit. Yeah. So it covers a little bit more than the actual size of the mesh but I think that's fine. But by the way, if you want the collision to be exactly right, you can use mesh here and then you can select the actual Apple mesh to be the collision, right? If you want to be exact. It's a little bit slower but depending on the mesh or depending on your use case, you might want the exact physics collision there. But again, on our use case, I think a sphere is more than fine and you can also check here the kind of preview of where it does. It's like there's a halo around it. I think that's fine. And again, let's be sure to apply that to our template. So apply all. Now we've applied to our food template. And again, if you have more than one food templates, make sure to do that on all templates, otherwise some foods will not be collectible.
Cool! And now, finally, so we have collision everything except on the players. Now let's add collision on the player as well. So now I'm selecting a player entity here on the player template better, which again, is the one that contains the character medium here, which is the model. Let's add collision there. So here, let's add a new component, same thing, again, guys are becoming pros at this. So add a collision. Now it's very common for characters like this to be capsules. And a capsule looks like this. So it's very easy to control this, to be like a character that can rotate around and bump around and multiply, really bump into things as it's rotating. It's a very nice shape to use for that. And what we'll do on the capsule, let's increase the height to three. And let's make the radius 0, I think 0.5 is fine. Now what happens here is that the capsule, the collision has its bounds around the center point, right? So right now it's using whatever this is. So if you want the player to actually fit inside that, we'll need to take our character model and move it down a bit. So since the size of our collision is three, what we'll need is to select our character medium and then set the wide minus three divided by two. Oh, sorry, minus three divided by two, sorry. Minus three divided by two minus three divided by two. And then let's just put that back into the, back into ground level there. So that should be around 1.5 then. So now our character is again on the ground, but we place the collision in the right place. I think that looks kind of okay. There's no collision on the head, but I think it's fine for our use case. This should be fine, okay.
Now again, we do want the player to bump into stuff, so the player is a rigid body. So let's add a rigid body component to it, toward the player, so the same one that has the collision. But this one won't be static, this one will be dynamic. Once you change from static to dynamic, a bunch of new options open up. And again, if you have any questions about what these numbers mean, just hover over this, and then you can see the API reference, you can see some hints there. This is similar to some other game engines as well, where in terms of like, what mass, lean damping, et cetera, et cetera. I'll give you the numbers that I'll be using, that also you're able to see on the full projects later, but if you want to use the same numbers as me, so mass is 100, linear damping is 0.9999, so four nines, so it's not exactly one, otherwise it wouldn't move, but it's almost one. This is to prevent the player from skidding across, so you're moving around, and it only moves as you're adding force width, otherwise it will stop, we want a number close to one but not really one, 0.9999 works well. We'll be using that same one for angular damping, so 0.999, and we'll also be using the same number for friction. So you can just copy that same number, so again 0.99999999 for linear damping, angular damping, and friction. Now what do these do again? Is make sure that the player feels nice on the ground that you have set up. Feel free to change it, you know, to play around with those things. Maybe your game has some cool skinny mechanics. Maybe the floor is actually ice or something. Just go crazy with these numbers. But the one important thing though is on angular factor, we want to put zero on x and z. And what do these do? This prevents our character from like topping over because if you think about it, if you think this is a capsule, on the real world, and you try to put it like this it will fall over, right? But that's not really what we want. We want it to be the character like standing like this and just walks around like this. It must be able to rotate like this. So this is why we kept the y at one so that it can rotate on the y-axis. But we don't want it to rotate on the x-axis or the z-axis. So we put that to zero on the angular factor. Linear factor needs to be one, one, one because it can move in all directions. Maybe not on y but let's keep it at one. We just don't want it to rotate on anything but y. So this is my setup. That again, feel free to use your own numbers. This is the one that feel okay here. And you can take a look into those later. Let's apply those changes to the template now. So I'll click on apply all. Let's move forward. We need to keep going. I talk too much. Cool, so what we'll start now is we'll be using now the script template. So we're moving into scripting now. Let's start with some scripts that we have here. On script templates we have already some again some templates. You know, some boilerplate code for most of the functionality. We'll be starting with the player controller. Find the player controller.js on script templates. Let's move it somewhere that makes sense.
14. Creating a New Folder and Customizing the Editor
Let's create a new folder called player and move our script there. The online editor is powered by Visual Studio Code and has various themes to choose from. You can also adjust the font size for better visibility.
Let's create a new folder. Let's call it player, and then let's move our script there. So again, a player controller. Let's move it to that player folder or we can keep it there. But I think this is... I think this is work better. And then let's... if you double click there, it will open a new tab with the script. Now this is the online editor that, again, is powered by Visual Studio Code. Now the theme that I'm using is actually the same one as Visual Studio Code. But if you guys want to change it, I'm not sure which one are you using. But if you go here on edit preferences, you can change the editor theme as well. We have a bunch of different themes that you can use. And I'll say increase the font size so you can... Here you can see it better. Let me increase it even more so you can see it even a little bit better. 18. But again, you can use whatever theme you want.
15. Scripting and Input
16. Adding Power Attribute to Player Controller
We added a power attribute to the player controller class, allowing us to change the scaling of the force without modifying the code. By setting the type of the attribute as a number, we can use both floats and ints. After saving the attribute, we need to click the parse button in the editor to update the attributes. The power attribute has a value of 4,500,000, which affects the skidding of the movement. Multiplying the movement vector by the power attribute allows for dynamic movement. With these changes, the player can now move around the scene.
17. Setting Model Rotation and Adding Animation
To set the rotation of the model, we need to move the model entity, not the rigid body. We create a new attribute called 'model' in the script and reference the model entity as its value. We use the 'setEulerAngles' method to rotate the model on the y-axis. After saving and refreshing, the model rotates. Next, we create an animation state graph for the idle and run animations. The state graph editor allows us to define the starting node, nodes for idle and run states, and transitions between them based on conditions. The idle state is the default animation, and the run state loops. We add transitions from idle to run and from run to idle based on the speed of the character.
OK. Now, the next thing you want is to set actually the rotation of the model, right? Because otherwise it's just like– just like doing like this, right? Now, the way that we'll want to do that is we don't want to– we don't want to rotate the rigid body itself. Otherwise, it will like– it will bug up the rotations of the– that the calculation of the physics. So what we want is actually just to move the model. Just the model, not the not the rigid body. So for that, we will need on the script a reference to the model entity, which is the child of the player. It's only to this one. And the way that we do that is we'll just add a new– this zoom thing is getting in the way– we'll just need to create a new attribute for it. So here, let's create a new attribute. PlayerController.attributes.add. So create a new attribute. Let's call it a model. Then for the type, so now this won't be a number. This will be an entity. So now, we're referencing another entity. And then before we go back to the editor, let's actually add the code for that. So again, it's a new attribute. You can call it whatever you want, but the important thing is of type entity. And then here on the line 43, at least for me, we have to do set rotation to model. Let's remove that because now we can do it. And then let's do this.model entity which is what the entity that we're referring. And we'll do set Euler angles. That's how you call it, I think it is. Now for rotations, Play Canvas does use quaternions for rotation, but it's very complicated if you want to set quaternions yourself. So it uses four dimension rotations to prevent gimbal lock. A lot of explanation for nothing, but we need to use set Euler angles, not set rotation. If you do set rotation, you'll be using the quaternions, which we don't want, so using set Euler angles and you want to rotate on y. But I already added here the calculation for depth. We don't need to write it by hand. So just do zero for x. So we don't want to do anything on x. We want to use new angle for y and you want to use zero for z as well. Now, if we save that, we go back to our launch tab and then we refresh. Oh, okay. So you can see that very useful. It's already giving us some errors, which is very useful for us to debug, but it it says here, cannot read properties of null reading set Euler angles. Interesting. Let's go back here on the code so it's trying to read set Euler angles from null. How does this mean? So model entities is nulled. Of course, because we forgot to link them. If I go back to character, to player here, which has the script, I'll need to press the parse again. And now we have the model entity, actually right here, right? So then what we do is we click on the character medium and just drag it there. So now we have a reference here to the character medium entity from our script. So if we click there, we can easily see where it is. It also highlights there. Okay, there you go. Nice. Okay. Now you can refresh here. There we go. Right. So now it rotates. Now it's very sudden, the rotation, but you know, we won't have time to, to fix that, to make a nice rotation. I'll give, I'll leave you guys a, as a homework to, to fix that. Or you can just check how we did it on the, on the full project later. But, okay. This works for now. Let's, let's move on. Let's make some animation perhaps now. Cause that's fun. Cause again like now we're only on typos and not, not really goes happens, but let's add some, some animation.
Cool. Now if you go here on food, food random character on the animation folder, we already have idle and run. So those are two, again, two FBX files that, again, I just drag and drop from, from can you download? That's it. This is what it provided me here. Like I was ready to generate all those files for me. But what I'll need to do first is create a state graph for it, which defines like, oh, I'm idle or I'm running. And then how to, you know how to do that. So to do that, let's select character animation and let's create a new, an instant graph. So again, on assets now, so now we're creating a new asset, which will be an animation state graph. So new asset and instant graph. Let's call it character graph. Now, if we double click on it, we'll change gears on the editor to the animation state graph editor. Now, if any of you guys have used other game engines before, this is very similar to other solutions in terms of how to set up an animation state graph. The way that it works is that you have a starting node and then you have nodes and transitions between them based on conditions. In our case here, we've already created the boilerplate simplest one, which has an initial state, which currently does nothing. It's looping. It's a state with no animation attached. What we'll do is let's rename this one to idle, so the default animation... By default, you're idling, like breathing, just kind of like this. And then let's create a new node. Sorry, new state... And let's call it to run. So we can jump between idle or run states. The run state will also be looping, because it'll be doing like this, right? Let's make sure that we click on loop there. And let's add a transition from one to the other. There's a condition that will make it so from idle, we'll start running... And then if we stop running, the speed is zero, we'll go back to idle. So right click on idle, add transition to run. Same thing around, add transition to idle.
18. Creating Animation State Graph
To create the animation state graph, add a parameter for the player's speed and set conditions for transitioning between idle and run states. Assign the state graph to the player model and link the idle and run animation clips. Set the speed parameter to 1.22 for a running animation. Apply the changes to the player template and adjust the speed parameter according to the player's actual speed.
Now, if we just do this, it'll just be coming back and forth and nothing will happen. So we'll need to add a parameter so that we can let the graph know what state, you know, what is the speed of the player so that we can actually move around. So here on the left, you can create a new parameter. So parameters, parameter, and let's call it speed. You can call it whatever you want and you can provide whatever type you want as well. So you have integer, so you can force it into integer, floats, boolean, so true or false or a trigger. A trigger will be true only for one frame on the first one and then it will go back to false. Very useful for like shooting where something happens only once. In our case, we want the float. That's our floating number, which will give us a number of what is the speed? What's like the magnitude of the speed vector that you're moving around. So with the speed parameter, we can select now our conditions and then let me just expand this a bit. And then here, I can add the condition. So on idle, I only want it to go to run if the speed condition is more than 0.1. So 0.1 works fine in this case. We want exit time to be nothing. So just erase exit time. Exit time means that it will only do the check once the animation is done, but actually we want it to be able to interrupt the animation. So if you're in the middle of your idle and you start running, you'll like stop idling and start running immediately. So be sure to erase exit time there. For duration, you can add anything you want. Duration just blends between the two states as the transition goes instead of just jumping from one to the other. This is the normalized time based on the speed, based on the time of the animation. So 0.2 is a fine number, just gives like some small blending. Let's do the same thing on the other one then. From run back to idle, that's at a condition, but we'll only do that if the run is less than 0.1. So if it went to zero, a very small number, probably it's not running so it'll go back to idle. Again make sure to delete exit time. Exit time shouldn't be zero. Exit time should be blank, just erase that. And then duration again, let's do 0.2 or whatever. Cool, that's it actually. That's the setup that we need for the animation state graph. Now when you create the state graph, you don't assign animations yet. We'll assign them in a second. This is only defining the raw behavior, just the brain of it. But the actual actions will be fine soon. So if you click here, then on the previous selection, or if you press escape, you'll go back to the main PlayCanvas editor. Now we have our graph here. What we want is to apply that animation to our model. So if you go back here to player and then select character medium here, we need to add that component for the animation. So let's add a component, anim. So it should be the first one, not this one, anim. And then just drag in the state graph that you just created. Just drag it in. And now here, as you can see, the idle and run states that we created. Now there are some slots for the actual animation clips for us to link, for us to attach. Before we do that, though, make sure that on the speed, you put that to 1.22, because from the test that I was running, this is a good number for... Like it kind of looks like it's running across the board. Looks pretty cool. So again, 1.22 should be fine. And then on root bone, select the root entity here. So if you just expand character medium, so be sure to use root bone there. This is just to make sure that the... This is a little bit technical on how animations work, but this is just to be sure that the animation and your entities on the scene are referencing actually the same transforms. This is how you make sure that everything lines up properly. Just a nice thing to do. And then here on idle and run, let's assign the animation clips. Now, if you open here idle... Actually, sorry, we'll need to make sure to select. So select character graph, sorry, select the character medium here to be sure to select, to have the slots here. So select character medium on your hierarchy and then from here, we'll need to select those clips. So you see, it's kind of like a placard thing from the movies. What's the name of that plaque? I don't know. So we need to select in this case, it's rootidle.glb. So just drag that into the idle. If you're not sure which one to use, that's a very nice way to preview, which is just by clicking on it. If you click here, you see, okay, like this is just kind of standing still. There's a character here. But in this one, okay, there's a nice animation here. So this only shows the wire frame view, but you can check what actually goes on like this. This looks like an idle animation. So this is what we want. So I just dragged in that one here and then same thing for run. So I just select the run folder and I want the root.run.glb. Just drag that in. Again, it's the file that has the movie thing. And if you're not sure, just select. Okay, this is a nice running animation. Okay, cool. Cool. Now we made some changes there. Let's be sure to apply that to our template, right? So here on the player template, make sure to apply all. That it applies to our template. Okay, you just click twice there. Now if I just press play here. Okay, so it's no longer on T pose. That's good. So it's using the idle animation but we are not changing the speed number. So even if we're moving about it, the animation state graph still things that were idling. So we need to make sure to set the speed parameter according to the actual speed that the player is going at.
19. Animating the Model and Handling Collisions
To reference the animation component on the model entity, we use this.modelEntity.anim. By setting the speed attribute to the magnitude of the linear velocity vector, the animation reflects the player's movement. To add functionality when the player collides with a collectible, we create a script called collectibles controller. This script listens for the triggerEnter event on the collision component and provides a callback function to handle the event. In the callback function, we use this.entity.destroy to make the collectible disappear.
And the way that we do that is if you open up the editor. So there's a nice to do animation here. What we need to do is we need to somehow reference the animation component on the model, right, on the entity and then set the parameter. Now we already have this setup, right, the model entity. And if we look at our setup, the model... Sorry, the animation is on the same entity as the model. So we can just reference the character medium and get the animation component out of it, right? The anim component out of it. So that's very handy. So again, model entity, right? So, or whatever you call it here. So if you go this.modelEntity, which again is referencing the the same entity that has the animation. And you say.anim. So now we're referencing the anim component of that entity. And then we do setFloat. Now setFloat, you need to specify two things. First, you need the attribute name, so we call it speed. And the actual number, right? Now the number, we could... Like the easiest way is just to use the actual number that the Rigidbody is using. Like if it's applying force and then sometimes it's hitting, blah, blah... We want the actual number that the Rigidbody is using. And the the key for that is this.entity.rigidbody. So with this, we got the reference to the Rigidbody. And then we want the linear velocity, which again is... So that is the velocity on the X and Y and Z-axis. Not the rotation, so how much it's actually moving. But this is a Vec3, so this is like an actual three-dimensional thing. But we want like the length of it, right? We want the magnitude, how much it's actually moving. So we can just say,.length, which is an average. And also you can just check the view reference for that. So with this, we're getting the magnitude of the linear velocity vector and passing that into our animation. So if we save that, go back to the game. We have to reload the scripts, because the scripts are already loaded. And then we move. Nice! Now what happens if I keep pressing D to move to the right and then I hit that collision right there? Let's see what happens. Oh, it stopped because it's using the actual rigidbody. It doesn't look like the classic thing in video games where the character is like running against the wall like that. This actually makes a little bit more sense, which is pretty cool. We got that out of the box. Cool. All right, so now we have some very nice integration here now.
20. Creating Collectable Controller and Game Manager
To create a collectable controller, we need to fire an event when a trigger occurs and destroy the collectible. We then add the collectable controller script to the food entity and apply it to the templates. A game manager entity is created to handle overall game functionality, including time management and event listening. The game manager script is already set up to work with the collectable controller. We also modify the spawn collectible code to reference the food template and dynamically instantiate it at the desired position.
But more than that, we needed to also we need to let the game know, oh, you picked up something. Now, the script templates that we have set up there are listening for events as well. So events can come from components, right. So for instance, the collision component, or we can fire our own events. So you can tell everyone on the scene, you can say everybody on the application, say, oh, by the way, this happened. And the way that we do this is say, this startup, so remember this startup is in reference to the PlayCanvas application. And say, that fire. So with this, we are firing an event. So that if anyone is listening to this particular event, such as we are listening to trigger event, trigger ends around the collision. They'll immediately receive that message. And we can say, collect it. So this is the name of the thing that we called. We can find more about it later. But if we just say this.app.fire, collect it, anything that is listening on this.app, so for instance, if they do this.app.collected, if they do this, they'll receive the message. Cool. So that's it. So this is the code that we need for the collectable controller. Whenever there's a trigger, we fire that event. And then we destroy it. Then what we do on the food here is then we need to add that script now. So then we go here, add component script. And then we add our new script called collectable controller. And then again, we need to apply, to make sure that we apply to the templates. And if you created more than one template, like have bananas and cakes, and you imported your own assets and you want to use, make sure to add those to the collectable controller, to all of that. And let's test it out. Press play. We're almost done with Phase Two, don't worry. And then I walk over there to the Apple. Oh, cool. Right. It disappeared. Nothing else happened because we didn't do anything else. So currently our game is walk towards the Apple. Cool. Right. Nothing happened. So let's move on right now. Cool. Now, what we want now is to use now the script templates that we have here. Right. Because again, it contains like boilerplate code for the actual like gameplay that you're free to look at later, copy and make it your own. But what we'll need to do is we'll need to create a game manager. So we have a game manager entity. Let's create on root. Let's create a game manager. It's called game manager. Script and let's add the game manager script. Which again, is already there, right? Let's take a look at what this game manager is doing. Make sure to click on parse by the way, because it has some some settings there. So if you open the game manager script, it already has a bunch of stuff that I won't have time to go through here. But it basically does stuff like, oh, am I playing around is the round over the stuff like counting the time and so on, for instance, are in the update method. It decreases time as time passes and then it fires an event. When the time s Up and etc. Now, this game manager already contains, like, most of the code that we need to make it work. And if you remember, it's already listening to the collected event that we just created on our collectors on our collectible controller. Yeah, so as you can see, we're already attaching to this event. So the game manager will work flawlessly with the collectible controller that just created. So, okay, we're good to go. So now the game manager is receiving the message as you want now game, by the way. Game Manager is an interesting name to give to exactly this is the script that doesn't handle anything. Any particular like entity or thing in your game? It just handles like your overall thing, right? Okay, I collected something. The players over there, I'm starting a new game. I'm restarting the game. I just seen here. And if we do a command F or control F to do, there's one thing left, which is on the spawn collectible. Now the spawn collectible already has some code here, which is basically what it basically does is it looks for a random position on the board for a place that doesn't have an obstacle on it. So this is already implemented for us. You can take a look, take a look here today to how it's implemented. You can make it on your own. You can, you can copy it. But what it's not doing, is it's not spawning. So if you play this and check it out, it will not spawn anything. We need to add that functionality ourselves because I want to show you guys how to do that. I mean, it already, at this point, at line 92, we all ready have the new X and new z, which is exactly which position we want to, we want to spawn but we need to do that. Now, in order to do that, first we need a reference to the templates that we created. And this is why I wanted to create a template out of the food items that you created. Right so, for instance, the apple writer, we have is an empty is a template that we saved here, food, right? So what we want is on the game engine we'll add an attribute so that we can reference that template and then we can dynamically instantiate it, you know, as we pick up stuff. So what we'll do is we'll say GameManager because now it's a GameManagerScript.attributes.add and let's call it a food template. And then for type, it's not number, it will be an asset. Now instead of again, so this means that we're not going to reference anything that's on the scene right now. We're going to reference something that is on the project asset. Now we don't want to reference any asset, you cannot instantiate a texture, but you can only instantiate a template. So we're going to say that the asset type is template. So this means that food template can can only accept references of type asset, which are templates. So you're sure that it's only template. By the way, if you guys have created like more than one, if you created multiple food templates, you have banana, you have apple, et cetera, you can say, and the arguments, you can say array equals true. If you do array true, this means that you can set more than one food template, and then food template will become an array, and you can do like dot length to see how many were added, or you can reference with the quotients thing. In our example, there's only one, so we'll keep it without the array thing. Then, what we'll do, so I have food template here, let's go back here to the spawn new collectable position. What we'll do is we're going to say, we're going to say this dot food template, right, dot resource dot instantiate, oh, sorry, instantiate.
21. Phase Three: User Interface and Publishing
We instantiate a new entity from the template using the 'dot resource dot instantiate' API. Then, we set the position of the new entity and add it to the scene hierarchy. We can use Chrome dev tools to inspect and debug our code, add breakpoints, and check variables. The console and network tab are powerful tools for debugging and monitoring file downloads. In phase three, we'll focus on user interface and publishing. Let's continue from where we are and work on the UI.
Now, we need to do dot resource because we want the actual raw template from it, like the actual data that contains from the asset reference, and then we want to instantiate that, so this is the API to do that, so dot resource dot instantiate. This will create a new entity, which is a copy of that template.
Now, we want to do stuff with it, we want to move it where we want, so let's reference it somewhere. So let's say const new entity equals the instantiate, and let's say new entity dot set position and UX0 do that. So now we're going to position the new entity that we just created to that position that we already found before, right? The code's already done.
22. Creating UI Screens and Elements
In this part, we'll create actual UI screens for the game. We'll start by creating a 2D screen and adding a text element for the score. We'll customize the position and anchor of the text element. Next, we'll add an image element for the time bar and set up the anchors to match the size of the parent. We'll also customize the color of the image. Finally, we'll add a script to the 2D screen and make references to the game manager entity and the time bar entity.
Now what we'll do is let's create actual UI screens first. So if again, if you go back to, sorry this is very annoying. If you go back here to the example, the UI is basically, so you have this time thing right here, a score text. And if you remember when we lose, there's a big screen saying, oh, time up, you know, like round over and then a button to start again. So let's do that real quick. Let's see if we can do that on time. That would be challenging.
So onRoot let's create a new entity and we'll create a user interface. We'll create a 2D screen. Now, everything that you want to be on screen space, it needs to be under a 2D screen. Otherwise it will be like on the 3D world. So let's create a 2D screen. Since there's always screen space, you can move it up. So it's not like in the middle of your hierarchy there. So you can move it up wherever you want. It will always be in screen space. And let's add, let's start by adding a text which will be the score. So here, let's create a new user interface. Text element. Where is it? There. Now be sure to be, to face the right side there. If you don't see it, it's probably on the other side. Wait a minute. So when you create a new text element, it assigns already like a random font, not random, but like the first font that you have in your project. So on the food run, here we have a lot of interesting fonts already set up. So you chose the first one, Kenny Blocks, but we can choose anyone. Let's choose this one, whatever, Kenny Mini, Kenny Mini Squarer, yeah. So I chose this one. Again, just drag and drop. And then we can move it about wherever you want on the screen. Now, by default, the element will be anchored to the center of the screen, which means that if I play, let me do it like this. If I play text areas in the middle and I rotate like this, if I do anything on the screen, play on a mobile device, it will always be there on center of the screen, which might make sense if you're new to use case. But we want one that says, like they're on top left, right? So if it's on the top left, if you want things to be on top left, what we do is on text, we can set the anchor to be there. So we already have some presets here. So on preset, if you just press top left anchoring pivot, it will automatically set the pivot and the anchor to the top left. And then we can move it down like this or something. Let's call it score text, set score to right? Cool. So now we have the text ready for the script that will actually put the scores as we move along.
Now we're almost at time. If you guys are happy to continue, let's continue let's continue for now. If you guys need to drop in, then fine. But I think we can, let's go ahead for now, let's see how far we can go. I'll go as fast as again. But again, I think the recording will be available later as well. So you can take a look at that later. And also again, the full project will be available. Yes, we did start a few minutes fast. Let's see five minutes, what are you going to do Jorn? Let's see. And the full project again, will be available later if you guys take a look at like the full thing with a little bit more like breathing. So we have the score text. Now let's add this time right here, this bar, that's pretty neat. So the way that we'll do that is a following. We'll create a new entity as well, a new user interface. Let's call it an image element. So this image element. Let's also put the preset on the top left anchor, and keep it so it's there. By the way, this means then as we move stuff around, to always be on the top left there. So it's always there. Very useful for creating responsive UI for mobile devices that you can rotate or not. So yeah, this is a pretty neat feature. If you select here on the resize element component, you can easily resize the size thing. So let's create that background. So this is the background here, that white thing on the back end, on the background. And then let's create a new entity to be like the middle part, right? So now let's color this one the green tint that we have there. Now we want it to be like, to take the full size of the time, right? But then as the time goes on, it should go like this, right? Or like this for you guys. So the way that we do that is very easy to set up the anchors so that it's exactly, it matches the size of the parent. So we can match the size of the parent by setting the anchors to be all of the corners. So we can either select this gizmo right here and then go here, so this one should be here. This one should be there. This one should be there. And this means that the anchor is 0, 0, 1, 1. Now it has some margin, which we don't want. So it's taking more space. So let's reset up the margin there. So it's all zero. Now it's taking the full space, but if the margin then is decreasing like this, you can see this is the fact that we want. Like, as the time goes on, we want the margin to increase. So we have all the setup there that we need for make that happen now. Let's take the score here. Let's put it up there now. Now actually, this is everything that we need. Now, of course, we need to add the tag, the text says Simon, et cetera. Let's not do that. But what we'll do is on the 2D screen here, let's add a script and let's add the UI controller script. Now the UI controller script already has like all the code that we need to make all of this thing already set up properly, like exactly as we need. But we just need to make the references to the right entities. So the first one that we need, we need the game manager entity. So this is the entity which contains the game manager script, so let's put that. Now we need the timebar entity. So that's the green one.
23. Final Project and Publishing
Let's check out the full project, which includes all the UI controllers and a final game setup. Feel free to use the CC0 assets by Kenny and add the proper credits. To publish to Play Canvas, click the 'publish/download' button, give it a name, and press 'publish now'. The resulting link is permanent and shareable. Play Canvas is playable on mobile and multi-platform. That's it for today. Thank you for joining and sorry for going over time.
Okay, cool. The score text entity. Cool, let's put that on there. Now if you remember here on the example there was a starting, there was that Eat Me there, string that was there. Let's skip it out for now. That's not created. On the round over screen entity and round start, so this is the game over ones, right. So let's not do anything on those right now, so otherwise it will, otherwise it will take too much time. But now if you press play on this and you check out what we just did, so let's do another one. Oh no, can I set properties of null, setting enable? Probably because I didn't set one of the things. Let's fix that. So this is very useful by the way, to have these things here. If you click on the button, it will automatically open up the code editor for you with syntax highlighting and highlighting exactly where it went wrong. So now it's using this, right. Let's check if this is not null then do the thing. Otherwise just let's check it. Let's save it. Refresh. Okay, now it only starts when you pick up something, right? So let's pick up some, let's see what happens. Oh, there we go. Okay, so now we have the scores. Now we can see that the time is going down. And then if you pick it up, it goes, oh yeah, okay. So now we would have lost. But again, we didn't finish setting up all the different stuff. Now if you wanted to see the full setup, all that you need to do, let's do that right now because you no longer have time. Let's now check out the full project. So again, I'll send it soon. Full projects. Let me send you on the chat. This is the full project that you can take a look and you can fork as well if you want. The final setup is basically just setting up all the different UI controllers that there and creating this screen right here, which has this button on the bottom, which already contains some hover pressed hints. So, as you press, as you go over, it does different things. And already has like the listener as well for when you click to restart. So, you have everything there that we need. And this is the full project. Again, go ahead guys, go crazy on it. You can take a look at everything that is done. Feel free to use, I mean, all the assets are CC0 by Kenny. Do give him a shout out if you use any of those. Do make sure to add the proper credits. And this is the final game. Let's see if you have anything else there on the slides. But I think that was it. So, yeah. So, we didn't learn how to use audio, but I think that's for the next one. Be sure to take a look at the audio manager script there. Be able to see exactly how it's done. And this is wrapped up. Oh, oh, oh, one final thing. If you want to publish to Play canvas, this is super important, on the toolbar here, the last toolbar here, publish slash download. Just click it. Publish to Play canvas. Give it a name. Give it a description. That's optional. Just the title is required. Press publish now. It's building. There it is. It's building up. Click. This is a permanent link to your particular build. This is yours forever. Never be taken away from it unless you download, unless you delete the project or delete the app. Otherwise, you can send this to everyone. You can send this to anyone to play around with your game. And also be sure to tweet. If you do it, be sure to tweet about it. I'll retweet it. We'll help each other out, we'll follow each other to help out those in game devs. Because again, this is playable for everyone. You can play it on mobile, you can play multi-platform. Out of the box, there you go. This is how you do publishing on Play Canvas. I took 30 seconds or something to do that. There we go. And yeah, that is Play Canvas. Thank you very much, sorry for running a little bit over time. I think I was a bit too optimistic when I was preparing this. I did practice it twice, I did manage to do it on time. But I think I spoke too much today.