 Unity has a concept of what it calls virtual axes. A virtual axis is this thing which is mapped to some kind of actual physical input, like a joystick axis, but whatever it's mapped to, when we read the value of this thing, what we get back is a value between negative one and positive one, where zero is the neutral value in between. So for example, most obviously you can have a virtual axis to the left analog stick x-axis, such that when the stick is in the middle position, that's reported to zero, when it's fully to the right, that's positive one, when it's fully to the left, that's negative one, or perhaps vice versa, whether you map right being positive or left being positive or vice versa, that's basically arbitrary, though I think usually right is positive. Anyway, because it's an analog stick, you can also get values in between. So like the user presses the stick not fully to the right, but partway in between, so they get a value that's not positive one, it's something between zero and positive one. And you might also have some sensitivity setting that governs what the mapping of stick positions along the axis to the value, what exactly that curve looks like, it's not necessarily a linear relationship, because a linear relationship doesn't necessarily make the input feel good. So that's something you might want to have configurable, also you probably want a dead zone, because analog sticks aren't perfect, and when the user releases the stick, the spring doesn't necessarily perfectly put it in the center, so you want to have a little bit of wiggle in the middle where the reported value is zero, even though if it's not perfectly centered. So that's the most obvious kind of axis, but a virtual axis in Unity can also be mapped to just arbitrarily chosen keys and buttons, such that one key or button is positive input, and the other key or button is negative. Like say, for example, if I chose right arrow on the keyboard as being positive, and left arrow as being negative, when I press down the right arrow key, then the axis would report as positive one, when I press the left arrow key, it would report as negative one. Except in this case, perhaps when I press the key, I don't want input immediately in that frame to jump from zero all the way to positive one or negative one, maybe I want it to ramp up from the neutral position. And likewise, when I release the keys, maybe instead of immediately snapping back to zero, maybe I want the transition to be gradual. And so a virtual axis in Unity, when you map it to keys and buttons, you have some settings that control that behavior. If you want the axis to immediately snap the positive one and negative one and snap back to zero, you can have that, but you can also have gradations in between. Additionally, a virtual axis can instead be mapped to mouse movements of either left and right or up and down. So like say, left could be negative and right could be positive, such that when you don't move the mouse, the axis value is reported to be zero. But when you move it to the right, it's reported as a positive value. When you move it to the left, it's reported as negative. And depending upon how fast you move that determines what the magnitude of the value is. So you move it slowly to the right, you get a small positive value, move the mouse fast to the right, you get a larger positive value, and you move it fast enough, eventually you get positive one, but then you move it faster than that and it just maxes out at positive one. So if you map a virtual axis to a mouse, do you want to be able to specify sensitivity to govern what mouse movement speeds correspond to what magnitude reported values? The higher the sensitivity, the larger the value you get for the same speed of mouse movement. So that's what a virtual axis is about. And the way you can figure this stuff is in your project under settings input. It's showing all the axes, the virtual axes configured for my project. And by default, there's always these 18 that come pre-configured in a new Unity project. We can delete any one of these, I can just select this one and hit delete and get rid of it. But I'm not going to do that. You can configure these however you like, it's up to you. Let's look at the horizontal one here. This is where I specify the name. Here I can just change it and see the change there, but I don't want to change the name, so I'll undo that. The other most important field here is the type, because that determines whether this is mapped to an actual joystick axis or mouse movement or keyboard keys and buttons. We'll stick with joystick axis here. And quite annoyingly, all the other fields you see here, whether they're relevant or not, depend upon what kind of type this is. So for joystick axis, actually, these button fields, these four here, they don't have any bearing on the joystick axis. They're only relevant if we select a key or mouse button. And then say like dead zone here, that's relevant for joystick axis, but if we were to make this a key or mouse button axis, then that field would be irrelevant. So just keep in mind that not all these fields have bearing depending upon what kind of axis we've chosen. Anyway, so having selected the joystick axis, we also care about which axis we're talking about. And x and y, that's the left stick axis of your gamepad. Third and fourth, I'm pretty sure that's the right stick. Though actually, all of this is dependent on the joystick, how the numbers of the axes get mapped to the actual gamepad differs from one kind of gamepad to the next, like it's different from PlayStation Xbox controllers. So that's kind of annoying issue that you may have to account for in your code, you'll have to like, perhaps ask the user what kind of gamepad they have, there are various different solutions people have worked out for. I should mention right now that actually this whole input system, for various reasons, people don't find it totally adequate. And sometime in 2018, they're supposed to introduce a new system. This system will be around for a long time. So you can use it, I'm sure for years to come. But it does have its issues, and they're, they're working on replacing it. This is one of those issues is handling the mapping of axes is kind of annoying. Anyway, and then this join them, that's also important, the question is, well, do you want to get input for this virtual access? Do you want to get from just one specific joystick or all of them? And it's kind of strange, because then potentially of conflicts of like, this one axis is reporting this value and this other axis is reporting a contradictory value, that all gets reconciled somehow into a single virtual access value that we can query in our code. I mean, generally, you leave it on get motion from all joysticks for single player games. And that's appropriate, because if the user has multiple gamepads plugged in, well, then it's just up to them not to use two gamepads at once. So it's just kind of their problem. Obviously, for a local multiplayer game, you would want to distinguish between different users gamepads. But for our purposes, the setting is perfectly fine. And I'll leave it up to you to read up on these other values like sensitivity and snap and play around with those values. I'll leave that up to you. Anyway, so that's one virtual access. I'm going to quickly load up this project and you'll see how these can be mapped by the user. There I've built and run my game and you get this configuration window pops up before the user actually plays. You can disable this pop up window. If you have the pro version of Unity, if you pay for the proper license, I just have the free version so I can't disable this window. And we have this input tab. And the idea is the user can come here and remap any of the virtual axes, how they like. So the idea is that if in our game, we use the virtual axes for all of our core game input, then the user can remap all this stuff through the stock menu. And you and your game don't have to create your own key binders menu or anything like that. That is the idea. People are generally not very happy with this arrangement. It's one reason they're going to introduce a new input system. Because number one, this menu kind of sucks, like you can't make this any bigger. It really sucks to use. And just most games, people expect to be able to remap their controls inside the game directly rather than from this external menu. So this is not really a satisfactory solution, particularly for like a polished professional game. Even though we don't have the new input system yet, there are ways to work around this so that you can have a key binding menu in your actual game. But for just a quick and dirty project that you don't necessarily fully polish, this is probably good enough. So I'll close the game here, go back to the project settings and input. And what you may have noticed here is that we have some virtual axes of the same name. We have this horizontal virtual axis, the one we just looked at, but then there's also this one up here. And Unity is actually perfectly cool with that. It's just that when we query the value of the horizontal virtual axis, its value is potentially influenced by multiple inputs. So looking at this horizontal virtual axis, this is bound to a key or mouse button. And I think for this type, the axis and join them, that's now irrelevant. Dead zone is irrelevant. But the fields that now matter here are the negative and positive button. And also you can define an alt negative and alt positive button, because often in key bindings for games, they give you an option of like, well, what's your primary choice for this input? And what's your secondary backup key for this input? Because sometimes people like that. But anyway, the value selected here, there's left and right and A and D. And this is where we use those key and button names, as described here in the documentation. So left means the left arrow, right means the right arrow on the keyboard, the number one in square brackets means one on the keypad, joystick one button zero would mean button zero on just joystick one, not any other joystick, etc. So when you set up these buttons, you're going to want to consult this list here in the documentation in the manual. Finally, let's actually get the values from these virtual axes in our code. And doing so is very simple, you just use the method input dot get access, and you specify the name of the virtual access as a string. So we have currently defined two horizontal virtual axes, this mapped to the x axis of the left stick on our game pads. And this one mapped to both left and right on the keyboard and A and D on the keyboard. So then potentially I could be holding down one of these buttons, but then also at the same time, holding my left stick either left or right. And then somehow they just get reconciled into a single value in the range of negative one to positive one, somehow the conflict gets resolved, but whatever it is back here in my code, I will get back a single float value, which is negative one to positive one somewhere in that range. And in the case where it's zero, well, that's neutral, that's where I don't have any input, so we don't want to do anything. But otherwise, if it's non zero, then we'll just print out what the actual horizontal x value is, we've stored the value in horizontal x here. And then we want to move our sphere, so we're going to move our sphere proportional to the input value. And it should be proportional to time, but we're also multiplying it by three here just to amplify it, because otherwise it wasn't very noticeable. So I multiply by three, the larger I make this number here, the faster the apparent movement. So let's finally play the game. So let's finally see this in action, come here, play, put focus on the window, and A and D, A is moving my sphere down, because in the code, this is the Y value of our translate. So we're moving along the y axis. So A is down, D is up, left on my keyboard is also down, right on my keyboard is also up. And if I turn on my gamepad here one second, let's see. Yeah, so now I have that on. So left on my left stick is moving down, right on my right stick is moving it up. And let's just see what happens. I'm going to hold right left on my keyboard, what happens? Huh, we'll just probably just whatever the latest input is. So like just somehow that conflict gets resolved into a single value. Again, it's probably not a real big issue. It's just up to the user not to hit too many buttons at once, right? So that's the horizontal axis in action. Let's also look here at this mouse x virtual axis, which is defined to correspond to mouse movement along its x axis. So that should be left and right movement. You can also select of course y axis movement, that we up and down third axis, that would be the scroll wheel. And then some mice I think actually there are mice with additional axes. There's some mice where you can move the mouse wheel left and right that might actually not be an axis. I don't know. I'm sure there's some some mice out there with more than three axes. Anyway, so this is just mouse movement along left and right. sensitivity has been configured to point one. That's how it came stock. I believe one is the max sensitivity value. I'd have to look at the documentation. Anyway, so our input is being dampened. We'll see what that looks like. Anyway, so that's our mouse x axis. Let's look at the code here. I'll comment this stuff out and uncomment here. And we're getting our virtual axis called mouse x storing that in a variable called mouse x. In the case that it's not zero, then we're going to print out what the value is into the log. And we're going to move our cube. And here in amplifying by eight. Same logic is just larger amplification this time. And we're moving along the x axis this time instead of the Y or Z. So let's see that in action, save the code, come back, play. And now, oops, I already went off the screen there. So kind of the funny thing here is that I don't even have to focus the window before it starts responding. In fact, it starts responding. It like it seems like a some number of mouse movement events have queued up before the game even starts responding. That's why the box is immediately warping off screen. I'll try not to move the cursor this time. I'll hit play without moving. Now it's going okay now if I start moving. Okay, yeah. Yeah, so see that's a that's a pretty decent amount of movement. Let's see how we can edit this live I assume I can I'm gonna make this point five is it suddenly much faster? Do I have to click off? What will happen? Let me lock this so it doesn't disappear. There we go. Is that changing? Oh, yeah, it's faster now. Yeah, it's definitely faster. We go all the way up to one. Come back here. I guess that's faster. Strangely, what didn't feel all that different, but now go back to point one. Come back here. Way slower. Okay. Yeah, so you can actually edit this stuff while your game is playing live. I assume just like everything else, if I make a change is it going to preserve when I quit the game? No, like everything else to get set back to the value when I hit play. Okay, so that's getting mouse input as an axis. And that's appropriate, mostly for like first person shooters and first person shooter. You don't really have a cursor visible. It's just you want to detect movements of the mouse. You don't really care about where the cursor is positioned on the screen. In fact, you want the cursor to be invisible, which is something we'll talk about in a second when we deal with cursors. Let me quickly recap here. You have some number of virtual axes. These are the ones that can predefined. We can add our own or delete the ones here, reconfigure them however we like. But each virtual axis has a name as you type here. The most important field is the one here where you specify what kind of input this virtual axis is mapped to. And then from there, which settings are relevant depends upon which type. In this case, this axis is relevant. The join num is not relevant because it's not a joystick axis. And then sensitivity, I don't I think dead zone does anything gravity doesn't do anything. But the sensitivity is relevant. I don't think snap does anything for a mouse. Invert though would flip the positive negative axes, etc.