Unity New Input System: Mobile Inputs
UI Setup
Adding Mobile Inputs using the new Input System is pretty straightforward. Here I have added a Canvas with 3 Images for the controls (Joystick, A & B Button) along with a slider for the jump power bar.
Depending on what version of Unity you are using, you may need the EventSystem’s Standalone Input Module with the new UI Input Module.
On-Screen Stick
On the Joystick Image, we are going to add the On-Screen Stick script component and set the control path to Stick(Joystick). This will have the Input System recognize it as a joystick input . The Movement range determines the max distance it can move in all directions.
On-Screen Button
For the Button Images, we will add an On-Screen Button Script component and set the Control Path. The Control Path defines which virtual input the on-screen button will simulate.
- A UI Button = Spacebar (keyboard)
- B UI Button = X (keyboard)
Input Action Asset
In the Input Action Asset, we can create an Action Map (Mobile or UI) that will contain the actions for these UI inputs.
JoyStick Action
The Move Action will be a Vector2 value and the binding will be a Stick(Joystick).
Button Actions
For the Buttons, they will both be Button Action Types with the following bindings:
- A Button — Jump — Spacebar
- B Button — Power — X Key
Script
Create a script that will be attached to the game object you want to control using the UI inputs
Connecting the game object script to the Input Action Asset will require:
- UnityEngine.InputSystem namespace
- Reference an instance of the Input Action Asset
- Enable the Action Map (Mobile)
- Subscribe/Subscribe to the necessary Event Triggers
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;
using System.Collections;
public class PlayerController : MonoBehaviour
{
PlayerInputActions _input;
}
private void Awake()
{
_input = new PlayerInputActions();
_rb = GetComponent<Rigidbody>();
}
private void OnEnable()
{
_input.Mobile.Enable();
_input.Mobile.Jump.performed += Mobile_Jump_performed;
_input.Mobile.PowerJump.started += Mobile_PowerJump_started;
_input.Mobile.PowerJump.canceled += Mobile_PowerJump_canceled;
}
private void OnDisable()
{
_input.Mobile.Jump.performed -= Mobile_Jump_performed;
_input.Mobile.PowerJump.started -= Mobile_PowerJump_started;
_input.Mobile.PowerJump.canceled -= Mobile_PowerJump_canceled;
}
JoyStick Movement
The JoyStick is a Vector2 value, we will want to read it in Update using the ReadValue property and store it in a global variable so we can use it in Fixed Update since we are applying it to the Rigidbody.
private void Update()
{
if (_input.Mobile.enabled)
{
//Input for Player Action Map
_move = _input.Mobile.Move.ReadValue<Vector2>();
}
}
private void FixedUpdate()
{
if (_input.Mobile.enabled)
{
_rb.AddForce(new Vector3(_move.x, 0, _move.y) * _speed, ForceMode.Force);
}
}
Jump
We already created and subscribed to the Jump performed Action that is triggered when the A Button is pressed. When this event occurs we can run add a force to the the Rigidbody to make the game object shoot up.
private void Mobile_Jump_performed(InputAction.CallbackContext context)
{
if (_isGrounded)
{
_rb.AddForce(Vector3.up * _jumpForce, ForceMode.Impulse);
}
}
Remember the On-Screen Button Script component is virtually representing the Spacebar, which is the binding for the Jump action in the Action Map.
Power Jump
When the UI B Button is initially pressed it will trigger the PowerJump started event. This will set a bool that tracks when this event has started and ended.
In Update, when this bool is true and the game object is touching the ground, we increase the value of the slider and we clamp it between the slider normalized value of 0 & 1.
private void Mobile_PowerJump_started(InputAction.CallbackContext context)
{
_buttonHeld = true;
}
private void Update()
{
if (_buttonHeld && _isGrounded)
{
_jumpMeter.value += Time.deltaTime;
Mathf.Clamp(_jumpMeter.value, 0, 1);
}
}
When the user lets go of the UI B Button, the PowerJump canceled event is triggered. We will want to set the buttonHeld bool to false and apply the JumpForce to the Rigidbody using the jumpPowerForce float value and multiplying it by the current value of the jumpMeter which will convert it into a percentage of the jumpPowerForce.
private void Mobile_PowerJump_canceled(InputAction.CallbackContext context)
{
_buttonHeld = false;
if (_isGrounded)
{
_rb.AddForce(Vector3.up * (_jumpPowerForce * _jumpMeter.value), ForceMode.Impulse);
}
StartCoroutine(JumpMeterCoolDown());
}
Lastly, aCoolDown routine is called to drain the JumpMeter back to 0.
IEnumerator JumpMeterCoolDown()
{
while(_jumpMeter.value > 0)
{
_jumpMeter.value -= Time.deltaTime;
yield return null;
}
_jumpMeter.value = 0;
}
Conclusion
The On-Screen Stick and On-Screen Button components allow you to create UI-based input controls for touchscreen or UI interactions in Unity using the New Input System. By using On-Screen Stick and On-Screen Button components:
- You can create responsive and intuitive UI controls for touch devices.
- You avoid needing custom UI event handling, as the New Input System handles input binding automatically.
- It offers an easy method to create virtual gamepad functionality for mobile and cross-platform games.