【Unity编辑器开发GUI.Window】

Unity GUI.Window 笔记

根据官方文档2021版本的,点击链接跳转记录

概述

GUI.Window 是 Unity IMGUI 系统中用于创建弹出窗口的核心方法,具有以下关键特性:

  • 浮动窗口:浮于普通 GUI 控件之上
  • 焦点控制:可通过点击获得焦点
  • 可拖拽:支持拖拽移动位置
  • 独立绘制:需要专门的函数来绘制窗口内容

方法签名

csharp 复制代码
public static Rect Window(
    int id, 
    Rect clientRect, 
    GUI.WindowFunction func, 
    string text, 
    GUIStyle style
);

参数说明

参数 类型 描述 是否必需
id int 窗口唯一标识符(必须保证唯一) ✅ 必需
clientRect Rect 窗口初始位置和大小(屏幕矩形) ✅ 必需
func GUI.WindowFunction 窗口内容绘制函数(接收窗口ID作为参数) ✅ 必需
text string 窗口标题栏显示的文本 ❌ 可选
image Texture 窗口标题栏显示的图像 ❌ 可选
content GUIContent 窗口标题栏显示的内容(文本+图像) ❌ 可选
style GUIStyle 窗口自定义样式(默认使用当前GUISkin的window样式) ❌ 可选

返回值

  • Rect:表示窗口当前位置和大小的矩形

核心机制

1. 多窗口管理

csharp 复制代码
void OnGUI()
{
    // 多个窗口使用相同绘制函数
    windowRect0 = GUI.Window(0, windowRect0, DoMyWindow, "Window 0");
    windowRect1 = GUI.Window(1, windowRect1, DoMyWindow, "Window 1");
}

void DoMyWindow(int windowID)
{
    // 根据ID区分窗口
    if (GUI.Button(new Rect(10, 20, 100, 20), "Click Me"))
    {
        Debug.Log("Clicked in window: " + windowID);
    }
}
  • 关键点:使用不同的ID区分窗口
  • 优势:复用绘制函数减少代码冗余

2. 窗口显示控制

csharp 复制代码
bool showWindow = true;

void OnGUI()
{
    // 控制开关
    showWindow = GUI.Toggle(new Rect(10, 10, 100, 20), showWindow, "Show Window");
    
    if (showWindow)
    {
        windowRect = GUI.Window(0, windowRect, DoMyWindow, "My Window");
    }
}
  • 开启窗口:在OnGUI中调用GUI.Window
  • 关闭窗口 :停止调用GUI.Window
    注意,到目前写这边博文25年六月并没有函数可以关闭,只可以通过类似这样的条件来控制

3. GUI状态保存

Unity自动保存/恢复以下状态:

csharp 复制代码
GUI.skin
GUI.enabled
GUI.color
GUI.backgroundColor
GUI.contentColor
GUI.matrix
  • 作用域 :在调用func时恢复调用GUI.Window时的状态

  • 应用场景

    csharp 复制代码
    void OnGUI()
    {
        GUI.color = Color.red;
        windowRect = GUI.Window(0, windowRect, DoMyWindow, "Red Window");
    }
    
    void DoMyWindow(int id)
    {
        // 此处GUI.color为红色(被保存的状态)
    }

4. 透明效果

csharp 复制代码
void DoMyWindow(int id)
{
    // 设置透明度
    GUI.color = new Color(1, 1, 1, 0.5f); // 50%透明
    
    // 窗口内容...
}
  • 使用GUI.color的Alpha分量实现淡入淡出效果

最佳实践

1. 拖拽实现

csharp 复制代码
void DoMyWindow(int id)
{
    // 顶部20像素为拖拽区域
    GUI.DragWindow(new Rect(0, 0, 10000, 20));
    
    // 窗口内容...
}

注意,这里的GUI.DragWindow只能在窗口回调函数(即GUI.Window的第三个参数所指定的函数)内部调用。

为什么必须在回调函数内调用?(我的疑惑)

是因为Unity IMGUI 事件处理流程

2. 窗口层级管理

csharp 复制代码
void OnGUI()
{
    // 先绘制底层窗口
    bottomWindowRect = GUI.Window(1, bottomWindowRect, DrawBottom, "Bottom");
    
    // 后绘制顶层窗口(显示在上方)
    topWindowRect = GUI.Window(2, topWindowRect, DrawTop, "Top");
}
  • 绘制顺序:后绘制的窗口显示在前

3. 自动布局窗口

csharp 复制代码
void OnGUI()
{
    // 使用GUILayout.Window替代
    windowRect = GUILayout.Window(0, windowRect, DoWindowWithLayout, "Layout Window");
}

void DoWindowWithLayout(int id)
{
    // 使用GUILayout自动布局
    GUILayout.Label("Auto layout content");
    if (GUILayout.Button("Button"))
    {
        // ...
    }
}

限制与注意事项

  1. GUILayout兼容性

    • MonoBehaviour.useGUILayout = false时,GUI.Window无效
    • 使用GUILayout控件时,应使用GUILayout.Window
  2. 绘制顺序

    • 窗口从后往前绘制(Z轴顺序)
    • 不要依赖窗口函数的调用顺序
  3. 性能考虑

    • 频繁创建/销毁窗口可能影响性能
    • 考虑复用窗口对象
  4. 移动平台

    • 触摸设备上拖拽体验可能不佳
    • 需要增加热区大小

高级技巧

1. 窗口聚焦控制

csharp 复制代码
void DoMyWindow(int id)
{
    if (GUILayout.Button("Focus Me"))
    {
        GUI.FocusWindow(id);
    }
}

2. 窗口动画

csharp 复制代码
IEnumerator AnimateWindow()
{
    float duration = 1f;
    for (float t = 0; t < duration; t += Time.deltaTime)
    {
        windowRect.y = Mathf.Lerp(-100, 100, t/duration);
        yield return null;
    }
}

3. 模态窗口

csharp 复制代码
void OnGUI()
{
    // 禁用背景
    GUI.enabled = !modalActive;
    
    // 绘制普通UI...
    
    // 启用并绘制模态窗口
    GUI.enabled = true;
    if (modalActive)
    {
        modalRect = GUI.Window(0, modalRect, DrawModal, "Modal");
    }
}

总结

GUI.Window 是 Unity IMGUI 系统的核心组件,用于创建交互式窗口:

  • 唯一ID是窗口系统的基础
  • 返回值保存窗口位置状态
  • GUI状态在窗口间自动保存/恢复
  • 拖拽 通过GUI.DragWindow实现
  • 层级由绘制顺序决定
相关推荐
小丁努力不焦虑10 小时前
vscode环境下c++的常用快捷键和插件
ide·vscode·编辑器
9分钟带帽15 小时前
vscode编辑Markdown文件
vscode·编辑器·markdown
Wacanda1 天前
Unity笔记——Unity 封装方法指南
笔记·unity
ZPC82101 天前
奥比中光双目摄像头实现物品抓取的机器人系统
c++·python·unity·机器人·游戏引擎·github
呼叫冰河谷1 天前
Unity学习笔记(五)——3DRPG游戏(2)
笔记·学习·unity
我命由我123451 天前
VSCode - VSCode 查找中文字符
前端·ide·vscode·编辑器·html·软件·软件工具
Littlewith1 天前
Node.js:Stream、模块系统
java·服务器·开发语言·node.js·编辑器
9分钟带帽2 天前
vscode的终端运行目录修改为当前文件的路径下
ide·vscode·编辑器
特立独行的猫a2 天前
在Vscode中使用Kimi K2模型:实践指南,三分钟生成个小游戏
ide·vscode·编辑器·kimi·kimi k2