- Home /
Control UI button through keyboard?
I have 10 buttons (like a hotbar). But I don't want to use a mouse ingame. So I need to make the buttons respond to the key-presses 0-9.
Note: I DON'T want to attach some code to the onclick event. I know how to do that. I also know how to configure the Input manager. I basically need to bind the keyboard keys to specific UI-Buttons and disable the mouse input on them.
Hotbar panel script (with the hotbar buttons as children):
void OnGUI()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
GetComponent<Transform>().FindChild("Hotbar1").... ? // show button-down transition
else if (Input.GetKeyUp(KeyCode.Alpha1))
GetComponent<Transform>().FindChild("Hotbar1").... ? // show button-up transition AND actually click it so that it fires the attached on-click() methods.
// TODO: do this in a for-loop for all 10 buttons.
}
Where are my Button.click() or Button.down() & up() methods? I also tried manually setting the transition state (dirty method though) but I don't seem to be able to access that either. Is this even possible without coding my very own button?
I also checked out: http://unity3d.com/learn/tutorials/modules/beginner/ui/ui-button but it didn't explain it either. It assumes that you always use a mouse. But I read that Unity does not support keyboard-input for their GUI other than [Spacebar] for pressing the currently selected button...
Hi guys...
Been reading this post and I think it may be what i`m looking for.. Wondering if you may be able to help me... Im trying to make it so when I click the unity UI Button, it acts as a keycode i.e press the button, and its the same as pressing Escape!! Im UBER new at using unity UI (First time EVER)so any and all help would be appreciated..
Thanks in advance
Answer by Huacanacha · Mar 28, 2015 at 08:26 AM
Well that was trickier than I expected... but I have come up with a clean solution using only public interfaces to the Unity UI system.
Attach the KeyButton script to a regular UI.Button
Set the key to whatever KeyCode you want to bind to
Configure colors and transition normally via inspector (normalColor and pressedColor). Note: the script co-opts disabled state so disabling is not supported in the current form... it would be easy enough to add.
Configure onClick events as normal via the inspector.
You can create a prefab to make initial creation easier but you will still need to set the key
to indicate which key press the button is bound to.
There were quite a few edge cases to cater for (mouse movement initiating state changes, app losing focus etc) but the script seems fully armed an operational now.
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Button))]
public class KeyButton : MonoBehaviour {
public KeyCode key;
public Button button {get; private set;}
Graphic targetGraphic;
Color normalColor;
void Awake() {
button = GetComponent<Button>();
button.interactable = false;
targetGraphic = GetComponent<Graphic>();
ColorBlock cb = button.colors;
cb.disabledColor = cb.normalColor;
button.colors = cb;
}
void Start() {
button.targetGraphic = null;
Up();
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(key)) {
Down();
} else if (Input.GetKeyUp(key)) {
Up();
}
}
void Up() {
StartColorTween(button.colors.normalColor, false);
}
void Down() {
StartColorTween(button.colors.pressedColor, false);
button.onClick.Invoke();
}
void StartColorTween(Color targetColor, bool instant) {
if (targetGraphic == null)
return;
targetGraphic.CrossFadeColor(targetColor, instant ? 0f : button.colors.fadeDuration, true, true);
}
void OnApplicationFocus(bool focus) {
Up();
}
public void LogOnClick() {
Debug.Log ("LogOnClick() - " + GetComponentInChildren<Text>().text);
}
}
--- Previous Answer ---
You need to add an EventTrigger to expose the full suite of UI events, including OnPointerDown and Up.
EventTrigger is added to the GameObject containing the UI element that needs to handle the events.
It works for a single button. But as soon as I add a 2nd button, the first button no longer works. I believe that this is because having 2 standalone input modules is not the way to go?
For button #2 I then change the 2 function parameters, "First Selected" and the "Submit Button" from 1 to 2.
I also noticed that these buttons still respond to the mouse which they're not supposed to do.
Button 1:
I suppose that the eventtrigger only calls methods that are called FRO$$anonymous$$ the button. And the inputmodule accepts input from the keyboard (among others) and then fires the corresponding button event.
EventSystem - one per scene only. Doesn't need to be under a Canvas. EventTrigger - add to every UI element that needs the extra events.
EventSystem and EventTrigger should in all likelihood NOT be on the same game object.
But how do I 'connect' (bind) the keyboard keys 0-9 to the buttons 0-9 then? The input module (at least the standard one) has no option for binding keys to specific UI controls.
So I thought I had to use one input module per button to 'connect' them. Which was obviously wrong.
Sure I can script it, but I'm hoping for something that's build-in into the GUI.button.
This works but I manually scripted it. And sadly doesn't automatically add a text component when you create it in the editor. It loses some functionality when you derive from Button for some reason. Like the required Image component is lost and the Text component as well.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[AddComponent$$anonymous$$enu("UI/HotbarButton")]
[RequireComponent (typeof (Image))]
public class HotbarButton : Button
{
#region $$anonymous$$embers
public int ButtonNumber = 1;
public $$anonymous$$eyCode Hotkey = $$anonymous$$eyCode.Alpha1;
#endregion
void LateUpdate()
{
if (Input.Get$$anonymous$$eyDown(Hotkey))
{
this.DoStateTransition(SelectionState.Pressed, false);
}
else if (Input.Get$$anonymous$$eyUp(Hotkey))
{
this.DoStateTransition(SelectionState.Normal, false);
this.onClick.Invoke();
}
}
}
It sadly also responds to the mouse and it feels like some dirty workaround.
Ah I have misunderstood your intent. You want to trigger actions/events on a button, not respond to events. I'll get back to this a little later when I have the time!
Ok I finally cracked it. It annoyed me this wasn't simpler and better supported by builtin functions, but it was possible in the end to respect all button settings whilst disabling mouse/touch input. It only uses public Button interfaces so we're not relying on any internal Button state.
Check out the script I added to my answer above!
Answer by Karwoch · Jun 02, 2015 at 11:21 AM
For me, this works perfectly:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class KeyEnter : MonoBehaviour {
public string inputName;
Button buttonMe;
// Use this for initialization
void Start () {
buttonMe = GetComponent<Button>();
}
void Update() {
if(Input.GetButtonDown(inputName))
{
buttonMe.onClick.Invoke();
}
}
}
Just create script with name KeyEnter, put there this code, attach it to a button, and from there You can just add in inspector key name You want to work with (all key names are edited in input manager).
I would use IEnumerable for better performance, but this way I`m sure buttons only works when they are enabled (I`m not so sure in case of coroutines).
Of course You can add any additional effects, but I didn`t needed them.
Thanks Huacanacha for inspiration.
I have to put above script into an empty GameObject
to make the buttonName
variable available and then input this GameObject
(with the attached script) into the the button below the On Click()
.
So far so good, but on execution I get a
Null reference exception: Object not set to an instance of an object
at the button$$anonymous$$e.onClick.Invoke();
So, I'm stuck here.
Answer by plapi · Jan 06, 2020 at 02:13 PM
**BEST SOLUTION*
So... Why is everyone using so much code here? Super Simple: Just apply this script to your button and choose what button you want to trigger.
using UnityEngine;
using UnityEngine.UI;
public class triggerButtonWithKey : MonoBehaviour
{
public KeyCode key;
void Update()
{
if (Input.GetKeyDown(key))
{
GetComponent<Button>().onClick.Invoke();
}
}
}
Thank you so much, this is PERFECTLY elegant code and does exactly the trick! I logged in just to upvote and say thanks!
Answer by Priyanshu · Mar 28, 2015 at 08:03 AM
If using 4.6 UI go here.
I'm using 5.x but it is still more or less the same as 4.6. However, I still can't get it to work. Do you have a simple example? I tried adding a StandAloneInput$$anonymous$$odule to the button and then assigning the alpha1 key to it (as configured in the input manager). I still don't quiet understand how I'm supposed to do this.