 So I'm going to get rid of the fret object we don't care about anymore, and we have our cube in our sphere, and we want to add some code that can control these objects. So what I'm going to do is I'm going to take the script asset, which we created earlier, I renamed it to my script. And when I did that, something to keep in mind is that the class name here has to match up, and it didn't automatically get refactored, because I don't think Unity can come into your code and edit when it's open in Visual Studio. So I had to come over here and manually rename it to my script, so the name matches. Anyway, so on my cube, I can add the my script by dragging in as a component. And same thing on the sphere. You could also just come down to add component and if you go down to, is it under scripts? Yeah, under scripts that it should be listed under scripts, because it's one of our assets. We could have done it this way. Anyway, you want to do it. So now that we have these attached scripts, what does that mean? Well, we come over here and this class has already been stubbed out with a start method and an update method. The way Unity calls our code is that our script components, which must extend the model behavior class from the Unity engine namespace, it's looking for certain method names, including start and update. There are like a dozen other special method names, but these are two of the most commonly used. The start method is called, as the name implies, when the script component is created, and it's called at the start of the first frame for which the script component exists. So script components can be created in other parts of code or when you create a game object that has a script component that counts to or when the scene loads. Those are all cases where script components are being created at the start of that frame. That's when the start methods are getting invoked. And so if in here there's the debug class that has a log method, I'm just going to say, Hi, that's our message and you need a semicolon. And so now, if we come back over to Unity and we run the game, I can save it. I don't have to save it actually, but I can hit play. We see in the console, we see high printed twice. Why is it printed twice? Well, because both our cube and our sphere have a my script component. So there's actually two instances of this class. And so start is actually called twice. The update method is another special method and it's called once per frame, not just at the start. So if I add debug dot log, that's not a good thing to do, but I'm going to do it anyway. Let's say frame. And now if I were to come back and well, actually, here's something to notice. I didn't have to restart the game because Unity will actually when I change my code and come back to Unity, it automatically detects the change in my asset and it just recompiles. There's some trickery to be aware of there where it's going to save the whole state of our of our scene of our game objects that will serialize everything, kill our C sharp code and then totally recompile the C sharp code and start the new C sharp code and then deserialize all the stuff it saved to restore the state. And there's some special concerns about cases where that can go wrong in more advanced circumstances. So we'll have to talk about that later. Serialization is also of course relevant when we talk about saving and loading games. If you want to save the user's progress to a file and load it from a file, that also involves serialization. So we'll talk about all that later. Anyway, so it's printing frame every second and you generally don't want to log things every frame because our log is being flooded with tons and tons of log messages. Anyway, so I'm going to kill the game and get rid of this log call in update. Something more interesting to do in our code is to move our game objects and we can do that here. What I'm going to do is go back to the editor and move these things around. So they're not at the origin. As we see here, so okay, neither at the origin, but what I want to do is in my code, in the start method, I want to move both objects to the origin. And the way I can do that is I want to access the transform of the game object, which this game component, the my script component is associated with. And we can do that because my script inherits from mono behavior, which inherits from component and component keeps a reference to the transform component as just the property called transform. So nothing very unobvious there. So we're accessing the transform and we can get at its current XYZ coordinates with the property local position. There's also position, which is the distinction there. We'll talk much more about later. You can arrange your game objects in hierarchies such that the transform of one object depends on the transform of its parent, which is useful because you want to attach objects together in hierarchies such that you move the parent and the child moves along with it. We'll talk much more about that later. Anyway, it's a local position is just getting the XYZ coordinates of the object itself. And okay, so that is returning a vector three, which is just a struct type, which is an XYZ value, and I'm just going to call pause as in position. Notice Visual Studio is making this dot grayed out. It's not the same blue color as the other stuff. And the reason for that is because it's hinting to us that we don't actually need it. You can just implicitly refer to properties and fields without qualifying them with this. So we'll just delete that and this code is still just the same, just less explicit. Anyway, so we now have the current position in here, we're just going to log that out. I'll just log out pause and let's just see what we have right now. Hit play. We see first high and then we see the first position. Which one is this? This is the sphere, which is located at Y of, there's the two positions as they currently exist. What we want to do is we want to set the local position and we can do so with form dot local equals some new vector three and we specify XYZ of all zeros. So now what we should see when the game starts is we should see both these things snapping to the center. Oh, you may have noticed there. Hmm. Yeah, let me stop before I stopped and restarted the game. You may have expected the code to recompile and then update the position of the objects before I restarted the game. But that wouldn't happen because when I come in here and change my code, yeah, the chain, the code all gets recompiled, but it's not going to re-trigger the start event because that only happens when the my script component is created for the first time, but it already exists. It got saved in the serialization and restored, but it's not going to call the start again update on the other hand. If I made changes to what happens in here, those changes would affect what happens as the game continues. Anyway, so now what we want to do is in the update, we want to have each frame, we want to move the, let's say the X cord of our objects just a little bit. So let's do that. And how can we do that? Well, what you might try and do is vectors have an X cord and you can just access it like that. And we want to update it 0.04 units. And because it's a float value, you have to run an F in C sharp. It requires it. Otherwise it thinks it's a double and it wouldn't like it. But the compiler still is not happy with this because, well, transform.localPosition gets us back to vector three. And a vector three is not a class type. It's a struct type. And it does have an X coordinate like this. But if we try and directly modify it here, what's happening is this expression is returning a struct, not a reference to an object. And structs are things which are directly stored as values. Like when we create this vector three variable pause up here, that is a variable which is directly storing all the data that makes up a vector three. It's not like a class variable where it's storing just a reference to some instance, it's storing the actual thing itself and all of its data directly, which is generally good for performance, particularly with smaller pieces of data like vector threes. But because we're not getting back a reference to something, there's there's no X of some variable that we're modifying. So this is not allowed. Instead what we have to do is here I'll just mark this as comment that out. We have to get the local position, just like we do it up here stored in a variable pause, and then modify its X by what did we say 0.04 f 0.04 units, every frame, and then set our transforms. Again, I cannot type because I'm reaching around my microphone. It's really awkward. And now set that to pause. Okay. So this will work. The compiler will accept this. And so let's see that in action. Come back here. And is it going to recompile and hey, there it goes. So recompiled and it's now running that new update function every frame. And there it goes off into the sunset down the X axis. So that's pretty neat. Let me refocus that and zoom out a bit. So it shows up and let's focus our camera so it actually sees it move. Oh, that's totally in the wrong spot. Isn't it? There we go. Bring it down a bit, which it's going to go off to the right here. There we go. Yeah, they snapped together into the origin and they move off together at the same rate of 0.04 units per frame. And that raised the question. So how much is a unit in unity? The convention is that a unit is generally supposed to correspond to a meter in your game world. So if you're creating a game on a human scale and like you have human characters, you should keep in mind that a unit is supposed to be about a meter. And if you break that rule, I mean, nothing's stopping you from just like scaling everything up and deciding that 10 units is a meter or something like that, whatever you want. If you break that rule, understand the physics engine in particular is tuned to assume one unit equaling the meter. And so your physics might get a little wonky if you're using the built-in physics. And if you use some other kind of scale. So you probably should just stick to one unit equaling one meter. Going back to the code, you may object that this is annoyingly complicated to have to do these three steps instead of doing it one in unity agrees with you. There is a convenience function as a method translate. On your transform, which you can just pass in. Well, the simplest version is you just pass in the amount you want to translate on the x-cord and then the y-cord and the z-cord. So this alone would be equivalent. And so we can comment that stuff out. And this is, oh, you're not right. You have to make it a float, put F. Otherwise, it thinks it's a double, but it translates expecting to float. And this is just having the same effect without the hassle. So let's just go back and verify that, save the code, come back, play. There we go, same effect. Okay, there's also a translate form as an overload where you can specify a vector, vector three. And that's the same business, which is more convenient in the case where you might happen to already have a vector. But this overload, of course, is more convenient when you don't already have a vector. So you don't have to write a new vector like that. Now, there's something actually improper about the code as we've written it. It seems to work, but we have naively assumed that our frame rate is going to be constant, which is not gonna be the case. On different systems, the game will probably run at different frame rates, and it's not necessarily gonna be constant. Like almost all modern game engines, the Unity engine will vary its frame rate, depending upon like the workload per frame and various other factors of what's going on in the system and so forth. And so from frame to frame, the amount of time that's elapsed can constantly be fluctuating. Sometimes it'll be some number of milliseconds and then next frame it'll be a different number of milliseconds. And so you wanna make sure to account for that so that when we update every frame to move our object, we want it to move at a constant rate or appear to move at a constant rate. We have to take into account the fact that the amount of time that's elapsed between frames is not always the same. And so what we can do is we can use the time class, which has a property called delta time. And what this is is, let's just print it out, actually. That log, excuse me, dblog.log. We'll print out time.delta time. Go into Unity and let's play the game. Yeah, so let's just pause here a second. So 0.01, that's implying 10 milliseconds. 0.021, that's about 21 milliseconds. So we're averaging if we look under stats as we play. It's giving us frames per second, I'm told this is not accurate and there's an obvious problem here on my system. I currently have 144 hertz for my refresh rate. And if we go under edit, project settings, let's see, qualities where it is, I believe, yeah. Come down here, by default it has v-sync on. That's what every v-blank means. You can turn off v-sync, but let's not do that. So really, it should be running actually at a pretty constant 144 frames per second. I don't know, maybe the fact that I have a g-sync monitor is also messing with this. So I'm not sure exactly what's happening here. Anyway, so that's illustrating that the time between frames is kind of going all over the place. And so if I just resume, what does this look like if I play again? Oh, okay, well now the problem is we are scaling our movement down to a tiny fraction. Is it even appearing to move? Yeah, it's moving just really, really slow. Okay, so the question is, well, how fast was it moving before? Assuming that we were moving .04 units every frame and assuming incorrectly, assuming that we're rendering at 144 frames per second consistently, then that would mean every second we were rendering this much. And this, I believe, is something a little less than six. It's like, I don't know, 5.5, let's just approximate. I think it's a bit more than that. Anyway, so that's how much we were moving per second in total, but split across 144 frames. And if you multiply a value times times dot delta time, well, if you think about it, say our game is rendering at an even 10 frames per second at a consistent 10 frames per second, well, then every frame, this is gonna be .1. And so it'll be one 10th of this each frame. But then for every 10 frames, we're gonna move the full 5.5 units. So this is how fast we're moving per second when we multiply it by the delta time. So let's just see that in action. Play here. Is that about the same speed? Yeah, it looks the same to me, but we definitely should be doing this way because this makes it frame rate independent. Whether we're running at 30 frames or 90 frames or 1,000, whatever, the movement we see should appear to be about the same. And also as the frame rate jitters up and down and fluctuates, unless our frame rate dips into something very low, like the single digits, the movement will look relatively smooth and at least consistent. Though I should note, here I'm gonna talk while I maximize on play, that makes this not full screen, but full window when I hit play here. And I can see, you probably don't see this on the video, but the movement could be smoother. It's not the smoothest motion I've ever seen in a game. This is extremely simple scene. So you would hope like it'd be totally smooth as far as the human eye could tell. And I'm running at a comfortable 144 frames. So I think what accounts for that little jitters I'm seeing is the fact that in Unity, everything is represented in floats, our transforms are all float values. They're 32-bit floating point numbers rather than 64-bit. And Unity does that for efficiency, where the games get more complicated and have a lot of objects and vertices and all that. The overhead of double precision kind of adds up. But it does mean that we get more precision errors. So I'm wondering what I'm seeing here, the little jitters. I wonder if that's because the single precision floating point calculations might be accounting for a little bit of apparent jitter there. Do be clear though, the jitter I'm seeing here on my screen at 144 Hertz is really, really small. It's nothing major at all. And if you're seeing jitter, it's probably just some artifact of the recording, which I think is only at 60 frames per second. So it's probably not accurate to what I'm seeing.