
本文将介绍Unity中的UI Toolkit(UI工具)中的鼠标捕获机制,首先需要了解什么是鼠标捕获。
什么是鼠标捕获?
现在考虑在UI元素上单击鼠标、拖动和释放,可以通过为以下事件注册回调来接收此类鼠标事件:
- 鼠标按下:MouseDownEvent
- 鼠标移动:MouseMoveEvent
- 鼠标释放:MouseUpEvent
要测试这些行为,请创建一个UI排列如下的EditorWindow。
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public sealed class CaptureExample : EditorWindow
{
private bool _isCapturing;
public void CreateGUI()
{
// layout
// Place child in the center of root
var root = rootVisualElement;
root.style.paddingTop = 100;
root.style.paddingBottom = 100;
root.style.paddingLeft = 100;
root.style.paddingRight = 100;
root.style.backgroundColor = new StyleColor(new Color(0.8f, 0.8f, 0.8f));
var child = new VisualElement
{
style =
{
height = new StyleLength(Length.Percent(100)),
borderBottomLeftRadius = 12,
borderBottomRightRadius = 12,
borderTopLeftRadius = 12,
borderTopRightRadius = 12,
backgroundColor = new StyleColor(new Color(0.3f, 0.3f, 0.3f))
}
};
root.Add(child);
// Register an event for child
child.RegisterCallback<MouseUpEvent>(_ => Debug.Log("MouseUpEvent"));
child.RegisterCallback<MouseDownEvent>(_ => Debug.Log("MouseDownEvent"));
child.RegisterCallback<MouseMoveEvent>(_ => Debug.Log("MouseMoveEvent"));
}
[MenuItem("Window/CaptureExample")]
public static void ShowWindow()
{
GetWindow<CaptureExample>("CaptureExample");
}
}
当运行它时,会看到一个像这样的窗口:
如果将鼠标拖动到中间的圆角矩形内,可以看到上面注册的每个事件都被触发了。

接下来,在这个child的内部按下鼠标,并在按住鼠标的同时将鼠标移动到child的外部。然后可以看到在圆角矩形之外不会调用。
这样,只有当鼠标悬停在注册回调的UI元素上时,才会调用鼠标事件MouseMoveEventMouseUpEvent。
如果在这里让子UI元素捕获鼠标,鼠标事件就会发给这个UI元素,直到释放捕获。这意味着将在捕获鼠标时在child外部调用MouseMoveEvent,MouseUpEvent要么显式释放鼠标捕获,要么在单击另一个元素时释放捕获。
检查鼠标捕获行为
那么,实际检查鼠标捕获的行为,以下脚本是将捕获过程添加到上面的EditorWindow的脚本。
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public sealed class CaptureExample : EditorWindow
{
private bool _isCapturing;
public void CreateGUI()
{
// layout
// Place child in the center of root
var root = rootVisualElement;
root.style.paddingTop = 100;
root.style.paddingBottom = 100;
root.style.paddingLeft = 100;
root.style.paddingRight = 100;
root.style.backgroundColor = new StyleColor(new Color(0.8f, 0.8f, 0.8f));
var child = new VisualElement
{
style =
{
height = new StyleLength(Length.Percent(100)),
borderBottomLeftRadius = 12,
borderBottomRightRadius = 12,
borderTopLeftRadius = 12,
borderTopRightRadius = 12
}
};
root.Add(child);
// Register events for child
// If child is capturing the mouse, these events will also react elsewhere
child.RegisterCallback<MouseUpEvent>(_ => Debug.Log("MouseUpEvent"));
child.RegisterCallback<MouseDownEvent>(_ => Debug.Log("MouseDownEvent"));
child.RegisterCallback<MouseMoveEvent>(_ => Debug.Log("MouseMoveEvent"));
// Change the color according to the mouse capture state
void SetChildColor()
{
child.style.backgroundColor = _isCapturing
? new StyleColor(new Color(0.3f, 0.8f, 0.3f))
: new StyleColor(new Color(0.3f, 0.3f, 0.3f));
}
child.RegisterCallback<MouseDownEvent>(evt =>
{
// Capture/release mouse when clicked
if (_isCapturing)
{
child.ReleaseMouse();
_isCapturing = false;
}
else
{
child.CaptureMouse();
// It's possible.
//MouseCaptureController.ReleaseMouse();
_isCapturing = true;
}
SetChildColor();
});
SetChildColor();
}
[MenuItem("Window/CaptureExample")]
public static void ShowWindow()
{
GetWindow<CaptureExample>("CaptureExample");
}
}
当显示此窗口并单击子项时,鼠标被捕获并且子项变为绿色,如果鼠标被捕获并且将鼠标移到子项之外,可以看到正在调用的鼠标事件。
通过再次单击子元素或单击另一个UI元素来释放鼠标捕获。

捕获事件
当元素捕获和取消捕获鼠标时,还可以将事件注册为回调。
为此,请按以下MouseCaptureEvent方式MouseCaptureOutEvent使用或:
child.RegisterCallback<MouseCaptureEvent>(_ => Debug.Log( "MouseCaptureEvent" ));
child.RegisterCallback<MouseCaptureOutEvent>(_ => Debug.Log( "MouseCaptureOutEvent" ));
…
以上是Unity的UIToolkit鼠标捕获机制介绍的全部内容,如果你有任何反馈,请随时在本页面下方留言。