Event.current
и OnGUI
Хотя обычно он не используется так часто, вы можете проверить ввод в OnGUI
, используя Event.current
.
Каждый раз, когда клавиша нажимается, сохраняйте ее в списке нажатых клавиш.Когда этот ключ идет вверх, удалите его из списка.Затем вы можете просто проверить, содержит ли список соответствующие ключи и соответствует ли длина ожидаемому количеству ключей.
public HashSet<KeyCode> currentlyPressedKeys = new HashSet<KeyCode>();
private void OnGUI()
{
if (!Event.current.isKey) return;
if (Event.current.keyCode != KeyCode.None)
{
if (Event.current.type == EventType.KeyDown)
{
currentlyPressedKeys.Add(Event.current.keyCode);
}
else if (Event.current.type == EventType.KeyUp)
{
currentlyPressedKeys.Remove(Event.current.keyCode);
}
}
// Shift is actually the only Key which is not treated as a
// EventType.KeyDown or EventType.KeyUp so it has to be checked separately
// You will not be able to check which of the shift keys is pressed!
if (!Event.current.shift)
{
return;
}
// As said shift is check on another way so we want only
// exactly 1 key which is KeyCode.B
if (currentlyPressedKeys.Count == 1 && currentlyPressedKeys.Contains(KeyCode.B))
Debug.Log("Only Shift + B");
}
Это необходимо сделать в OnGUI
, поскольку в одном кадре может быть несколько событий,Это эксклюзивно и будет срабатывать только при нажатии Shift + B .
Если вы предпочитаете поместить это где-нибудь в вашей сцене и установить значения static
public class KeysManager : MonoBehaviour
{
public static bool ShiftPressed;
public static HashSet<KeyCode> currentlyPressedKeys = new HashSet<KeyCode>();
private void OnGUI()
{
if (!Event.current.isKey) return;
if (Event.current.keyCode != KeyCode.None)
{
if (Event.current.type == EventType.KeyDown)
{
currentlyPressedKeys.Add(Event.current.keyCode);
}
else if (Event.current.type == EventType.KeyUp)
{
currentlyPressedKeys.Remove(Event.current.keyCode);
}
}
ShiftPressed = Event.current.shift;
}
}
Тогда вы, как и прежде, можете использовать что-то вроде
private void Update()
{
if (KeysManager.ShiftPressed && KeysManager.currentlyPressedKeys.Count == 1 && KeysManager.currentlyPressedKeys.Contains(KeyCode.B))
{
Debug.Log("Only Shift + B exclusively should trigger this");
}
}
Итерации с Input.GetKey
через все KeyCode
В качестве альтернативы вы могли бы как прокомментировано, проверьте все возможные ключи.
Однако, это может или не может быть проблемой, связанной с производительностью.Вам придется проверить это и решить, является ли это приемлемым в вашем конкретном случае.
using System.Linq;
...
// will store all buttons except B and LeftShift
KeyCode[] otherKeys;
private void Awake ()
{
// This simply returns an array with all values of KeyCode
var allKeys = (KeyCode[])Enum.GetValues(typeof(KeyCode));
// This uses Linq Where in order to only keep entries that are different from
// KeyCode.B and KeyCode.LeftShift
// ToArray finally converts the IEnumerable<KeyCode> into a KeyCode[]
otherKeys = allKeys.Where(k => k != KeyCode.B && k != KeyCode.LeftShift).ToArray();
}
private void Update()
{
if(Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.B) && !AnyOtherKeyPressed())
{
// Happens while ONLY LeftShift + B is pressed
}
}
// Return true if any other key
// is pressed except B and LeftShift
private bool AnyOtherKeyPressed()
{
foreach (var keyCode in otherKeys)
{
if(Input.GetKey(keyCode)) return true;
}
return false;
}
Может быть, мы слишком много беспокоимся, и это не имеет значения (я не верюэто, но только теоретически ^^), чем вы могли бы даже поднять его на один уровень и сделать его более гибким.
[Serializable]
public class KeyCombo
{
// Note I'll be lazy here .. you could create a custom editor
// for making sure each keyCode is unique .. but another time
public List<KeyCode> keyCodes = new List<KeyCode>();
// This will show an event in the Inspector so you can add callbacks to your keyCombos
// this is the same thing used in e.g. Button onClick
public UnityEvent whilePressed;
// Here all other keyCodes will be stored
[HideInInspector] public KeyCode[] otherKeys;
// Return true if any other key
// is pressed except B and LeftShift
public bool AnyOtherKeyPressed()
{
foreach (var keyCode in otherKeys)
{
if (Input.GetKey(keyCode)) return true;
}
return false;
}
}
public List<KeyCombo> keyCombos = new List<KeyCombo>();
private void Awake()
{
// This simply returns an array with all values of KeyCode
var allKeys = (KeyCode[])Enum.GetValues(typeof(KeyCode));
foreach (var keyCombo in keyCombos)
{
// This uses Linq Where in order to only keep entries that are different from
// the ones listed in keyCodes
// ToArray finally converts the IEnumerable<KeyCode> into a KeyCode[]
keyCombo.otherKeys = allKeys.Where(k => !keyCombo.keyCodes.Contains(k)).ToArray();
}
}
private void Update()
{
foreach (var keyCombo in keyCombos)
{
if (keyCombo.keyCodes.All(Input.GetKey) && !keyCombo.AnyOtherKeyPressed())
{
keyCombo.whilePressed.Invoke();
}
}
}
Теперь вы можете добавить несколько KeyCombos и проверить их по отдельности - однако имейте в видучто каждый дополнительный keyCombo также означает одну дополнительную итерацию по всем остальным ключам, так что ... это далеко от совершенства.