Hi there,
normally I prefer to code everything myself, but to save time I used the super asset of One Wheel Studio , in order to bind the keys.
My problem is that I’m having a little trouble doing what I want to modify.
Here we have 2 scripts :
- KeyBinding (attached to a prefab button)
- and KeyBindingManager
Each KeyBinding prefab button handles a different key with : public enum KeyAction in the KeyBindingManager.
The entry is written like this :
if (Input.GetButtonDown(KeyCode.myKey))
if (KeyBindingManager.GetKeyDown(KeyAction.myEnumKeyAction))
{...}
My problem :
The user can bind the same KeyCode to two different KeyActions.
Which is a problem for me.
I don’t know how to go about finding a solution.
For now, what comes to mind would be,
be able to compare prefabs with their KeyAction,
and do a ChangeKeyCode(false);
If their two KeyCode are identical.
Does this seem correct to you ?
Here are the codes :
KeyBindingManager
using UnityEngine;
using System.Collections.Generic;
//static class that stores the key dictionary. The dictionary is loaded at runtime from Keybinding scripts.
//The keybinding scripts will load from the inspector unless there is a corresponding key in player prefs.
public static Dictionary<KeyAction, KeyCode> keyDict = new Dictionary<KeyAction, KeyCode>();
//Returns key code
public static KeyCode GetKeyCode(KeyAction key)
{
KeyCode _keyCode = KeyCode.None;
keyDict.TryGetValue(key, out _keyCode);
return _keyCode;
}
//Use in place of Input.GetKey
public static bool GetKey(KeyAction key)
{
KeyCode _keyCode = KeyCode.None;
keyDict.TryGetValue(key, out _keyCode);
return Input.GetKey(_keyCode);
}
//Use in place of Input.GetKeyDown
public static bool GetKeyDown(KeyAction key)
{
KeyCode _keyCode = KeyCode.None;
keyDict.TryGetValue(key, out _keyCode);
return Input.GetKeyDown(_keyCode);
}
//Use in place of Input.GetKeyUP
public static bool GetKeyUp(KeyAction key)
{
KeyCode _keyCode = KeyCode.None;
keyDict.TryGetValue(key, out _keyCode);
return Input.GetKeyUp(_keyCode);
}
public static void UpdateDictionary(KeyBinding key)
{
if (!keyDict.ContainsKey(key.keyAction))
keyDict.Add(key.keyAction, key.keyCode);
else
keyDict[key.keyAction] = key.keyCode;
}
}
//used to safe code inputs
//Add new keys to "bind" here
public enum KeyAction
{
none,
up,
down,
left,
right,
forward,
backward,
pause,
jump,
mute
}
KeyBinding
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System;
[System.Serializable]
//[RequireComponent(typeof(SaveKeyBinding))] //used to save data to database
public class KeyBinding : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public delegate void remap(KeyBinding key);
public static event remap keyRemap;
//Name comes from enum in KeyBindingsManager scrip
public KeyAction keyAction;
//keycode set in inspector and by player
public KeyCode keyCode = KeyCode.W;
//Text to display keycode for user feedback
public Text keyDisplay;
//Used for color changing during key binding
public GameObject button;
public Color toggleColor = new Color(0.75f,0.75f,0.75f,1f);
Image buttonImage;
Color originalColor;
//mouse rebinding
public bool allowMouseButtons = true;
//Internal variables
bool reassignKey = false;
Event curEvent;
bool isHovering = false; //used for mouse controls
//Changes in button behavior should be made here
void OnGUI()
{
curEvent = Event.current;
//Checks if key is pressed and if button has been pressed indicating wanting to re - assign
if (curEvent.isKey && curEvent.keyCode != KeyCode.None && reassignKey)
{
keyCode = curEvent.keyCode;
ChangeKeyCode(false);
UpdateKeyCode();
SaveKeyCode();
}
else if (curEvent.shift && reassignKey) //deals with some oddity in how Unity deals with shifts keys
{
if (Input.GetKey(KeyCode.LeftShift))
keyCode = KeyCode.LeftShift;
else
keyCode = KeyCode.RightShift;
ChangeKeyCode(false);
UpdateKeyCode();
SaveKeyCode();
}
//checks if mouse is pressed and assigns appropriate keycode
else if (curEvent.isMouse && reassignKey && isHovering && allowMouseButtons)
{
StartCoroutine(Wait());//prevents "over clicking"
//converts mouse button to keycode - see Keycode defintion for why 323 is added.
int _int = curEvent.button + 323;
KeyCode mouseKeyCode = (KeyCode)_int;
keyCode = mouseKeyCode;
ChangeKeyCode(false);
UpdateKeyCode();
SaveKeyCode();
}
//cancels binding if not hovering and mouse clicked
else if(curEvent.isMouse && !isHovering)
{
ChangeKeyCode(false);
}
}
public void OnPointerEnter(PointerEventData data)
{
isHovering = true;
}
public void OnPointerExit(PointerEventData data)
{
isHovering = false;
}
//Initializes
void Awake()
{
buttonImage = button.GetComponent<Image>();
originalColor = buttonImage.color;
button.GetComponent<Button>().onClick.AddListener(() => ChangeKeyCode(true));
}
//Loads keycodes from player preferences
void OnEnable()
{
Debug.Log("PrintOnDisable: script was enable");
//Comment out this line it you want to allow multiple simultaneous assignments
KeyBinding.keyRemap += PreventDoubleAssign;
KeyCode tempKey;
tempKey = (KeyCode) PlayerPrefs.GetInt(keyAction.ToString()); //saved by the keyType, but returns int that corresponds to keyCode --- sauvegardé par le keyType, mais retourne int qui correspond à keyCode
if(tempKey.ToString() == "None")
{
Debug.Log(keyCode.ToString());
keyDisplay.text = keyCode.ToString();
UpdateKeyCode();
SaveKeyCode();
}
else
{
keyCode = tempKey;
keyDisplay.text = keyCode.ToString();
UpdateKeyCode();
}
}
void OnDisable()
{
Debug.Log("PrintOnDisable: script was disabled");
KeyBinding.keyRemap -= PreventDoubleAssign;
}
//Called by button on GUI
public void ChangeKeyCode(bool toggle)
{
reassignKey = toggle;
if(toggle)
{
buttonImage.color = toggleColor;
if(keyRemap != null )
keyRemap(this);
}
else
buttonImage.color = originalColor;
}
//saves keycode to player prefs
public void SaveKeyCode()
{
keyDisplay.text = keyCode.ToString();
PlayerPrefs.SetInt(keyAction.ToString(),(int)keyCode);
PlayerPrefs.Save();
}
//Prevents user from remapping two keys at the same time
void PreventDoubleAssign(KeyBinding kb)
{
if(kb != this)
{
reassignKey = false;
buttonImage.color = originalColor;
}
}
//updates dictionary on key bindings manager
public void UpdateKeyCode()
{
KeyBindingManager.UpdateDictionary(this);
}
//prevent button from getting clicked.
IEnumerator Wait()
{
button.GetComponent<Button>().onClick.RemoveAllListeners();
yield return new WaitUntil(() => !Input.GetMouseButton(0));
button.GetComponent<Button>().onClick.AddListener(() => ChangeKeyCode(true));
}
}
What I want to achieve :
If I bind my key A to button 1, I would like it to be impossible for me to bind my key A to button B, regardless of the method used.