We are now able to run our State logic
but of course we don't still have any. Before we go ahead and start adding some logic
though, we first need to create our Player Input. The reason why is that we're
using the new Input System, so we'll need to create
the Player Input ourselves. Thankfully, it's quite simple to do that. Lets start by creating a folder in our "Assets"
folder, to which I'll name "InputActions". Inside, we'll create 2 new folders, one inside of the other: "Characters" and then "Player". Inside the "Player" folder, we'll create its Input
Actions by right clicking in the Project Window, going to "Create" and "Input
Actions" at the very bottom. I'll name them "PlayerInputActions". When you're done doing that,
double click on the asset file to open up the Input Actions Window
or press on the "Edit asset" button. I'll dock the Window right next to the Game tab. Now, if you never used the new Input System,
you likely have no idea what is what. While I won't do a deep dive
into what each option does, I'll at least try to explain what
we need to know for this tutorial. The first thing we want to create
is what Unity calls an "Action Map". This is nothing more than a group of Inputs. You can divide your Inputs in whatever way you desire, but we'll create a "Player Action Map"
that groups every Player Input. So, lets go ahead and press on the plus
(+) icon, which adds a new Action Map. I'll name it "Player". When we select an Action Map,
Unity shows us the existing Inputs, known as Actions, of that Action Map at the right side. It should come with a default Action already but
feel free to right click on it and press "Delete". Right now we'll only be needing two inputs. One is for our "Movement", which
we'll be making it be our "WASD" keys and the other one will be to toggle
between our "Walk" or "Run" States, which will be bound to the "Left Ctrl" key. To do that, press the plus (+) icon
and name the first one "Movement". Then, press it again and name
the second one "WalkToggle". Select the "Movement" Action again. At the right side we now have a "Properties"
area for the currently selected "Action". This area allows us to choose a few things, such as the type of value that we want our Input to return, what type of interaction is needed for the Input to be called and if we want to process that data,
such as Clamp the returned value. For our "Movement" Input we want it
to be constantly reading for changes so that we can get an updated
value in our "HandleInput" method. The way we do that is by setting
the "Action Type" to "Value". The "Value" type is an Action Type that
continuously tracks changes on that action. This is different from the "Button" Action Type that only tracks changes whenever we press or un-press an Input. Now, we want our "Movement" Input to return
something that we can use to move horizontally. If you've ever used the old Input System
that would be the "GetAxis" or "GetAxisRaw" of the "Horizontal" and "Vertical" axis,
in which you would then set the "Vertical" axis value to move on the "z" axis, as "x"
and "z" are our Player Horizontal Axis in 3D. So, all we need here is a "Vector2",
as it holds the 2 values we need. We can choose that returned value
type in the "Control Type" dropdown. We now have the type of Input and Value we want to receive. However, we haven't really set any key to this Action. To do that, we use "Bindings". When creating an Action, Unity already adds
a default Binding to it with no Key attached. However, we want our Movement Input to be the "WASD" keys. Currently, our Binding is just one key, so we can't do that. Thankfully, there are other Binding Types
depending on the chosen Action Type, so go ahead and right click in the
current Movement Binding and "Delete" it. Then, press on the plus (+) icon
at the right side of the Action and choose "Add 2D Vector Composite". I'll name it "Keyboard". This now allows us to bind one key for each direction. To bind a key, we need to use the "Path" dropdown. This has quite a lot of keys to choose
from and you could go ahead and go to "Keyboard" and search for the Key you want. However, we'll do something simpler and faster
and that's to "Listen" for our own Input. If we go ahead and press "Listen"
and then press "W" in our keyboard, an option saying "W [Keyboard]" should now appear. Go ahead and select that one. Our "Up" direction is now bound to the "W" key. All we need now is to do the exact
same thing for our other 3 directions, so go ahead and do just that. Just in case you didn't understand, binding
a key to a direction here means that "W", for example, will get the value
of "Up", which is "1" in the "z" axis, which of course in our "Vector2"
will be "1" in the "y" variable. If we press lets say "WD", then we'll get a value
in the "x" and in the "y" variables of the Vector2 and that value will already be normalized, as in our "Keyboard" Binding we have
the "Digital Normalized" Mode selected. That's it for our "Movement" Input,
so lets now do our "WalkToggle". In Genshin, whenever we are
Walking or Running, we can switch between both by pressing the "Ctrl" key. This Input is reading like a button, waiting
for us to press on it and nothing else. There is no reason for us to continuously track this Input value as we don't really need to use it anywhere else
besides when switching between these two States. Because of that, we'll choose the "Button" Action Type. For our Binding, we'll be "Listening"
for the "Left Control" key and choose it. We now have the necessary Inputs to start
moving so all we need to do now is to save them and somehow read them. To save these Input Actions, simply
press on the "Save Asset" button above. If you wanted every change you do to automatically save, then you would enable the "Auto-Save" at the right. I will however not do that. We now have our Inputs saved but
we still need a way to access them. If we select the Input Actions asset
file we can see in the Inspector that we have an option to "Generate a C# Class". This class is automatically generated by Unity and provides us a way to access these
Input Actions we've just created. So, feel free to enable it. Now, there are a few fields you can update but
we'll leave everything to their default values and instead just press "Apply". This should create a new C# Script
in the same folder with the same name as our Input Actions asset file,
as well as automatically generate code of our Action Maps and Actions, including
their Bindings, Properties, etc.... That's great, but we of course still need an
instance of this class to be able to use it. To do that, we'll create our own Player Input Class. So, go back to the "Player" Scripts folder. In here, create a new folder named
"Utilities", followed by "Input". Inside, we'll create a new C# Script,
to which I'll name "PlayerInput". Open it up and start by
removing the default methods. We'll leave the "MonoBehaviour"
inheritance as we'll need it later. We need a few things to start
using our Input Actions. The first is of course an instance
of our "PlayerInputActions" class. To do that, create a new "public" property of type "PlayerInputActions",
to which I'll name "InputActions". I'll give it a "private set;". I'll also create a reference for our Player
Action Map so that we can access it right away. To do that, type in "public PlayerInputActions",
which is our generated C# class, ".PlayerActions". I'll name it "PlayerActions" as
our Action Map is named "Player". The ".PlayerActions" we've added
is automatically generated by Unity and represents the struct
type of our Player Action Map. If you've named your Action Map something different, then it should be your Action Map name
with "Actions" attached to it at the end. With that done, we can start by creating
a new instance of our Input Actions. We'll do that in the "Awake" method. In here, simply type in
"InputActions = new PlayerInputActions();". Then, set our "PlayerActions = InputActions.Player;". Note that while "PlayerActions" is the
name of the Action Map struct type, "Player" is the name of the
variable of that struct type. We now have a reference for our Inputs but there's
a mistake I see some people make quite often, which is trying to read their Inputs now. While we indeed have an instance of our Player
Actions, Unity requires us to first "Enable" them. To do that, we'll use the
MonoBehaviour "OnEnable" method and also the "OnDisable" method to disable them, as we don't want them to be enabled if the
Player Game Object is no longer enabled. So, add in the "OnEnable()" method
and inside type in "InputActions.Enable();". Then, add the "OnDisable" method
and call "InputActions.Disable();". We are now able to read our Inputs. Of course, we still need to add this
class as a component of the player, but we'll also need to add a
reference to it in our "Player" script so that we can access it in our States. So, go back to our "Player" script. In here, start by creating a new "public" property of type "PlayerInput". I'll name it "Input". Make sure you type the same
property "set" as I do, but I'll most of the time make
it "private" unless we need to be able to set the value from other classes. Then, in the "Awake" method, we'll
get its reference by typing in "Input = GetComponent<PlayerInput>();". We can now add this "PlayerInput"
class as a component of our Player, but lets first add the
"RequireComponent" attribute. Above of our "Player" class, type in
"[RequireComponent(typeof(PlayerInput))]". Now, every time we add the "Player"
component to a Game Object, it will automatically add the
"PlayerInput" component with it as well. Save and go back to Unity and
select the "Player" Game Object. If Unity didn't add the "PlayerInput"
as a component automatically, add a new component of its type yourself.