October 26, 2020
Input Action Assets
Unity
Title:
Unity Input System | How to Use Input Action Assets
By:
Infallible Code
Youtube – Tutorial
Description:
One of the better tutorials covering all the basics of utilizing Unity’s new Input Action Asset for their new input system.
Tutorial – Part 1 – Reference by String
Initially there are already some issues since they are using an older version of the new Unity input system. GetActionMap and GetAction are no longer methods associated with the InputActionAsset object and the InputActionMap object. To get around this I just used the FindActionMap and FindAction methods and they appeared to work fine here.
There are to callbacks tied to the movement action we created: movement.performed and movement.canceled. According to the Unity documentation, performed means “An Interaction with the Action has been completed” and canceled means “An Interaction with the Action has been canceled”. Then there is a method named OnMovementChanged which reads the current context input from the Vector2 input and just assigns it to a Vector3 used for movement. Since this method subscribes to both movement.performed and movement.canceled, my understanding is that the OnMovementChanged method is then called with performed when an input is given (to start moving the player) and then OnMovementChanged method is called again through canceled when the player lets go of the input (so the system knows to stop the player or at least to assign a zero vector value).
The action map and actions are referenced here through strings. These strings are the names given to them in the input master you create initially. Also the inputs created for the Movement action they created use a 2D Vector Composite.
Tutorial – Part 2 – Reference Hard Typed Generated Script
After noting that the action map and actions must be referenced through strings in the initial project, they mention that there is a way to replace the string accessors with strongly typed solutions. They also mention to do this they would encapsulate the logic in a few methods and break them off into their own class, but this is where they introduce the Input Action Importer which can do that for you using the Input Action Asset you have created.
When selecting the Input Action Asset, there is a “Generate C# Class” option. This creates an “encapsulation of your Input Action Asset complete with strongly typed accessors for all of your custom made action maps and input actions.” When creating this, you are also given some options to define where the file would be saved, what it is named, and what namespace it should live in. Leaving these blank provides a default option. The older version also had check boxes for generating events and interfaces, but those do not appear in the newer version I am using.
Looking through the generated class, we can identify in the lines here where the strongly typed accessors have been created:
m_UnityBasicMovement = asset.FindActionMap(“UnityBasicMovement”, throwIfNotFound: true);
m_UnityBasicMovement_Movement = m_UnityBasicMovement.FindAction(“Movement”, throwIfNotFound: true);
Here…
UnityBasicMovement = name of the action map
Movement = name of the action (found within the UnityBasicMovement action map)
This then allows you to tie your actions into the Input Action Asset through an approach as follows:
movement = playerControls.UnityBasicMovement.Movement;
Here…
movement = an InputAction object
playerControls = reference to the generated C# script object from the Input Action Asset
UnityBasicMovement = name of the action map where the action is located
Movement = name of the action
This entire line of references are all now hard typed and help reduce errors.
I then ran into an issue I faced in another tutorial using an older version of this input system. They had a serialized field to drop a reference to the generated class into in Unity’s inspector, but that is not an option with the new system. To rectify this you just need to create a new instance of that generated class to connect all your actions to.
Tutorial – Part 3 – Use Generated Interface
Here they use the interface created by the generated class because they selected the “Create Interface” option. I see this interface structure is also present in the class I am working with so it appears that is just added by default now. This is important because the generated class also creates a struct with in it that holds a method that requires this interface as a parameter.
This method is named SetCallbacks. It takes in the generated interface (named I[Name of Action Map]Actions) and that parameter is named instance. It then checks if the wrapper.callbackinterface object has been set yet and if so, it unsubscribes all of its OnMovement methods from the action’s event (in this case, the Movement action). It then sets that wrapper.callbackinterface to the current instance for future reference, and adds all the current instance’s OnMovement methods to the Movement action (again, this is the started, performed, and canceled events). All in all this method handles unsubscribing everything from a previous instance (if there is one) and then subscribes all of the new instances methods (or just adds them if it is the first instance). They word it as “this method registers the instance of IGameplayActions to the Movement InputAction’s events: started, performed, and canceled.”
After making the player input script with all our movement logic implement this created interface, this means all of the manual method registering to events could be replaced with simply using the SetCallbacks method passing in this as the parameter. Make sure to use the method required by this interface (which was OnMovement in this case) and place your input logic into that method. Then finally the object that should be enabled and disabled at this point should be your InputActionAsset generated class, and not an InputAction object.
To summarize…
I replaced:
movement.performed += OnMovementChanged;
movement.canceled += OnMovementChanged;
with:
playerControls.UnityBasicMovement.SetCallbacks(this);
and replaced:
private void OnEnable()
{
movement.Enable();
}
private void OnDisable()
{
movement.Disable();
}
with:
private void OnEnable()
{
playerControls.Enable();
}
private void OnDisable()
{
playerControls.Disable();
}
Summary
This tutorial was extremely helpful for showing all the ways you can access Unity’s newer input system through C#. They start with the basic string references, then move to the hard typed option created by their generated class, and finally show how the interface within the generated script can be used to implement hard typed references as well. While it is a bit more complex to get started with this setup than Unity’s original input system, this tool seems like it could be very promising for quickly setting up more involved player controllers. It also looks like it will provide good options for editing the inputs at run time.
via Blogger http://stevelilleyschool.blogspot.com/2020/10/unity-input-action-assets-intro-with.html