Game Development with Unity and MongoDB Realm

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone i'm nick raboy i'm a developer advocate at mongodb and i'm also the organizer of the tracy developer meetup recently we did have a meeting at the tracy developer meetup group uh on unity and mongodb i didn't record that session but i did want to go back and actually do it again uh because i think it's worthwhile material to include on youtube and uh it seemed like it had a lot of traction so i want to make sure that everyone's successful if they were to go back and try to attempt this project on their own so i will be using unity i will be using mongodb and we're going to be using a little c sharp here and there in between if you are not already a member of the tracy developer meetup and you are in the tracy california area so stockton lathrop galt things like that with wherever is a reasonable distance i encourage you to register to the group participate in our meetings you're going to learn a whole lot so on my screen you'll notice that i do have the unity hub open what we're going to do is we're going to go ahead and create a new project and for that new project i'm going to use the 2d template everything that i go over today you should be able to go through either 2d or 3d it's really up to you 2d is kind of my jam so that's why we're choosing it it's i'm from the 90s so that's that's where i'm going to stick but it's totally up to you on what you want to choose i'm going to save my project to the desktop and i'm going to call this tracy devs sample and i'm going to say create project now it may take a few minutes to create this project depending on what kind of computer you're developing on and the specs of that computer alright so you'll notice that i do have a blank unity project open it has a sample scene as well as a main camera all of these are game objects well at least the main camera is so the main camera is a game object that exists within the sample scene uh the main camera is just a game object but it does have the camera component attached so you'll notice that as we add game objects to our game we're going to be adding various components to them that will help define well are they a sprite are they a camera are they something else so that's how you define what a game game object is within unity what you see on the screen here in this box this is the range of the camera so if i were to hit that play button it would basically just zoom in on those boundaries and we have a blank blue screen which is pretty much normal when it comes to unity if you have nothing in it so i'm going to stop the previewer and i'm going to right click within the sample scene and i'm going to say 2d game object or 2d object i'm going to click on sprites and i'm going to click on square there are other ways to create a sprite in unity you can create the game object as an empty game object and you can add the components one by one it's totally up to you you'll notice on the right it added a sprite renderer in this case the spray is a square i could very easily change that to an image but the focus of this particular video or what happened at this particular meetup was not on the graphic side of things not on the animating side of things it's more on the logic side of things so we're going to leave it as a square i'm going to rename this from square to player as you'll notice in the top left of my unity editor the name does not truly matter it has no impact whatsoever on the game it's just for naming purposes so that way we know what we're attempting to work with so i've named it player what i'm also going to do is i'm just going to create another game object so i'm going to create another sprite i'm going to right click in the menu and i'm going to say 2d object sprites and i'm going to add one more square just so that way we can see that they're not just one object i moved the new sprite over to the right a little bit it is white what i'm also going to do is i'm going to change the scale of it so that way it's smaller i'm going to cut it in half we're not working with the z axis much or at all in this particular example because we are creating a 2d game so i'm going to leave that alone it doesn't need to be touched i'm going to change the color of this square so this square i'm going to say maybe it's green and i'm going to give it a new name so instead of just calling it square which isn't really helpful i'm going to call it incentive now when i say incentive think about it in a game as maybe a coin or a medal or some kind of trophy something that your player is trying to obtain all right so i have a player and i have an incentive if i were to hit that run button it would zoom in a little bit but i cannot actually control my player and my incentive doesn't actually move uh that could easily be an obstacle rather than an incentive too it doesn't really matter but right now everything is static within the scene all right so let's go ahead and add movement to our player what we're going to do is we're going to go to the assets section of our unity editor and i'm going to click create so i'm going to right click and click create i'm going to say create folder if we truly absolutely wanted to we can add all of our assets to the root of this assets section but trust me when i say this it will get very messy very quickly if you don't start creating subfolders for all of your different components so this particular subfolder is going to be called scripts it's going to include all of the scripts that are going to control our game i'm going to double click on that scripts directory i'm going to right click and i'm going to say create and i'm going to create a c-sharp script so this c-sharp script is going to exist in the scripts directory and i'm going to call this player the name does not truly matter i'm just calling it player because i know that this particular player script is going to control our player game object it could very easily be named joe or jane or whatever you wanted to call it doesn't really matter what you call your game object or your script all right so we have a player script what i'm going to do is i'm going to double click on it and if you've already set up a default editor on your computer in my case i'm using visual studio code it should open up in that editor and it'll look something like this so every single script that you create in unity will extend the mono behavior and the mono behavior does have access to various life cycle events for example start and update so the start event is triggered on the first frame of your game and the update is every single frame and that could be variable depending on the frame rate of your device so of course slower devices will have less frames per second and faster devices will have much more we're going to see how to accommodate that in just a moment there are other life cycle events so for example there is an awake that we're going to be using in the future of this particular example which happens before the first frame there are other lifecycle events as well i totally recommend that you check out the unity documentation if you want to learn more about those so we have our player our goal here is to move it around but the first thing that we want to do is when it starts let's define a starting position on the screen so what i'm going to say is transform so just by saying transform i'm talking about whatever this script is attached to right now this script is attached to nothing but when we attach it to a game object the transform will transform that particular game object i'm going to say position equals new vector 2 since we're in the 2d space and i'm going to give it a 0.0 f because this is a floating point position and 0.0 f so we're going to center this on the screen when our game loads in the update this is where we're going to handle our movement and this is going to evolve as we progress through this particular example but for now we're keeping it the bare minimum so what we're going to do is we're going to say if we're going to say input dot get key and we're going to check to see the key that was pressed we're going to say key code and what we're looking for in this particular example are the arrow keys there are other ways and even potentially better ways to handle user input in your game but because this is a very basic example and this this works particularly well we're going to say for example left arrow and we're going to track the the keyboard presses directly if you're working with a game controller or some other kind of input device you may want to evaluate some of the other offerings that unity offers so if the key that was pressed was the arrow key the left arrow in particular i'm going to say transform and i'm going to say position i'm going to say plus equals and this is where things can get a little weird just for now so even though that we are working with a 2d game object we still are in the 3d space technically and because we're transforming just the position of the game object which really has no kind of details on uh or knowledge that we're in the 2d space what we can do is we can say vector 3 and we can say left there are other ways to manipulate the vector position in unity and there are other ways to handle movement in unity so you don't even have to do a transform and in a a lot of circumstances it doesn't even make sense to do a transform but for this example it does i'm going to close this off for now so this tells us that we're going to change our vector direction into the left direction although if we were to try this and hit the left arrow it likely wouldn't do anything what we have to do is we did have to define how fast this particular game object should move in the left direction and we also have to accommodate for the time speed so starting with the movement speed i'm just going to go up to the top of my class outside of the functions and i'm going to create a new variable what i'm going to do is i'm going to create this as a serialize field so when i say serialize field what that does it allows us to access this variable directly within the unity editor and you'll see what i mean in just a moment but what i'm going to say is private float and i'm going to say movement speed i'm going to default this movement speed to 5.0 and this is not a string 5.0 f and we're going to adjust it in just a moment but if i drop down back into our update i'm going to say times and i'm going to say movement speed if i left it as is technically it would move left but it probably would move pretty quickly depending on the device that you're using so in order to have a consistent experience between devices what you should probably do is you should multiply it again by time dot delta time so i'm going to go back into my unity editor for now we're going to come back into the script in just a minute but i'm going to go into the unity editor it's going to take a moment to reload if i were to run nothing would happen so nothing happens because this script in particular isn't attached to anything so i'm going to click on my game object for player and i'm going to drag this script over into the components area of the inspector and i'm going to drop it if i wanted to i can click add component and search for the script manually but trust me when i say this it's a lot easier just to drag and drop you'll notice that movement speed is showing up because we did make it a serialized field if i had left it as a private variable and i removed serialized field this particular field would not exist inside of the inspector i'd still be able to access it and use it within the script but just not from the inspector if i made it public without the serialized field it would still show up but for this particular example we don't need it to be a public field so we should probably keep it private so i'm going to save it and i'm going to hit run now when i hit the left arrow key you'll notice that it moves left when i hit the other arrow keys nothing happens because i didn't program anything to accommodate that so i'm going to stop this and i'm going to go back into my code editor and i'm going to continue to finish this so i'm going to copy and i'm going to say else and just paste that in and i'm going to do it a few times before i make adjustments so i potentially have each of the arrow keys i'm going to change this rather left arrow i'm going to say right arrow instead of up arrow or left arrow i'm going to say up arrow vector 3 up and finally i'm going to say down arrow once again there are plenty of other ways to handle movement of your player within unity and once again this may not be the best way to do it depending on what your game is is going to be so i'm going to save it we're just going to test to make sure that it actually works correctly i'm going to go back into unity and i'm going to hit run now i'm going to move my player around everything looks to be good if i wanted to test things out this is a cool a little trick with unity that you can do i'm going to click on player i'm still in the play mode i'm going to go over to movement speed and i'm going to increase it to 10. now if i go back in without having restarted my editor it took that change so instead of 5 it's now moving at 10. however i stop it it changes it back to 5. so any change that you make while it's currently playing it will not persist when you stop it however if i changed it to 10 right now and stopped it and started in what and what not it would still be 10. so those are just fun fun little facts to know if you're getting started with unity all right so we have our player if i were to move my player over our incentive nothing would happen which is normal so instead maybe what we want to do is we want to start having a collision handled so when when our player collides with our incentive maybe our incentive changes location on the screen so let's let's start handling collisions so i'm going to click on the player i'm going to click add component and i'm going to click box collider 2d now it may be hard to see but if i click on this edit collider you'll notice that i have little boxes here this is my collision boundaries and i can adjust them as necessary because we're working with a square and we're using a box collider 2d it probably will be pixel perfect collision but depending on the image that you're planning on using you may need to make adjustments so that way collision boundaries look and feel the way that you want because a box may not make sense for for every single example so i added a box collider on the player i need to add a box collider on the incentive so i'm going to add it if i were to hit play we still wouldn't be done it's still not going to register our collisions what we do need is we need to add physics to our game objects so what i'm going to say is i'm going to say add component i'm going to type in rigid body 2d because once again we are working with 2d and if i were to leave the body type as dynamic that means that we are adding gravity to this particular game object so we've added physics and we've added gravity if i were to hit play our game object it should fall right off the screen because there's nothing stopping it from falling endlessly for this particular game we don't need to worry about that kind of collision we just want collision between our two objects so what i'm going to do is i'm going to change this to kinematic and i call it kinematic i don't know if that's the true way to pronounce this word it could be kinematic but i'm going to call it kinematic and what that's going to do is it's going to keep our collision information it's just going to remove our physics information and i'm going to say use full contact so that way two kinematic objects can can collide with each other i'm going to do the same thing for the player i'm going to add a rigidbody2d i'm going to change the body type to kinematic and i'm going to say that we have full contacts so i'm going to click that little checkbox now if i were to hit play uh it it still wouldn't it still wouldn't do anything really because we're not we're not really tracking any collision information or we're we have it but we're not making use of it another thing that we're doing is now that we're using physics we're using a rigid body we're still transforming the game object itself which is working for now but in a more complex game you may run into trouble because what you really want to do is once you have physics on a game object you want to control that game object through the physics itself so like i said it's working now but it may not be working well so we have to make an adjustment so if i go back into my code for the player we're going to start on the player because we're using a rigid body 2d let's go ahead and add a variable i'm going to say private i'm going to say rigidbody 2d and i'm going to say rigidbody2d we're going to use our awake method to grab an instance of this so that way we can we can actually play around with it so i'm going to say void awake and i'm going to say rb2d equals get component so the git component function will allow you to access any component that's attached to the game object that this script in particular is attached to and the particular component that i want to access is the rigidbody 2d now instead of transform what i want to say is i want to say rigidbody i'm going to do the same thing for all of the other areas as well so i can't just hit play because we'll get an error when i'm working with a rigid body 2d in particular we're no longer in the 3d space so we can actually change this to vector 2 instead so if i were to run this which i will just for testing purposes our experience should still be the same and it is all right so let's go ahead and start playing around with the incentive now and we're to we're going to make use of the collision inside of the incentive so let's go ahead and create an incentive script i'm going to call this incentive just so that way we know what we're working with i'm going to open it up it should look pretty familiar to you what we want to do is we want to get our rigid body component so let's go ahead and say private rigid body we're going to call it the same thing and we're going to say void awake which happens before the start method we're going to say rigidbody2d equals git component rigidbody and now we can make use of it so what what do we want to do well when the game starts let's randomize the position of the incentive just for the heck of it so we're going to say rb2d dot position equals new vector 2 and let's use random range so we're going to say random dot range and let's go ahead and say maybe negative 4.0 and positive 4.0 and these are not in pixels this is based on the camera space so it's a little different and i'll show you how to how to maybe check in some circumstances on on how this would work uh but it won't work it won't work on all devices like this you'll have to do other things so we have a random starting position the update we're not actually going to move the incentive every frame so we can we can actually remove it and what we are going to do is we're going to check to see if there was a collision so what we can say is we can say void on collision enter 2d and this means that when the collision starts so there are other collision methods so there's oncollision exit 2d where where this is when the the collision stops there i think there's an on collision stay 2d so when the collision is has been in the uh it's been happening for more than a certain amount of time things like that there are other operations as well the on enter the on collision enter 2d is good enough for us so i'm going to say collision 2d we don't care what was colliding with us because we only have two components right now or two two game objects so what i'm going to do is i am just going to copy line 17. and i'm going to paste it here and every time we collide it's going to pick a different different position so i'm going to go back into my unity editor and you'll notice that we have an error we'll get to that in just a minute to figure out what that means what i'm going to do is i'm going to click on incentive i'm going to drag the incentive script onto the incentive inspector area for that i'm going to see what this error is so random does not contain a definition for random i probably made an error somewhere so i'm going to go back into my code uh yeah it's not random it's it's range so random.range i'm going to save it it should be good now looks good so you'll notice i positioned it here going back to what i said about the actual positioning so we're not using pixels here you can use a pixel perfect camera if you want there are options in unity it's out of the scope for this particular example but if i drag this around on the screen you'll notice at the top area of the screen here the position changes so with these particular camera boundaries we have what looks to be about 10 and the x and for the y we have what 4.87 and around 5 and 5. so it's up to you on how you want to do your positioning like i said it's going to be different on all devices because all devices will not have the same aspect ratio so you'll have to accommodate that with different logic checking depending on where you want to deploy to i'm going to hit play should position it somewhere random on the screen it did down below i'm going to move my player over the incentive and you'll notice that it is randomly selecting positions that's to be expected so everything's working as we anticipated let's go ahead and see a nifty trick so if you're new to unity let's go back to the root of our assets area and let's create a new folder i'm going to create a new folder i'm going to call it prefabs i'm going to go into the prefabs folder and what i'm going to do is i'm going to drag my incentive game object into the prefabs folder you'll notice that the incentive game object has now turned blue because it's a prefab now so prefab lets you duplicate your game objects by drag and drop and when you do that it copies all of the components that were previously attached to that particular game object so i'm going to drag from my prefabs back into my scene and i now have two incentives they're both blue the name does not matter whatsoever let's go ahead and move incentive one over let's go ahead and change the color i'm going to say that maybe this is yellow and i'm going to say that maybe the size is going to be 0.25 and we're done actually on that one so you'll notice if i hit play that each of these incentives behave separately from each other so if i hit the green one the green one moves if i had the yellow one the yellow one moves because the script even though that it was copied over with the prefab information each of these prefabs within the scene act independently of each other so the script does not control all game objects that it was attached to it controls the one game object that it was attached to so if i wanted to i could add more incentives on the map and it would work great a lot of times what you would want to do is you want to initialize those with code so maybe when your game starts you initialize i don't know if we use the example of bullets and a gun maybe we initialize 50 bullets in your gun so those could be 50 50 prefabs if you wanted them to be so you can think about it that way so just a nifty trick if you're getting started with unity all right so we have our incentives we have our player the next step is actually going to be to view score information maybe we increase our score every time we collide with our incentives so what i'm going to do is i'm going to right click in the scene area and i'm going to go down to ui technically what you're supposed to do is use text mesh pro in more recent games you get more more features out of it and it's supported just for simplicity purposes and really it's not too much more simple than using text mesh pro is i'm going to use the legacy text if you can use text mesh pro it's not going to be too far out of your way to get it set up and working but just for simplicity purposes i'm going to use text because we're not doing anything fancy what i'm going to do is i'm going to call it score text does name doesn't matter it was added within a canvas and there's an event system the event system we're not using here canvas will be adjusted in just a moment you'll notice that it added another box we can't really see it in this in this circumstance because by default when we add it it uses the screen space overlay option and there are different options when it comes to displaying your text because maybe you're building like a 3d game and you want the text to have perspective to it when you view it on a building when you're walking around in the game that's not what we want here we actually just want like an overlay hud like if you want to show health and whatnot so i'm going to change it from screen space overlay to screen space camera it does give us a render camera to work with i'm going to go into my scene and i'm going to drag my main camera into this box for render camera it's hard to see but it actually now you can see the text at the bottom left so let's go ahead and work with that text i'm going to call it score i'm not going to give it a score value yet i'm going to make it bold i'm going to change it to maybe i don't know 30 pixels i'm going to center it vertically and i'm going to make it white so that way it's a little more visible now you can't really see it i have to resize the the bounding box for the text i'm going to make it nice and large i'm going to also move it so right now the pivot point is in the center of the screen you don't have to mess around with the pivot information i find i get better results when i do so my intention is to keep the score at the top left of the screen so the pivot i'm going to make at the top left and you'll notice that after i did that it changed the position x and y information because it's going to be basing it off of that as my as my center point so i'm going to move it up and it's going to be based on that pivot point if i were to hit play we'd see score text but it would be kind of meaningless now because we're not actually calculating the score so let's let's get down to business on actually calculating a score now to do that we are going to need a way to store our data and this is where mongodb comes in and this is going to be a two two step process when it comes to actually working with our data this first step is going to be working with our data locally and then the second step is going to be working with sync so that way we can sync it between devices so we can pick up exactly where we left off so what i'm going to do is i'm going to open up the package manager for unity and you can actually do that by clicking on the window menu and then going to package manager for unity and what i'm going to do is i'm going to add it manually as a repository so right now the realm unity sdk is not a part of the unity asset store so to add it i'm going to click on the little cog icon i'm going to say project settings that's going to bring up another window for us we're going to add a repository i'm going to call it mpm for the url for this repository this is of course going to use the node package manager you don't need to have node installed on your computer you don't need to be familiar with node.js this is just where the where the package is going to come from but i'm going to give it the repository url so it's registry.mpm.js and then the scope for this particular package is io.realm.unity i'm going to save it i'm going to close this window now and i'm going to go back into my package manager if i click on the little drop down for packages in project i'm going to now go into my registries my registries may not have existed before because you didn't have any registries added but i'm going to click it and you'll notice that i do have realm added now this is the version that we're going to work with for this particular example today i'm going to click install all right so the package is installed from a user perspective that won't have any kind of impact on us whatsoever until we start using it so what i'm going to do is i am going to go into my scripts directory i am going to create a new script so the first script that i'm going to do is i'm going to create a script called realm controller with the purpose of this particular script controlling everything that we're going to be doing when it comes to our data in realm so this is manga to be realm this script is going to be attached to a game object that has no graphical ability whatsoever it's going to be an empty game object because we just want this to be a controller type it does not be it does not need to be visible in our game with the realm controller selected i am going to drag the realm controller over into the inspector to attach it doesn't do anything yet we have no logic in there but what's going to happen is i'm going to double click on realm controller and we're going to we're going to get down to business so first of all i don't need the start and the update we are going to leave it as a mono behavior but we don't need to be worrying about frame information so there's different ways to work with with realm um and there's really not a wrong way i'm going to show you my preference so my preference is to work with a singleton instance so in a typical game you're going to have more than one scene in your game right now we're only working with one scene and that's all we're ever going to work with but if you choose to have multiple scenes in your game every time you switch scenes all of your game objects are destroyed now if i have my realm controller inside of my sample scene right now and i wish to use that realm controller in another scene well what i would have to do is i would have to re-establish my connection with that realm database i mean the connection is local but you still have to open it it could be resource intensive what makes sense is to use a singleton that we're using the same instance regardless of where we are in our game so to do that what we're going to say is we're going to say static public realm controller and we're going to call it instance now we need to initialize it so we're going to use the awake method so we're going to say void awake this is part of our unity lifecycle events i'm going to use this method don't destroy on load so what we're saying here is do not destroy our realm controller game object when we switch scenes we do need this to be available all times every time i'm going to pass in game object which means that we're referencing the game object that this script is attached to perfect so the next step the next step is we're going to say instance equals this and we're going to call it just for now in order to continue working with realm so we have a realm controller for working with it but we need to define a data model so what is our data going to look like inside of realm so going back into the unity editor we're going to create another script so i'm going to right click i'm going to say create and i'm going to say c script and this is going to be game data model and you can call it really whatever you want doesn't matter i'm going to double click it now this is not going to extend the mana behavior we do not need the unity lifecycle event so what we need to do is we need to extend realm so this is going to be a realm object we don't need the unity engine for this instead we want to use realms and we also want to use mongodb so we want to use mongodb.bson we no longer have a start and an update to work with which is fine but we do want to define the fields in this game object so within this realm object so starting with our primary key because realm does expect this this is an object oriented database and it does expect a primary key even if it's going to be used differently when it comes to mongodb in the cloud so we're going to say primary key as a property we're going to say public we're going to say string id and we're going to give it a getter and a setter method i'm going to do the same thing for a few more of our variables so we know that we probably want to store a score value we're going to say public int score and you know what maybe we want to store the x and y value of our player too so we're going to say float and we're going to say x as well as y now this is going to change slightly as we progress but this is a good starting point and we don't need annotations yet for any of the other fields so we have our data model to work with let's go back into the realm controller what we're going to need to do is we're going to need to import realm again so we're going to say using realms and we need to add a variable to handle our currently open realm instance so this is we have an instance to our actual class what we need to do is we need to get access to the realm itself so we're going to say private realm and we're just going to say realm and we're going to see if that realm already exists or not so we're going to say if realm equals no then let's go ahead and create a new one so we're going to say realm equals and we're going to say realm.getinstance so that will get an instance of a new realm technically if you already have a realm in your local file system it will just get that which is good because if you already have a game established on android or ios or wherever it may be you don't want to just create a new realm every single time you just want to get a new instance of it so we have that what we want to do is we need to handle the circumstance where we stop our game so we need to destroy it not the database itself but the instance of it so what we can do is we can say void on disable and we can say if realm is not null so it actually has something we can say realm.dispose so we can destroy it all right so we have that we have that taken care of now let's go ahead and worry about either getting our data from the realm or creating data in it so let's go and create another method and we're going to use this method as a helper method and like i said anything you you see here there are probably a million ways to accomplish the same thing it's really your preference and your coding style so what i'm going to say is i'm going to say private i'm going to say this is going to be a game data model and i'm going to say git or create game data that's going to be the method so i'm going to say game data model and the actual character should not be capitalized in the variable itself but i'm going to say equals i'm going to say realm dot find i'm going to tell it what type of data i'm finding so it's going to be we're going to be finding a game data model and i'm going to provide it a primary key which we know to be a string because that's what we've defined in our game data model class now right now android boy doesn't exist so what i'm going to say is if eam data model equals null so it doesn't exist this is our first time trying to work with it we're going to create it now we can work with our objects like c-sharp objects that's the point of an object-oriented database however to avoid problems when it comes to multi-threading and things like that we do need to wrap it in a certain right block we don't have to do that for reading just writing but that would look something like this so realm.write and in within this write block we're going to create it and we're going to we're going to grab an instance of it so we're going to say game data model equals and we're going to say realm.add we're going to say new game data model and we're going to define the data that exists for this particular new game data model that we wish to add to our data store so we have an id let's go ahead and call it enroboy we have a score let's go ahead and zero it out we have a x value so also zero and a y of a zero um so we're basically just initializing everything so that way we're good to go and then outside of the if block we're gonna say return game data model we're doing that because we've either found data or we've created it and we are returning what we just created so life is good and we're going to call this method every time we try to access our data so that way we don't ever end up with null data values and things like that you can have basically as as much data as you want inside of your realm in our case we're only working with one piece of data because our primary key is always going to be android boy in this example but we're going to expand upon it in just a minute but now that we have that let's go and make some changes or additions in this case so i'm going to say public and i'm going to say int get score so let's go ahead and get our data from this particular data store so i'm going to say game data model equals get or create game data and i'm going to return the score value so i'm going to say return game data model dot score so i'm just going to return it as is because once we once we actually have our data we can use it just like we would any other c sharp class let's go ahead and add another i'm going to copy this this time around let's go ahead and get the position of our player so i'm going to say vector 2. i'm going to say get position and technically we don't need to do it this way we can we can just return the entire game game data model to whatever class is requesting it but i find that it's a little cleaner just to create helper methods along the way so get position we do have an x and y value so what we have to do is we have to return a new vector 2. so this is game data model dot x and game data model dot y so a new vector let's continue creating new methods so this time around i'm going to say i want to set the score and i want to set the position so i'm going to say i'm going to paste that for setting we're going to say void we're going to say instead of set let's go ahead and say increase score i'm going to define maybe what i want to increase it by so i'm going to provide a value this is where we have our right block so i'm going to say realm.write and within our write block what we're going to say is we're going to say game data model dot score plus equals value so we're going to just add value to whatever our score is let's do the same thing for our set position so i have a void here for our function and i have a set position our position we're working with vectors so let's go ahead and take in a vector so we're going to say vector 2 position and let's use our right block once again i'm going to copy it over i'm going to paste it in and for our position we have our x which is going to be position.x and we have our gamedatamodel.y equals position dot y because a vector we have access to the x and y coordinates and that's good enough there's one more thing that we will need to do in the future but for now this should work out wonderful so we have each of our methods let's go into our player.cs file and this is where we're actually going to increase the score but actually before we do that let's go back into our unity editor we need to actually link up the score so that way it can be showed shown visibly so we're going to create another game object it's going to be empty this one's going to be responsible for controlling our game so typically you would want something uh kind of like a a super super power or whatnot it's however you want to phrase it something to control all aspects of this particular scene there's there's different ways to do that i mean technically i could have all of this information inside of the player the player game object or the incentive but from a maintainability perspective just go ahead and create a game controller doesn't need to persist it's just for this scene i'm going to create a new script that's going to be a c sharp script i'm going to call it game controller i'm going to click on game controller in the sample scene and i'm going to drag the script into the component section so that way it's linked up and now i'm going to open it all right so inside of this game controller we will be using the mono behavior and what we want to do is is we want to be able to control the score so the text now to do that we will need to import a new dependency here so we're going to say using unityengine.ui and we're going to say serialize field private text score text now we're going to do this in a few functions here so a few few of these life cycle hooks so you'll notice that this is a little different so even though that we're working with a component and whatnot we're not going to try to grab it from the game controller because the game controller itself does not have the text component this is going to be something else so what we can say is and you'll see what we do in just a moment but what we can say is score text dot text equals score and i'm just going to set this to 0. we're actually going to take it from our data store instead of the update and the update happens so fast that you won't even see it as score 0 when we load our application but we're going to say score text dot text equals score and we're going to say plus realm controller dot instance dot get score and because it is an integer we do need to convert it to a string so we can say two string now if i were to run it it would fail because score text we have no idea what score text is it's a serialized field so let's go back into the unity editor let's click on game controller you'll notice that there is score text there because we're using a serialized field but it's none so go over to your sample scene drag score text not the canvas just score text into that empty field so now they are linked up and if i were to hit run it probably will still say zero but as long as it doesn't have an error we're good to go so score zero because we don't have um an actual score value yet it's just the initialized state so let's go back into our editor and let's go ahead and go to our player let's add another collision method here so we have the collision information inside of incentive to tell us what the incentive should do after collision but let's go ahead and define what the player does after a collision so we're going to say void on collision enter 2d and when the player collides and this could easily be added to the incentive if you prefer but when the player collides with something let's go ahead and say realm controller dot instance dot increase score and we're going to increase it by one what we're also going to do is we're also going to save the position so we're going to say realm controller dot instance dot set position and this is a vector and we have a rigid body so we can just say rigid body 2d dot position and this will pr this will pass through our position vector so let's save it let's go ahead and go back into our game i'm going to hit preview and we have a zero score let's go ahead and start hitting these uh it increased pretty fast because they probably it probably randomized on top of my player again we don't have any any logic to prevent that but the score is increasing if i stop it and i start it again it should still say six i think that's what we left off at yeah so it it says seven i think that's probably what we left off at you'll notice that it did center our object so we're not actually updating the position let's go ahead and stop it let's go back into our editor for player so when we start our game so on the first frame instead of setting it to zero let's go ahead and say that we want to say realm controller dot instance dot get position so that will update it to whatever we last saved it to so if i went back into unity remember we did we did actually store the updated position we're just we just never updated it um visually so let's go ahead and save it it should or let's go ahead and run it should update visually yeah that's not that's not centered so that's good um if i were to try it again it should be eight and it should be up there again and it is so the actual incentive positions we don't care about they're moving around but everything is stored we're persisting our data so this is actually creating a data store on the device so that could be my mac that could be my android phone my nintendo switch whatever and what we want to do now is we want to sync this data so another cool feature of mongodb we want to be able to sync our data between manga to be in the cloud and manga to be locally so manga to be locally being our unity game so let's go into our web browser we do need to set a few things up so this is mongodb atlas everything they show you can be accomplished on the free tier so you don't even need to enter a credit card to sign up for an account so i do have a a cluster created i'm going to say browse collections this is my free tier cluster i don't have a database for what we're about to do so i'm going to say create database i'm going to call it tracy devs and for the collection i'm going to call it game data and i'm going to say create now if i scroll down i have my database and i have my game data it's empty now we could leave it as empty but a cool a cool tip that i want to give you is let's go ahead and add some sample data for what we want our data to look like because it's going to be beneficial in the next step so i'm going to say insert document we do have an id here we're going to leave it because we're going to make some adjustments we have a score we have an x we have a y we want to change these from string so this is going to be an integer and our x and y we can't choose float inside of the collection editor here so we're going to choose double next best thing and finally because we're going to be working with sync we want to add another field called user id and this is just for this particular example yours may be different but let's go ahead and call this sample so we have our primary key is going to be this id our random hash and our user id so that way we know where to sync our data to is going to be our user id so i'm going to say insert so let's make use of it let's go to the app services tab we're going to create a new app to play around with i'm going to call it tracy devs i'm going to make sure it uses my examples cluster and i'm going to say create app service all right so we have an app service now there are a few steps that we need to do to enable sync first of all we need to go to schema so inside of schema search for that database and collection we just created click it and let's say generate schema so this is where that sample document comes into play we're going to say generate schema from sampling we only have one document in there but it was able to generate it based on what we have now we do have to make some minor adjustments still but it did save us from having to type most of this in so the title should actually match your collection name so this in my case it's called game data the x is not a double so we do have access to floats in the app services so i'm going to say float for the x and the y we also need to define what are required and in our case everything is required so we're going to say required so we have id we have score we have x and y and user id doesn't really matter the order that you enter them in as long as you've added them and what i'm going to do is i'm going to scroll up and i'm going to say save but i'm going to add a comma so that way it doesn't yell at me for an error so i'm going to hit save it's not deployed until i hit review and deploy draft so i'm going to click it scroll down to hit deploy so it's deployed that's step one of our app services complete so i'm going to click on authentication now so to keep this app simple and easy to follow we're not going to be worrying about username and password auth or oauth or jwt we're going to use anonymous authentication which is fine it's just going to create a new session every time you start your game unless as long as you haven't cleared the previous session so i'm going to say edit i'm going to say enabled and i'm going to deploy it when given the option and realistically i mean i guess it depends on your game but realistically you probably wouldn't use this as your option in the game the code wise the code itself in your game is going to be not much different it's just it's just a little easier to discuss through so that's enabled we have authentication let's go to device sync this is we're going to enable sync i'm going to be using partition based sync which will partition based on a particular field in this case the user id but you do have flexible sync as well and you should definitely review the documentation to see which is best for you i'm going to scroll down i'm going to say examples as my cluster the partition key is going to be my user id and i'm going to say that users should be able to read and write only their own data not everyone else's and it's going to create a rule for me so i'm going to say enable sync i'm going to say review and deploy the draft and before we go back into our code there's going to be one more thing that we look at so we're going to look at the realm sdks i'm going to click on realm object models i'm going to click on c sharp so it's going to give us a new object to work with and you'll notice that it looks fairly similar to what we've already created but there are some differences so for example our primary key is now an object id it is mapped to something so we're actually defining what it's mapped to because when we're working with our local data properties and we're worrying about our remote data properties we need to be able to link the two together and they don't need to be named the same thing as long as you've defined the mapping reference and case sensitivity does matter so i'm going to copy it i'm going to go back into visual studio code i'm going to go to my game data model and i'm going to i'm going to paste it in now just as long as you pay attention to game data model renaming it as as such so i'm going to save it um we do need to make a few adjustments here so we're going to go into the realm controller and we need to actually connect and we need to authenticate and then after we authenticate we need to either do a bi-directional sync or actually go into our application so we're going to add a few more variables here and we're going to we're going to import one thing we're going to say using realms.sync we're going to say private we're going to say app is going to be realm app we're going to say private user it's going to be realm user and we're also going to say one more thing we're going to say serialized field we're going to say private we're going to say string realm app id so this tells us which realm app in the cloud or which app in the cloud is going to be what we're working with so which app configuration so let's go ahead and go back into our web browser let's copy that id scroll to the top of your app services it's right here on the left click the copy button it's not what you think it is it's not just tracy devs so i'm going to go back into my code i'm going to paste it in see it's a little different so let's let's get down to business here let's make some changes here so first off we do need to attempt to log into our application and this is going to be an asynchronous event so when you do need to make this an asynchronous function what we're going to say is is the following we're going to say realm app equals app.create we're going to say new app configuration and we're going to pass in the realm app id perfect next up we want to see if we've already attempted to log in or not because if we've already logged in and our session is still valid there's no sense slowing us down and logging in again so we're going to say if realm app dot current user equals null so we're not logged in then we're going to do something otherwise we can copy a lot of what we've already done here so if we're copying what we've already done we already have a logged in user we're going to say realm user equals and we're going to say realmap dot current user we do need to change something on line 27 though because we are working with sync so the git instance is still the same but we now have a parameter here so we're going to say new partition sync configuration because we're using partition sync we're going to say realm user dot id so that's the partition key and for our user that we're going to use for our sync we're just going to say realm user so remember user id is actually our realm user id so that's what we're going to use now if we haven't logged in yet what we're going to say is we're going to say realm user equals await so this is asynchronous login we're going to say realmap.log in async now we're going to say credentials.anonymous if we were using email password login oauth jwt the credentials would be slightly different but we're going to use anonymous here next up we're going to say realm equals await realm dot get instance async so this is an asynchronous initialization of our realm because it's we're logging in we're making sure everything's good we will copy everything from our other git instance statement so our partition sync configuration and we'll pass it in so that's good so now we have off and set up for our remote realm so we actually have sync capabilities as of now but we need to make some adjustments so if i scroll down to the get or create game data our primary keys are not strings anymore they're game objects and we're doing things a little different so before i start changing this let's go to make an import here we're going gonna say using system dot link so link being what microsoft offers for for querying so we're it's gonna give us an api to work with so i'm gonna scroll back down to get or create game data i'm gonna make some changes here so instead of realm.find i'm going to say realm.all and this is going to be gamedata model again and we're going to say dot so this is where we enter our query we're going to say i don't know d for data doesn't really matter and we're going to say d dot user id equals we're going to say realm user dot id and so as long as the user id matches the realm user id then it's gonna it's gonna return data to us and we're also gonna say because we don't want all we just want one there should only ever be one in real realistically we're going to say first or default because we're working with user ids now we're we're no longer working with this id so we're going to say user id equals and we're going to say realm user dot id so just minor change there now there's going to be one more thing and this this may not occur in your game but i i'm telling you why we're going to consider it so in most games there are a login screen you log into the game it shows up a loading bar while it logs in and once you're logged in you can play the game because we're not showing a loading bar unity awake events they happen in parallel so we may try to render stuff on the screen before we've actually logged in and we don't want that we want to we want to be sure that realm is ready and the easiest way to do that is with a login screen but because we're not doing that we can we can actually do something a little hacky so i'm going to create another method i'm going to say public and i'm going to say bool is realm ready so we're just going to check to see if realm is ready and then if it is great we're going to use it but again this is hacky there's other ways to do this ideally you will have some kind of log in screen so i'm going to say return and i'm going to say realm not equal to null so if it's not equal to null it'll be ready it's true otherwise it's false so let's make some adjustments here so let's go to our game controller let's wrap this in our is realm ready so if realm controller dot instance dot is realm ready then let's go ahead and try to use it so that way we don't get errors because worst case scenario it'll just say score zero let's copy this and add it elsewhere so we know we're in the player.cs file we're using it in here so let's go ahead and and add it there it's basically everywhere where we're trying to use our realm and then finally down here and i think that covers everything of where we're trying to access realm so if we save it and cross our fingers everything should work great now so let's go back into our game and we're getting an error somewhere so on line 26 of the realm controller so let's go back so we have a missing semicolon let's go ahead and add it in and let's go back into unity i'm going to hit play and it's likely going to throw an error at you and i'll explain what that means yeah so it did throw an error and it says score zero so the error i'll call it out here so that the error is actually invalid schema change because our our local game schema in the game data model does not match what we have remotely and this is for safety reasons so what we're going to do just because we don't want to add any kind of migration scripts to the to the workflow i'm going to open up my terminal and i'm going to clear the local game database from my mac so i'm going to navigate in into the library folder it's going to be different depending on the platform you use i'm going to go to application support and because i have the default settings i'm looking for default company and i called it tracydev sample so i'm going to say rmrf i'm going to say tracydevs sample and i'm just going to wipe it clean so i have no local database as of now i'm going to run it and hopefully we get success all right so we still have an issue so i'm pretty sure i know what that means so remember if we look at our code our game data model the class is called game data model if i go to our web browser and i go to our schema go to game data i think i call the game data in mistake so it's not the collection name so the title is actually going to be our class name so i'm going to save it we will need to make some adjustments so i saved it reviewed draft and deploy i may need to restart sync if not great but just just take into consideration that it could could be a thing all right successful so i'm going to go back to unity let's run it with the idea that that maybe we will still run into problems um it looks like we might be good so let's go play around so i'm accumulating a score i'm gonna stop it so i have score three i'm right there it may collide when i start it up again but let's see it still there all good let's go into our mongodb let's go to atlas here let's click on browse collections let's scroll down to tracy devs game data and there you go you have a record here that was created from our local game now if i run it let's go and see what else we can do here i'm going to click run i think we have three as our score perfect it's still running i'm going to go back to my web browser i'm going to make an edit on this document i'm going to change the score to 30 and i'm going to say update it's updated there if i go back into my game it already synced for us so we have two-way sync so not bad so i do want to do a recap i know this was long this is like i said this is what we went over at the tracy developer meetup i thought it was a good idea to go back and re-record it because i didn't record it at the event itself so i regretted that so let's let's see what we did we created a few game objects a realm controller game controller we demonstrated how to move these objects around how to include physics the bulk of our code was actually with our data persistence so rel so we did create a data model in this particular example this this model um is linked up based on fields to our remote uh mongodb atlas collection and the fields that we would see in our documents the realm controller uh we're authenticating with anonymous authentication here uh we are asynchronously getting our um our instance with a partition sync configuration uh we have our very basic classes for for or not our classes our methods for creating data or getting if it exists um and really the the sync and the data stuff happens in the background with this is an object oriented database so we work with our objects as they are with the exception of the right block but other than that you get to you to work with unity in its entirety and then just kind of treat realm and data as an afterthought once you start creating all these helper methods and stuff so not bad once again i am the tracy developer meetup organizer in tracy california i encourage everyone it doesn't doesn't matter your age this is a family-friendly group i encourage everyone to come and participate uh i am also a developer advocate at mongodb hence why we chose to uh see some stuff on mongodb and unity but everyone can get involved it's a lot of fun unity is a lot of fun and it's a great way to get into game game development or just development in general if this is your first avenue in the development because it takes a more funner approach to things and it makes learning a little bit more fun so if you like this video hit that like button subscribe to the youtube channel drop a comment let me know your thoughts until next time everyone have a great rest of your day
Info
Channel: The Polyglot Developer
Views: 2,374
Rating: undefined out of 5
Keywords: tracydevs, unity, gamedev, mongodb, realm, atlas, csharp, dotnet, meetup, event, nic raboy
Id: tHt9QF9AWsQ
Channel Id: undefined
Length: 67min 13sec (4033 seconds)
Published: Wed Aug 31 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.