I started learning game development from Jonathan Weinberger back at the beginning of the summer in 2020. I started on Udemy and then joined GameDevHQ. The Galaxy Shooter game has been with me since the beginning. I frequently revisit it to test out new things. Sometimes I break it, but that too is probably a good learning experience. The game is currently broken for me. I’ll be fixing it but, the enemy's spawning is very messed up. My player gets damaged without anything appearing on screen. This happened when I upgraded my project to Unity 2020. Anyway, I can still show you how to update to the new Input System. Since it really doesn’t need enemies for me to demonstrate.
Installation and Initial Setup
First Install the Input System from the Package Manager.
Restart the Unity Editor once you’ve installed the package. It’ll restart and prompt yout to approve the switch to the new Input System.
Then, in the project window, create an Input Actions Asset. Mine was at the very bottom of the context menu when I right-clicked in the project window.
On your Input Action Asset (IAA), in the inspector, click “Generate C# Class” and then Apply. This will create a script above your IAA.
Button Setup and Assignments
Click on your IAA to open it’s settings menu.
First add an ‘Action Map’ and call it something that makes sense like ‘Gameplay’. Then you’ll want to create an action for each input function like Move, Jump, Shoot, etc…
For the Galaxy Shooter we have the basic Move and Shoot, but also some Auxiliary features like the Thrusters, Powerup Magnet, etc….
On the right, in the Properties, under Action Type choose ‘Value’ and for Control Type choose ‘Vector 2’. I’ll be using a Unity Event to pass in the existing Horizontal and Vertical variables to the new Input method.
For the Move action, we need a 2D Vector Composite Binding. So, select that from the dropdown. Then you’ll want to assign the WSAD keys to the corresponding directions. A quick way to do that is to click the ‘Listen’ button and press the desired key or button.
Now create Actions for all the various abilities the player has like Shoot, Thrusters, and Magnet. For these you can set the Action Type as Button. Then use the Listen feature to assign a key.
The Game Manager features like Pausing the game, starting the next wave and restarting after Game Over will be assigned to a different Action Map but the process is the same.
Connecting The Dots
Now we’ll need to connect all the new stuff to the old stuff, delete some stuff and write new stuff.
While I was doing some experimenting and learning new stuff, I separated some functions of the Player into separate classes. So I have the Player, a Movement script, another for the Auxiliary Controls and another for the actual Auxiliary features. Then another for Power Up Abilities and another for Weapons. I basically wanted to be able to turn off individual features, and like I said, I was experimenting. I also never planned on converting the Input System but figured it would be a good challenge.
This looks like it’ll be complicated, but it’s almost all Action-based. So I will likely just need to replace a few old Input Actions with the corresponding new ones…
To get started with this I am going to create an Input Controller class and attach it to the Game Manager object. This will let me assign and hook it all up in the editor, more or less.
Next, I’ll add a Unity Event to this class that will let me pass in the horizontal and vertical inputs. That starts with adding three namespaces for this script: UnityEngine.Events(for the Event), UnitEngine.InputSystem(for the new Inputs), and System to allow us to use Actions. Then comes the event.
Now I need to get access to the event in the inspector, so we need to use it in the InputController Class. We also need a reference to the Controls class, otherwise this is pointless. The Game Manager will make a new Controls in the Awake method, then we’ll grab the necessary Action Maps in the OnEnable Method.
Will that all set, I can start working on the actual movement controls. The Action created in the Input Settings automatically created what I need in my generated Controls class. All I need to do is use the action.
So, for Move, it’s called OnMove. Within that method I will invoke the Event and will pass in the two float values that make a Vector2. You will need to subscribe the OnMove method to the actions in the Input Settings. An easy way to do that is type the actions out with the method that doesn’t yet exist and then use the IntelliSense to add the method for you. I added a Debug.Log to test this out before I proceed, but I need to hook the Player up to all this first.
Getting the Player to Move, Again…
To get the Player moving again, I am going to add it to the Input Controller Event in the Inspector.
To do that, I need the corresponding method in the Player’s Movement script. As I said before, the original GameDevHQ course did not require you to separate each feature into its own script. That was my experimenting. So with the same signature as the Event and method in the Input Controller class, I created a new OnMoveInput method. I also assigned the global variables for horizontal and vertical to the parameters the method takes in. Then the usual Debug.Log for testing.
Back in Unity, I need to create an event in the GameManager’s inspector, and then drag my Player game object into the available slot. From there I select my Movement script from the list, and then the OnMoveInput method. Now I can test.
Before I can test my new inputs. On big thing needs to be updated to the new system. The EventSystem object in your hierarchy. There will be a button prompting you to switch to the new Input System giving you the results below. The default is fine unless you want to setup gamepad or other controls. Back to the test.
The result I currently want is just a message saying “Player Move Input (0,1)” for up, ( 0,-1) for down and so on. Let’s see what happens…
Okay, that works as expected. Now I need to replace the old movement code with something that works with the new Input.
I’ve commented out my original movement code so you can see what I’m replacing. Rather than the two local variables for Horizontal and Vertical, I’m getting them from the global variables, which get values from the OnMove Event. I then declare a local Vector 2 and pass in those two globals. I’m still using a transform.Translate with direction multiplied by speed and Time.deltaTime. To keep the player within the screen bounds I have those defined in global variables and use Mathf.Clamp on the position. Now we test again.
Now I can delete the commented-out code and move to the next feature, getting the player to Shoot, again… Before I do that I’m going to add the arrow buttons into the move input. No code needs to be changed. I just need to add some bindings to the Move action.
Reactivating the Weapons Systems…
Since I like being able to assign things in the inspector, I’m going to need to add Unity Events for each feature to my Input Controller Class. I can shoot and reload from my Weapons script, so I’ll need separate Events for each, which don’t need any parameters. I’ll then create separate methods for shooting and reloading. Then, I’ll subscribe those methods to the corresponding Actions on the Controls.
Next, I just need to Invoke the Events from each method.
Then, in my Weapons script I need to replace this original way of shooting with something that works with the new Input.
All I had to do was take the if statement and delete the old Input code. Then I just put that into a new method that will be called from the Event.
For the Reload feature, I just need to take the ammo limit calculation, put that in Update. Then I take what’s within the original Input.GetKeyDown if statement and put that into the new OnReloadInput method.
As everyone likes to say, hop back into Unity, and assign the methods to their corresponding Events.
Now, we Test!
Okay, so the inputs work like I want. I’ve got some really weird bugs I can only assume are a result of upgrading the project to Unity 2020. They aren’t affecting the controls though. Anyway… We will just worry about the inputs. I’ll continue this process in the next article.