Lesson21 - Event 事件系统

Event 概述

Event 类用于在编辑模式下监听用户的键盘、鼠标等输入事件。与运行时的 Input 类不同,Event 专门用于编辑器拓展开发,在 OnGUI 和 SceneView 回调中使用。

获取当前事件

Event.current

1
Event e = Event.current;

获取当前帧的输入事件。每个 OnGUI 帧都会有一个当前事件。

重要:避免在布局计算期间多次访问 Event.current,应该在函数开头缓存:

1
2
3
4
5
6
7
private void OnGUI() {
Event e = Event.current; // 只获取一次

if (e.type == EventType.MouseDown) {
// 处理鼠标按下
}
}

修饰键检测

Alt、Shift、Ctrl 键

1
2
3
if (e.alt)     Debug.Log("Alt 被按下");
if (e.shift) Debug.Log("Shift 被按下");
if (e.control) Debug.Log("Ctrl 被按下");

Windows/Command 键

1
2
3
if (e.command) {
Debug.Log("Windows 键或 Mac 的 Command 键被按下");
}

CapsLock 状态

1
2
3
if (e.capsLock) {
Debug.Log("CapsLock 已开启");
}

鼠标事件

鼠标事件判断

1
2
3
if (e.isMouse) {
Debug.Log("这是一个鼠标事件");
}

鼠标按键

1
2
3
4
// e.button: 0 = 左键, 1 = 右键, 2 = 中键
if (e.button == 0) Debug.Log("左键");
if (e.button == 1) Debug.Log("右键");
if (e.button == 2) Debug.Log("中键");

鼠标位置

1
2
Vector2 mousePos = e.mousePosition; // 当前鼠标位置
Vector2 mouseDelta = e.delta; // 上一帧到这一帧的移动距离

鼠标事件类型

1
2
3
4
5
6
7
8
9
10
11
12
if (e.type == EventType.MouseDown) {
Debug.Log("鼠标按下");
}
if (e.type == EventType.MouseUp) {
Debug.Log("鼠标抬起");
}
if (e.type == EventType.MouseDrag) {
Debug.Log("鼠标拖拽");
}
if (e.type == EventType.MouseMove) {
Debug.Log("鼠标移动");
}

键盘事件

键盘事件判断

1
2
3
if (e.isKey) {
Debug.Log("这是一个键盘事件");
}

获取输入的字符

1
2
3
if (e.isKey && e.character != null) {
Debug.Log("输入字符:" + e.character);
}

可用于文本输入的检测。

获取键码

1
2
3
4
5
6
7
8
KeyCode key = e.keyCode;

if (e.keyCode == KeyCode.Return) {
Debug.Log("Enter 键被按下");
}
if (e.keyCode == KeyCode.Escape) {
Debug.Log("Esc 键被按下");
}

键盘事件类型

1
2
3
4
5
6
if (e.type == EventType.KeyDown) {
Debug.Log("键盘按下");
}
if (e.type == EventType.KeyUp) {
Debug.Log("键盘抬起");
}

功能键和特殊键

功能键检测

1
2
3
if (e.functionKey) {
Debug.Log("按下的是功能键(方向键、PgUp/PgDn、Backspace 等)");
}

功能键包括:方向键(↑↓←→)、Page Up、Page Down、Backspace、Delete 等。

小键盘检测

1
2
3
if (e.numeric) {
Debug.Log("小键盘已开启");
}

系统命令

命令名识别

1
2
3
4
5
6
7
8
9
if (e.commandName == "Copy") {
Debug.Log("用户执行了拷贝操作");
}
if (e.commandName == "Paste") {
Debug.Log("用户执行了粘贴操作");
}
if (e.commandName == "Cut") {
Debug.Log("用户执行了剪切操作");
}

常见的命令名:Copy、Paste、Cut、Undo、Redo 等。

事件类型为 ExecuteCommand

1
2
3
4
5
if (e.type == EventType.ExecuteCommand) {
if (e.commandName == "自定义事件名") {
Debug.Log("收到自定义事件");
}
}

消费事件

Use() 方法

1
2
3
4
if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Return) {
Debug.Log("Enter 被按下");
e.Use(); // 消费事件
}

调用 Use() 后,Unity 会认为该事件已被处理,不会继续派发给其他处理器。这可以防止事件冲突。

实战应用

监听快捷键组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void OnGUI() {
Event e = Event.current;

// 监听 Ctrl+S(保存)
if (e.type == EventType.KeyDown && e.control && e.keyCode == KeyCode.S) {
Debug.Log("执行保存");
e.Use();
}

// 监听 Ctrl+Z(撤销)
if (e.type == EventType.KeyDown && e.control && e.keyCode == KeyCode.Z) {
Debug.Log("执行撤销");
e.Use();
}
}

鼠标拖拽检测

1
2
3
4
5
6
7
8
9
10
11
12
13
private void OnGUI() {
Event e = Event.current;

if (e.isMouse) {
if (e.type == EventType.MouseDown && e.button == 0) {
Debug.Log("左键按下在:" + e.mousePosition);
} else if (e.type == EventType.MouseDrag && e.button == 0) {
Debug.Log("左键拖拽,移动距离:" + e.delta);
} else if (e.type == EventType.MouseUp && e.button == 0) {
Debug.Log("左键抬起");
}
}
}

处理滚轮

1
2
3
if (e.isScrollWheel) {
Debug.Log("滚轮移动:" + e.delta);
}

完整的事件类型枚举

EventType 包括:MouseMove、MouseDown、MouseUp、MouseDrag、KeyDown、KeyUp、ScrollWheel、Repaint、Layout、DragUpdated、DragPerform、DragExited、Ignore、Used、ValidateCommand、ExecuteCommand、ContextClick 等。