# Creating a Custom Input Manager

The Ultimate Radial Menu Input Manager contains all the basic input types and functions. However, sometimes in your project you may have a very specific way that you want the Ultimate Radial Menu to receive input. You can get the radial menu to work with your custom input very easily! Let's see how.

## Creating Your Input Manager

To create your custom input manager, create a new script inside your project and name it. For this example, we will create a script with the name: CustomInputManager. After the script is created, change it's inherited type to UltimateRadialMenuInputManager.

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```csharp
using UnityEngine;

public class CustomInputManager : UltimateRadialMenuInputManager
{
    
}
```

{% endcode %}

After creating your script, now you will want to choose which of the input types you want to override. For this example we will create an override for the Controller Input of the input manager, but you can override any of the methods listed [here](/assets/ultimateradialmenu/documentation/ultimateradialmenuinputmanager.md#virtual-methods).

First, let's override the ControllerInput function.

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```csharp
using UnityEngine;

public class CustomInputManager : UltimateRadialMenuInputManager
{
    // Override the controller input.
    public override void ControllerInput ( ref bool enableMenu, ref bool disableMenu, ref Vector2 input, ref float distance, ref bool inputDown, ref bool inputUp, int radialMenuIndex )
    {
        
    }
}
```

{% endcode %}

At first glance, the function and parameters might seem confusing! Don't worry though! The code is very simple and straight forward. Let's go over the parameters and see what each of them is for.

<table data-full-width="true"><thead><tr><th width="205">Parameter</th><th>Purpose</th></tr></thead><tbody><tr><td>enableMenu</td><td>This parameter allows you tell the input manager if you want the radial menu to be enabled on this frame or not. For instance, if you want the menu to be enabled when the user presses the left trigger of the controller, then you can check when it has been pressed and set enableMenu to true to enable the radial menu.</td></tr><tr><td>disableMenu</td><td>The exact opposite of the enableMenu parameter. Determines if you want the radial menu disabled this frame or not.</td></tr><tr><td>input</td><td>The input value that should be processed. In this example we will use the controller input, but you will set this to what ever input you are needing to interact with the radial menu.</td></tr><tr><td>distance</td><td>The distance of the input from the radial menu.</td></tr><tr><td>inputDown</td><td>The state of the interact input button being pressed down this frame.</td></tr><tr><td>inputUp</td><td>The state of the interact input button being released this frame.</td></tr><tr><td>radialMenuIndex</td><td>The index of the radial menu in the UltimateRadialMenuInformations list on the input manager. Useful for checking specifics of the radial menu being interacted with.</td></tr></tbody></table>

All changes to these parameters (excluding the radialMenuIndex value) will be stored and sent back to the Update function for processing and sending to the radial menus in the scene.

## Processing Custom Input Logic

Now that we have our script created and our override void ready for some custom logic, let's add some code to get the radial menu processing the input that we are looking for.

For this example, we will adjust the controller input so that it will not reset back to center when the controller joystick has been released. In this way the radial menu will continue to process the last known input direction of the joystick even when the joystick has been released. So the first thing to do would be to create a variable that can store the last known input value so that it can be sent to the input manager.

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```csharp
using UnityEngine;

public class CustomInputManager : UltimateRadialMenuInputManager
{
	// This variable will store the controller input value.
	Vector2 controllerInputValue = Vector2.zero;


	// Override the controller input.
	public override void ControllerInput ( ref bool enableMenu, ref bool disableMenu, ref Vector2 input, ref float distance, ref bool inputDown, ref bool inputUp, int radialMenuIndex )
	{
		// Store a boolean to check if the input from the mouse & keyboard has been caught.
		bool inputModifiedThisFrame = false;

		// If any of the bool variables have been modified, then the mouse and keyboard is still the active input, so set the bool to true.
		if( enableMenu || disableMenu || inputDown || inputUp )
			inputModifiedThisFrame = true;

		if( !UltimateRadialMenuInformations[ radialMenuIndex ].radialMenu.IsEnabled && controllerInputValue != Vector2.zero )
			controllerInputValue = Vector2.zero;

#if ENABLE_INPUT_SYSTEM
		// Store the gamepad from the input system.
		Gamepad gamepad = InputSystem.GetDevice<Gamepad>();

		// If the gamepad is null, then just return.
		if( gamepad == null )
			return;

		// Store the input data of the stick determined by the user.
		Vector2 currentControllerInputValue = joystick == Joysticks.Left ? gamepad.leftStick.ReadValue() : gamepad.rightStick.ReadValue();
		if( Vector2.Distance( Vector2.zero, currentControllerInputValue ) >= UltimateRadialMenuInformations[ radialMenuIndex ].radialMenu.minRange )
			controllerInputValue = currentControllerInputValue;

		// Check the controller buttons for interacting.
		CheckControllerButtons( gamepad, interactButtons, ref inputDown, ref inputUp );

		// Check the controller buttons for enabling/disabling the menu if the user wants that.
		if( enableMenuSetting != EnableMenuSetting.Manual )
			CheckControllerButtons( gamepad, enableButtons, ref enableMenu, ref disableMenu );
#else
		Vector2 currentControllerInputValue = new Vector2( Input.GetAxis( horizontalAxisController ), Input.GetAxis( verticalAxisController ) );

		if( Vector2.Distance( Vector2.zero, currentControllerInputValue ) >= UltimateRadialMenuInformations[ radialMenuIndex ].radialMenu.minRange )
			controllerInputValue = currentControllerInputValue;

		// If the activation action is set to being the press of a button on the controller...
		if( Input.GetButtonDown( interactButtonController ) )
			inputDown = true;
		else if( Input.GetButtonUp( interactButtonController ) )
			inputUp = true;

		// If the user has a enable key assigned...
		if( enableMenuSetting != EnableMenuSetting.Manual && enableButtonController != string.Empty )
		{
			// Check for the Enable and Disable button keys and set the enable or disable booleans accordingly.
			if( Input.GetButtonDown( enableButtonController ) )
				enableMenu = true;
			else if( Input.GetButtonUp( enableButtonController ) )
				disableMenu = true;
		}
#endif
		// If the input had not been modified from the Mouse & Keyboard function before this one, then check any of the bool variables. If they have changed, set the current input device to controller for reference.
		if( !inputModifiedThisFrame && ( enableMenu || disableMenu || inputDown || inputUp ) )
			CurrentInputDevice = InputDevice.Controller;

		// If the controller input is not zero...
		if( controllerInputValue != Vector2.zero )
		{
			// Set the current input device for reference.
			CurrentInputDevice = InputDevice.Controller;

			// If the user wants to invert the horizontal axis, then multiply by -1.
			if( invertHorizontal )
				controllerInputValue.x *= -1;

			// If the user wants to invert the vertical axis, then do that here.
			if( invertVertical )
				controllerInputValue.y *= -1;

			// Set the input to what was calculated.
			input = controllerInputValue;

			// Since this is a controller, we want to make sure that our input distance feels right, so here we will temporarily store the distance before modification.
			float tempDist = Vector2.Distance( Vector2.zero, controllerInputValue );

			// If the temporary distance is greater than the minimum range, then the distance doesn't matter. All we want to send to the radial menu is that it is perfectly in range, so make the distance exactly in the middle of the min and max.
			if( tempDist >= UltimateRadialMenuInformations[ radialMenuIndex ].radialMenu.minRange )
				distance = Mathf.Lerp( UltimateRadialMenuInformations[ radialMenuIndex ].radialMenu.CalculatedMinRange, UltimateRadialMenuInformations[ radialMenuIndex ].radialMenu.CalculatedMaxRange, 0.5f );
		}
	}
}
```

{% endcode %}

After saving the above script, simply replace the current Ultimate Radial Menu Input Manager that is located on the EventSystem object in your scene with this one. Then enable the Controller Input option and you should see the new input logic being used.

<figure><img src="/files/DUWq3s6myW7rqEuuWP9p" alt=""><figcaption><p>EventSystem object Inspector</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tankandhealerstudio.com/assets/ultimateradialmenu/tips-and-tricks/creating-a-custom-input-manager.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
