c# - 使用 EventSystem 进行按键事件
问题描述
上下文:假设您正在检查是否在键盘上按下“W”,最常见的检查方法是通过以下代码:
void Update(){
if (Input.GetKeyDown("W"))
DoSomething();
}
有没有办法使用 Unity 的 EventSystem 执行以下操作?换句话说,是否有像IPointerClickHandler这样的接口的实现,例如,检查按钮是否被按下,而不在Update()函数中这样做?
解决方案
有没有办法使用 Unity 的 EventSystem 执行以下操作?换句话说,有没有像 IPointerClickHandler 这样的接口的实现,
不,EventSystem 主要用于光线投射和调度事件。这不用于检测键盘事件。EventSystem 中唯一可以检测键盘事件的组件是InputField
组件。就是这样,它不能用于其他任何事情。
检查是否按下按钮,而不在 Update() 函数中这样做?
是的,有一种方法,Event.KeyboardEvent
这需要该OnGUI
功能。
void OnGUI()
{
if (Event.current.Equals(Event.KeyboardEvent("W")))
{
print("W pressed!");
}
}
这比在函数中使用Input.GetKeyDown
函数更糟糕Update
。我鼓励你坚持下去Input.GetKeyDown
。没有什么问题。
如果您正在寻找没有输入系统的事件类型,请使用UnityInput.GetKeyDown
的新输入 API 并订阅该InputSystem.onEvent
事件。
如果您正在寻找类似于IPointerClickHandler
接口的功能,您可以在Input.GetKeyDown
.
1 .首先,获取所有KeyCode
枚举System.Enum.GetValues(typeof(KeyCode));
并将其存储在一个数组中。
2、创建一个界面“IKeyboardEvent”,并在界面中添加OnKeyDown
类似OnPointerClick
的IPointerClickHandler
功能。
3 . 遍历KeyCode
from #1并检查数组中的每个键是否被按下、释放或按住。
4、获取场景中的所有组件,查看是否实现了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);
}
用法:
在脚本中实现IKeyboardEvent
接口和函数,就像使用IPointerClickHandler
.
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);
}
}
推荐阅读
- django-rest-framework - django 逆向工程如何在 swagger 中使用
- javascript - 在通过 graalvm 从 Java 程序调用的 javascript 中使用 import
- python - 如何通过单击键盘上的按钮来删除 pygame 中的精灵?
- google-cloud-platform - GCP API 网关:将参数设置为 false 会返回“架构不允许的属性”错误
- python - 如何找到给定总和的子数组
- python - 将十六进制值附加到列表/将字符串列表转换为十六进制
- javascript - 使用 Javascript 加载多个图像
- mysql - 如何在sql中创建一个派生属性列,它是其他两个现有列的总和
- laravel - 是否可以格式化不包含从数据库中获取的 html 标签的文本(laravel vue)
- c# - 我需要在按钮 Click 上检索动态创建的“DatePicker”的值