Unity GUI.Window 筆記
根據官方文檔2021版本的,點擊鏈接跳轉記錄
概述
GUI.Window
是 Unity IMGUI 系統中用于創建彈出窗口的核心方法,具有以下關鍵特性:
- 浮動窗口:浮于普通 GUI 控件之上
- 焦點控制:可通過點擊獲得焦點
- 可拖拽:支持拖拽移動位置
- 獨立繪制:需要專門的函數來繪制窗口內容
方法簽名
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. 多窗口管理
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. 窗口顯示控制
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自動保存/恢復以下狀態:
GUI.skin
GUI.enabled
GUI.color
GUI.backgroundColor
GUI.contentColor
GUI.matrix
- 作用域:在調用
func
時恢復調用GUI.Window時的狀態 - 應用場景:
void OnGUI() {GUI.color = Color.red;windowRect = GUI.Window(0, windowRect, DoMyWindow, "Red Window"); }void DoMyWindow(int id) {// 此處GUI.color為紅色(被保存的狀態) }
4. 透明效果
void DoMyWindow(int id)
{// 設置透明度GUI.color = new Color(1, 1, 1, 0.5f); // 50%透明// 窗口內容...
}
- 使用
GUI.color
的Alpha分量實現淡入淡出效果
最佳實踐
1. 拖拽實現
void DoMyWindow(int id)
{// 頂部20像素為拖拽區域GUI.DragWindow(new Rect(0, 0, 10000, 20));// 窗口內容...
}
注意,這里的GUI.DragWindow只能在窗口回調函數(即GUI.Window的第三個參數所指定的函數)內部調用。
為什么必須在回調函數內調用?(我的疑惑)
是因為Unity IMGUI 事件處理流程
2. 窗口層級管理
void OnGUI()
{// 先繪制底層窗口bottomWindowRect = GUI.Window(1, bottomWindowRect, DrawBottom, "Bottom");// 后繪制頂層窗口(顯示在上方)topWindowRect = GUI.Window(2, topWindowRect, DrawTop, "Top");
}
- 繪制順序:后繪制的窗口顯示在前
3. 自動布局窗口
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")){// ...}
}
限制與注意事項
-
GUILayout兼容性:
- 當
MonoBehaviour.useGUILayout = false
時,GUI.Window無效 - 使用GUILayout控件時,應使用
GUILayout.Window
- 當
-
繪制順序:
- 窗口從后往前繪制(Z軸順序)
- 不要依賴窗口函數的調用順序
-
性能考慮:
- 頻繁創建/銷毀窗口可能影響性能
- 考慮復用窗口對象
-
移動平臺:
- 觸摸設備上拖拽體驗可能不佳
- 需要增加熱區大小
高級技巧
1. 窗口聚焦控制
void DoMyWindow(int id)
{if (GUILayout.Button("Focus Me")){GUI.FocusWindow(id);}
}
2. 窗口動畫
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. 模態窗口
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
實現 - 層級由繪制順序決定