场景:比如说你想检查键盘上是否按下了"W"键,最常见的方法是通过以下代码进行检查:
void Update(){
if (Input.GetKeyDown("W"))
DoSomething();
}
有没有一种使用Unity的EventSystem来实现以下功能的方法?换句话说,是否有像IPointerClickHandler这样的接口实现,可以检查按钮是否被按下,而不需要在Update()函数中这样做?
场景:比如说你想检查键盘上是否按下了"W"键,最常见的方法是通过以下代码进行检查:
void Update(){
if (Input.GetKeyDown("W"))
DoSomething();
}
void OnGUI()
{
if (Event.current.Equals(Event.KeyboardEvent("W")))
{
print("W pressed!");
}
}
使用Update
函数和Input.GetKeyDown
函数相比,这种方法更糟糕。我建议你坚持使用Input.GetKeyDown
,这样没有任何问题。
Input.GetKeyDown
的事件类型InputSystem,则可以使用Unity的新输入API并订阅InputSystem.onEvent
事件。IPointerClickHandler
接口的功能,则可以在Input.GetKeyDown
上实现它。System.Enum.GetValues(typeof(KeyCode));
获取所有KeyCode
枚举并将其存储在数组中。OnKeyDown
,就像在IPointerClickHandler
接口中的OnPointerClick
一样。KeyCode
,并检查数组中的每个键是按下、释放还是按下。IKeyboardEvent
接口。如果是,则根据#3中的键状态调用接口中的适当函数。using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class KeyboardEventSystem : MonoBehaviour
{
Array allKeyCodes;
private static List<Transform> allTransforms = new List<Transform>();
private static List<GameObject> rootGameObjects = new List<GameObject>();
void Awake()
{
allKeyCodes = System.Enum.GetValues(typeof(KeyCode));
}
void Update()
{
//Loop over all the keycodes
foreach (KeyCode tempKey in allKeyCodes)
{
//Send event to key down
if (Input.GetKeyDown(tempKey))
senEvent(tempKey, KeybrdEventType.keyDown);
//Send event to key up
if (Input.GetKeyUp(tempKey))
senEvent(tempKey, KeybrdEventType.KeyUp);
//Send event to while key is held down
if (Input.GetKey(tempKey))
senEvent(tempKey, KeybrdEventType.down);
}
}
void senEvent(KeyCode keycode, KeybrdEventType evType)
{
GetAllRootObject();
GetAllComponents();
//Loop over all the interfaces and callthe appropriate function
for (int i = 0; i < allTransforms.Count; i++)
{
GameObject obj = allTransforms[i].gameObject;
//Invoke the appropriate interface function if not null
IKeyboardEvent itfc = obj.GetComponent<IKeyboardEvent>();
if (itfc != null)
{
if (evType == KeybrdEventType.keyDown)
itfc.OnKeyDown(keycode);
if (evType == KeybrdEventType.KeyUp)
itfc.OnKeyUP(keycode);
if (evType == KeybrdEventType.down)
itfc.OnKey(keycode);
}
}
}
private static void GetAllRootObject()
{
rootGameObjects.Clear();
Scene activeScene = SceneManager.GetActiveScene();
activeScene.GetRootGameObjects(rootGameObjects);
}
private static void GetAllComponents()
{
allTransforms.Clear();
for (int i = 0; i < rootGameObjects.Count; ++i)
{
GameObject obj = rootGameObjects[i];
//Get all child Transforms attached to this GameObject
obj.GetComponentsInChildren<Transform>(true, allTransforms);
}
}
}
public enum KeybrdEventType
{
keyDown,
KeyUp,
down
}
public interface IKeyboardEvent
{
void OnKeyDown(KeyCode keycode);
void OnKeyUP(KeyCode keycode);
void OnKey(KeyCode keycode);
}
用法:
像使用IPointerClickHandler
一样,在脚本中实现IKeyboardEvent
接口及其函数。
public class test : MonoBehaviour, IKeyboardEvent
{
public void OnKey(KeyCode keycode)
{
Debug.Log("Key held down: " + keycode);
}
public void OnKeyDown(KeyCode keycode)
{
Debug.Log("Key pressed: " + keycode);
}
public void OnKeyUP(KeyCode keycode)
{
Debug.Log("Key released: " + keycode);
}
}
我创建了一个简单的脚本来触发简单事件。 我使用了OnguiGUI而不是Update。 请看下面的代码!
using UnityEngine;
using UnityEngine.Events;
public class TriggerKey : MonoBehaviour
{
[Header("----Add key to trigger on pressed----")]
public string key;
// Unity event inspector
public UnityEvent OnTriggerKey;
public void OnGUI()
{ // triiger event on trigger key
if (Event.current.Equals(Event.KeyboardEvent(key)))
{
OnTriggerKey.Invoke();
print("test trigger btn");
}
}
}