我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

u3d IMGUI[一]基础概念、控件

u3d IMGUI[一]基础概念、控件 本系列IMGUI文章意在精简和整合IMGUI的官方文档抽出重点可用于学习和知识点回顾虽然截至2026.8.22官方主推UITool kit但是由于IMGUI在老项目中大量使用以找工作上手项目的角度出发学习IMGUI还是值得的一.IMGUI概述1.1 概念Unity提供了三种UI系统UI Toolkit、uGUI和IMGUI。IMGUI (Immediate Mode GUI)译为立即模式 其是一个代码驱动的 GUI 系统主要作为程序员的工具。1.2 用途IMGUI 通常用于游戏内调试显示和编辑器扩展不用于玩家使用的UI。1.3 特点IMGUI 绘制的UI元素不是场景中的GameObject参考IMGUI立即模式 GUI参考Going deep with IMGUI and Editor customization二.OnGUI函数要创建 IMGUI 元素需要在MonoBehaviour中编写OnGUI函数其和Update一样也是生命周期函数之一每帧执行一次。三.控件要素创建IMGUI 控件需要三个要素类型、位置、内容3.1 类型创建IMGUI控件需要调用GUI类的函数该函数就是控件的类型3.2 位置Position是任何GUI控制函数中的第一个参数。参数本身由Rect()函数提供。Rect()定义了四个属性最左边的位置、最上面的位置、总宽度、总高度。所有这些值均以整数形式提供对应于像素值。所有 UnityGUI 控件都在“屏幕空间”中工作即已发布播放器的分辨率以像素为单位。坐标系基于左上角。/* Screen.width Screen.height example */ using UnityEngine; using System.Collections; public class GUITest : MonoBehaviour { void OnGUI() { GUI.Box (new Rect (0,0,100,50), Top-left); GUI.Box (new Rect (Screen.width - 100,0,100,50), Top-right); GUI.Box (new Rect (0,Screen.height - 50,100,50), Bottom-left); GUI.Box (new Rect (Screen.width - 100,Screen.height - 50,100,50), Bottom-right); } }3.3 内容A.基础用法控件中最常见的显示内容为文本(传字符串) 或 图像(传Texture2D)。public Texture2D icon; void OnGUI () { if (GUI.Button (new Rect (10,10, 100, 50), icon)) { print (you clicked the icon); } if (GUI.Button (new Rect (10,70, 100, 20), This is text)) { print (you clicked the text button); } }B.GUIContentGUIContent类可用于同时显示图片文字悬浮飘字这种功能OnGUI会检查鼠标是否落在某个带 tooltip 的控件上。悬停在按钮上 → 这一帧把该控件的提示赋给GUI.tooltippublic Texture2D icon; void OnGUI () { GUI.Button (new Rect (10,10,100,20), new GUIContent (Click me, icon, This is the tooltip)); GUI.Label (new Rect (10,40,100,20), GUI.tooltip); }四.IMGUI的控件本节介绍IMGUI的若干控件见下面demo该有的注释都有using UnityEngine; public class Example : MonoBehaviour { public Texture2D icon; private string textFieldString text field; private string textAreaString text area; private bool toggleBool true; private int toolbarInt 0; private string[] toolbarStrings {Toolbar1, Toolbar2, Toolbar3}; private int selectionGridInt 0; private string[] selectionStrings {Grid 1, Grid 2, Grid 3, Grid 4}; private float hSliderValue 0.0f; private float vSliderValue 0.0f; private float hScrollbarValue; private float vScrollbarValue; private Vector2 scrollViewVector Vector2.zero; private string innerText I am inside the ScrollView; private Rect windowRect new Rect (520, 260, 120, 50); void OnGUI () { //Label GUI.Label (new Rect (25, 25, 100, 30), Label); //Button if (GUI.Button (new Rect (125, 25, 100, 30), Button)) { Debug.Log(Button is Clicked); } //RepeatButton:持续按下时回调会每帧执行 if (GUI.RepeatButton (new Rect (325, 25, 100, 30), RepeatButton)) { Debug.Log(RepeatButton is Clicked); } //TextField单行输入框 textFieldString GUI.TextField (new Rect (525, 25, 100, 30), textFieldString); //TextArea多行输入框 textAreaString GUI.TextArea (new Rect (725, 25, 100, 30), textAreaString); //Toggle开关 toggleBool GUI.Toggle (new Rect (925, 25, 100, 30), toggleBool, Toggle); //Toolbar开关组 toolbarInt GUI.Toolbar (new Rect (25, 125, 250, 30), toolbarInt, toolbarStrings); //SelectionGrid网格开关组 selectionGridInt GUI.SelectionGrid (new Rect (320, 125, 300, 60), selectionGridInt, selectionStrings, 2); //HorizontalSlider滑动条 hSliderValue GUI.HorizontalSlider (new Rect (720, 125, 100, 30), hSliderValue, 0.0f, 10.0f); //VerticalSlider vSliderValue GUI.VerticalSlider (new Rect (900, 125, 100, 30), vSliderValue, 10.0f, 0.0f); //HorizontalScrollbar滑块 hScrollbarValue GUI.HorizontalScrollbar (new Rect (25, 260, 100, 30), hScrollbarValue, 1.0f, 0.0f, 10.0f); //VerticalScrollbar vScrollbarValue GUI. VerticalScrollbar (new Rect (200, 260, 100, 30), vScrollbarValue, 1.0f, 10.0f, 0.0f); //BeginScrollView scrollViewVector GUI.BeginScrollView (new Rect (350, 260, 100, 100), scrollViewVector, new Rect (0, 0, 400, 400)); innerText GUI.TextArea (new Rect (0, 0, 400, 400), innerText); GUI.EndScrollView(); //Window控件容器点击可接手或失去焦点 windowRect GUI.Window (0, windowRect, id { // Draw any Controls inside the window here }, My Window); //GUI.changed:检测用户是否在 GUI 中执行了任何操作,当完成某些操作时该值将设置为 true if (GUI.changed) { Debug.Log(The toolbar was clicked: toolbarInt); } } }五.用GUIStyles改控件外观默认情况下如果创建控件时未定义 GUIStyle则会应用 Unity 的默认 GUIStyle。GUIStyle有两种用法1.使用skin中预定义的GUIStyles创建一个皮肤文件其管理一系列Styles每个Styles有自己的名字可在创建控件时将名字传给最后一个参数void OnGUI () { // Make a label that uses the box GUIStyle. GUI.Label (new Rect (0,0,200,100), Hi - Im a label looking like a box, box); }2.声明 GUIStyle 公有变量所有元素都将显示在 Inspector 中。using UnityEngine; public class Example : MonoBehaviour { public GUIStyle customButton; void OnGUI () { GUI.Button (new Rect (10,10,150,20), I am a Custom Button, customButton); } }六.用GUISkin改控件外观GUISkin 是 GUIStyle 的集合。对于较复杂的 GUI 系统将一系列样式集中保存在一个位置是很有意义的。这就是 GUISkin 的作用。要创建 GUISkin从菜单栏中选择Assets-Create-GUI SkinGUI.skin是 IMGUI 的全局当前皮肤。赋值后下面绘制的控件会从这个GUISkin里取样式。using UnityEngine; public class Example : MonoBehaviour { public GUISkin mySkin; private bool toggle true; void OnGUI () { GUI.skin mySkin; toggle GUI.Toggle (new Rect (10,10,150,20), toggle, Skinned Button, button); GUI.skin null; GUI.Button (new Rect (10,35,150,20), Built-in Button); } }七.IMGUI 布局模式7.1 布局模式分类IMGUI提供了固定布局模式和自动布局模式。固定布局使用GUI类自动布局使用GUILayout类且不需要Rect函数。void OnGUI () { // Fixed Layout GUI.Button (new Rect (25,25,100,30), I am a Fixed Layout Button); // Automatic Layout GUILayout.Button (I am an Automatic Layout Button); }IMGUI为两种布局模式提供了对应的概念规则和API。固定布局组自动布局区域水平组垂直组7.2 固定布局 - Group组的作用是在固定布局中把控件的坐标默认相对于屏幕的左上角 改成 相对于组所在的矩形的左上角。可为定义组中包含的控件需要使用 GUI.BeginGroup() 和 GUI.EndGroup() 函数。组可以嵌套子组的内容都会裁剪到父组矩形。void OnGUI () { // Make a group on the center of the screen GUI.BeginGroup (new Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 100)); // All rectangles are now adjusted to the group. (0,0) is the topleft corner of the group. // Well make a box so you can see where the group is on-screen. GUI.Box (new Rect (0,0,100,100), Group is here); GUI.Button (new Rect (10,40,80,30), Click me); // End the group we started above. This is very important to remember! GUI.EndGroup (); }7.3 自动布局 - Area区域定义了有限的屏幕区域来包含 GUILayout 控件GUILayout 控件将放置在该区域的最左上角。自动布局的开发中区域大量使用。在一个区域内具有可见元素的控件会将宽度拉伸到该区域的整个长度。void OnGUI () { GUILayout.Button (I am not inside an Area); GUILayout.BeginArea (new Rect (Screen.width/2, Screen.height/2, 300, 300)); GUILayout.Button (I am completely inside an Area); GUILayout.EndArea (); }7.4 自动布局 - 水平和垂直组使用自动布局时默认情况下控件将从上到下依次出现。在很多情况下需要更精确控制控件的放置位置以及排列方式。如果使用自动布局模式则可以选择水平和垂直组。与其他布局控件一样可以调用单独的函数来开始或结束这些组。这些函数为GUILayout.BeginHorizontal()、GUILayout.EndHorizontal()、GUILayout.BeginVertical()和GUILayout.EndVertical()。using UnityEngine; public class Example : MonoBehaviour { private float sliderValue 1.0f; private float maxSliderValue 10.0f; void OnGUI() { GUILayout.BeginArea (new Rect (0,0,200,60)); GUILayout.BeginHorizontal(); if (GUILayout.RepeatButton (Increase max\nSlider Value)) { maxSliderValue 3.0f * Time.deltaTime; } GUILayout.BeginVertical(); GUILayout.Box(Slider Value: Mathf.Round(sliderValue)); sliderValue GUILayout.HorizontalSlider (sliderValue, 0.0f, maxSliderValue); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndArea(); } }7.5 GUILayoutOption的使用可将GUILayoutOption类作为 GUILayout 控件的最终参数可覆盖自动布局的一些默认参数public static bool Button(string text, params GUILayoutOption[] options) { return DoButton(GUIContent.Temp(text), GUI.skin.button, options); }void OnGUI () { GUILayout.BeginArea (new Rect (100, 50, Screen.width-200, Screen.height-100)); GUILayout.Button (I am a regular Automatic Layout Button); GUILayout.Button (My width has been overridden, GUILayout.Width (95)); GUILayout.EndArea (); }八.复合控件可以在单独文件中通过使用 Static 函数创建复合控件。记住需要在函数末尾返回正确的值以使其具有交互性。using UnityEngine; public class CompoundControls : MonoBehaviour { public static float LabelSlider (Rect screenRect, float sliderValue, float sliderMaxValue, string labelText) { GUI.Label (screenRect, labelText); screenRect.x screenRect.width; sliderValue GUI.HorizontalSlider (screenRect, sliderValue, 0.0f, sliderMaxValue); return sliderValue; } }using UnityEngine; public class Example : MonoBehaviour { public Color myColor; void OnGUI () { myColor RGBSlider (new Rect (10,10,200,30), myColor); } Color RGBSlider (Rect screenRect, Color rgb) { rgb.r CompoundControls.LabelSlider (screenRect, rgb.r, 1.0f, Red); screenRect.y 20; rgb.g CompoundControls.LabelSlider (screenRect, rgb.g, 1.0f, Green); screenRect.y 20; rgb.b CompoundControls.LabelSlider (screenRect, rgb.b, 1.0f, Blue); return rgb; } }
返回列表