- Home /
UI Navigation with gamepad
Hi
I have a problem with the ui navigation via gamepad. It works right of the box with arrow keys, so basically I know how to set it up.
But when I try to use it with a gamepad the navigation doesn't respond very well. I have to keep the joystick pressed in a certain direction a long time. It seems to get better if I increase the sensitivity in the input settings of the project but that comes with other disadvantages like the selection jumping around on the slightest move of the joystick. I'd like to keep that untouched for now.
I don't really know what's going on and I hope somebody can help me here. I've searched for a solution in unity answers and on google but I couldn't find anything. The gamepad I'm using is a XBox 360 wired windows gamepad, so nothing exotic.
EDIT: It also seems to help if I lower the repeat delay in the eventsystem in the scene. But obviously that's also something I don't want to touch to solve this problem.
EDIT2: Changing the navigation to explicit doesn't solve it either.
I also have this problem, when I navigate my menu with the d-pad everything works fine, but when I try to navigate with the analog stick it is very unresponsive and sluggish.
did the original poster find a solution to this problem yet?
Answer by mccameron · Nov 04, 2015 at 09:45 PM
Hi, I had this problem as well and after messing around a bit with the Input Manager I found a solution.
for the Horizontal and Vertical entries in your Input Manager that you are using in your event system, set the following values(not sure if all are these are necessary but this is what worked for me): Gravity: 10, Dead: 0.9, Sensitivity 4, and uncheck snap
for your standalone input module set input actions for second to 4 and repeat delay to 0.25
I'm pretty sure the most important of the settings above is to have Dead: 0.9, it seems that when the deadzone is too small the standalone input module doesn't work too well.
If you are using Input Manager for gameplay with the analog sticks make sure these UI settings are a different horizontal/vertical entry in the Input Manager so they don't conflict with your gameplay control.
Answer by odomobo · Nov 05, 2015 at 01:07 PM
I also have this problem. It is a bug in unity 5. The buggy code is open-source, so I wrote a fix for it. The fix only works for 5.2.2f1.
Mccameron's solution is the easiest fix by far, but the bug can still sometimes happen.
Installing my fix is a pain and requires a bit of technical knowhow:
Download the updated source from https://bitbucket.org/odomobo/ui/get/5.2.zip . You can also view my commit on bitbucket, if you desire.
Compile the source code in MonoDevelop/Visual Studio, as per the README.md file.
Install the compiled DLLs by copying them to the correct directory (Unity\Editor\Data\UnityExtensions\Unity\GUISystem in Windows, Unity.app/Contents/UnityExtensions/Unity/GUISystem in OSX)
If you don't want to go through all of those steps, you can download the DLLs I compiled, and you can skip straight to step 3 as per above: https://www.dropbox.com/s/utn4cqpsnak4ipv/GUISystem_5.2.2f1.zip?dl=0
I hope unity incorporates my fix into their next release.
Answer by s_guy · Jan 15, 2016 at 12:04 AM
The issue is fixed for me in 3.3.1p2 You may have to download it manually if it's not showing up in your Editor's update option yet.
Answer by Salim · Mar 22, 2016 at 04:38 PM
For those using an older version of Unity (like me), here's another fix:
First make unique inputs for the gamepad in the input manager; they need to be named different, like "VerticalDpad" and "HorizontalDpad".
Create a new script that you will attach to your EventSystem object. The script will handle the selection of buttons only if gamepad inputs are used. It should look like this:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class EventSystemXboxDPadInputs : MonoBehaviour
{
private GameObject currentButton;
private AxisEventData currentAxis;
//timer
private float timeBetweenInputs = 0.15f; //in seconds
private float timer = 0;
void Update()
{
if(timer == 0)
{
currentAxis = new AxisEventData (EventSystem.current);
currentButton = EventSystem.current.currentSelectedGameObject;
if (Input.GetAxis("VerticalDpad") > 0) // move up
{
currentAxis.moveDir = MoveDirection.Up;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
timer = timeBetweenInputs;
}
else if (Input.GetAxis("VerticalDpad") < 0) // move down
{
currentAxis.moveDir = MoveDirection.Down;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
timer = timeBetweenInputs;
}
else if (Input.GetAxis("HorizontalDpad") > 0) // move right
{
currentAxis.moveDir = MoveDirection.Right;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
timer = timeBetweenInputs;
}
else if (Input.GetAxis("HorizontalDpad") < 0) // move left
{
currentAxis.moveDir = MoveDirection.Left;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
timer = timeBetweenInputs;
}
}
//timer counting down
if(timer > 0){timer -= Time.deltaTime;}else{timer = 0;}
}
}
You can change the time between input by changing the value of "timeBetweenInputs".
That's a great solution! If I may, I made a few improvements.
Chiefly, using fixedDeltaTime ins$$anonymous$$d of deltaTime will allow this to work when your Timescale is set to 0 (as it may be on a pause menu).
using UnityEngine;
using UnityEngine.EventSystems;
public class CustomEventsInput : $$anonymous$$onoBehaviour
{
private GameObject currentButton;
private AxisEventData currentAxis;
//timer
public float timeBetweenInputs = 0.15f; //in seconds
[Range(0,1)]
public float deadZone = 0.15f;
private float timer = 0;
void Update()
{
if(timer <= 0)
{
currentAxis = new AxisEventData (EventSystem.current);
currentButton = EventSystem.current.currentSelectedGameObject;
if (Input.GetAxis("Gamepad Left Vertical") > deadZone) // move up
{
currentAxis.moveDir = $$anonymous$$oveDirection.Up;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
}
else if (Input.GetAxis("Gamepad Left Vertical") < -deadZone) // move down
{
currentAxis.moveDir = $$anonymous$$oveDirection.Down;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
}
else if (Input.GetAxis("Gamepad Left Horizontal") > deadZone) // move right
{
currentAxis.moveDir = $$anonymous$$oveDirection.Right;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
}
else if (Input.GetAxis("Gamepad Left Horizontal") < -deadZone) // move left
{
currentAxis.moveDir = $$anonymous$$oveDirection.Left;
ExecuteEvents.Execute(currentButton, currentAxis, ExecuteEvents.moveHandler);
}
timer = timeBetweenInputs;
}
//timer counting down
timer -= Time.fixedDeltaTime;
}
}
Thank you jtheSpaceC! Good point; you usually use menus when the game is paused.
This worked Fantastic! Ive been stuck with this for a month and finally found a solution! Thanks!
Answer by astracat111 · May 03, 2019 at 09:45 PM
Using Unity 2018 with InControl, so I can't exactly use the fix above, but it's a matter of setting the RepeatDelay in the Input Manager juuust right.
Really? How exact does it have to be? This script he gave us workied for me in a "shop menu" in the game. But im still having this issue in the start menu of the game. I only have 3 options. "New Game, Load Game, Exit". WHen I press down it skip the Load Game button and go all the way down to Exit :/ So anoyoing...
Your answer
![](https://koobas.hobune.stream/wayback/20220612040742im_/https://answers.unity.com/themes/thub/images/avi.jpg)