Why
主要用来创建调试工具、创建自定义属性面板、创建新的Editor窗口和工具达到扩展编辑器效果。
OnGUI不建议使用在项目UI中。因为效率的问题现在已经很少使用了,但在Editor脚本中,如果你需要扩展一下Unity编辑器的功能,那掌握该GUI的编写还是非常必要的。
官方给出了三种该UI的用途:
1.游戏中Debug时需要显示一些简单的UI;
2.给Component脚本创建一个自定义的Inspector;
3.创建一个Editor Window,扩展Unity本身。
有时候想要输出一些数据到屏幕上方便查看,新建一个UI对象又挺麻烦,用OnGUI()在屏幕上直接绘制UI比较方便。
GUI.Label(new Rect(100, 100, 200, 80), “aaa", style);
这条语句在屏幕中绘制了一个Label,第一个参数给出了位置和大小,第二个参数是要显示的内容,第三个参数可以省略,是所绘制Label的样式。
GUI.Label(new Rect(100, 100, 200, 80),"<color=#00ff00><size=30>"+"aaa"+"</size></color>", style);
在要显示的内容前后加上标签同样也是支持的,但只支持color,size,b和i。
完整代码如下:
private void OnGUI()
{
GUIStyle style = new GUIStyle
{
border = new RectOffset(10, 10, 10, 10),
fontSize = 50,
fontStyle = FontStyle.BoldAndItalic,
};
// normal:Rendering settings for when the component is displayed normally.
style.normal.textColor = new Color(200/255f, 180/255f, 150/255f); // 需要除以255,因为范围是0-1
GUI.Label(new Rect(100, 100, 200, 80), “aaa", style);
GUI.Label(new Rect(Screen.width - 100, Screen.height - 100, 200, 80),
"<color=#00ff00><size=30>"+"aaa"+"</size></color>", style); // 支持标记语言(什么富文本?
// 只支持color,size,b,i
}
OnGUI()函数生命周期
OnGUI()函数是每帧执行一次吗
Update()和OnGUI()有什么区别?
OnGUI() 会在渲染和处理GUI时间时调用,
简单理解就是分线程执行,执行先后顺序是:Awake线程->Start线程->FixedUpdate线程->Update线程->LateUpdate线程->OnGUI线程.
(注意:OnGUI 可以每帧调用多次,小心使用 , )
也就是如果OnGUI()里面事件方法一直在调用的话,OnGUI就会被重复调用 發生時可能一幀執行多次。它是依據事件,與幀無關。
|
OnGUI() 会在渲染和处理GUI时间时调用
这意味着你的OnGUI程序将会在每一帧被调用。要得到更多的GUI事件的信息查阅Event。如果Monobehaviour的enabled属性设为false,OnGUI()将不会被调用。(MonoBehaviour 是每个脚本派生的类的基类。)
OnGUI()每帧至少调用两次,以下程序可以证实。(update执行一次,OnGUI执行两次)
private int a=1;
// Update is called once per frame
void Update () {
a++;
}
void OnGUI(){
Debug.Log(a);
}
What
OnGUI是Unity中通过代码驱动的GUI系统
在脚本中添加OnGUI方法后,UI可以使用代码进行完全控制.
以下是一个OnGUI使用的小例子:
void OnGUI()
{
if (GUILayout.Button("点我"))
Debug.Log("Hello!");
}
把上面的方法放到任意一个脚本中,然后挂到场景中,运行后就能看到左上角一个按钮,点击就会执行if中的方法。
How
布局上,坐标系原点在屏幕左上角。
https://docs.unity3d.com/Manual/gui-Controls.html
Box矩形框
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestOnGUI : MonoBehaviour
{
void OnGUI()
{
GUI.Box(new Rect(10,10,100,90),"看这里!");
}
}
Button按钮
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestOnGUI : MonoBehaviour
{
void OnGUI()
{
if (GUI.Button(new Rect(20, 40, 80, 20), "点这里!"))
{
Debug.Log("OK");
}
}
}
Label标签
标签是非交互式的。只供展览。无法单击或以其他方式移动。最好只显示信息。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestOnGUI : MonoBehaviour
{
void OnGUI()
{
GUI.Label(new Rect(25, 25, 100, 30), "Label");
}
}
RepeatButton按住后会重复执行单击操作的按钮
点击按钮时,每帧执行一次。
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
void OnGUI()
-
{
-
if (GUI.RepeatButton(new Rect(25, 25, 100, 30), "RepeatButton"))
-
{
-
Debug.Log("OK");
-
}
-
}
-
}
TextField单行输入框
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private string textFieldString = "text field";
-
void OnGUI()
-
{
-
textFieldString = GUI.TextField(new Rect(25, 25, 100, 30), textFieldString);
-
}
-
}
TextArea多行输入框
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private string textAreaString = "text area \ntext area";
-
void OnGUI()
-
{
-
textAreaString = GUI.TextArea(new Rect(25, 25, 100, 60), textAreaString);
-
}
-
}
Toggle单选框
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private bool toggleBool = true;
-
void OnGUI()
-
{
-
toggleBool = GUI.Toggle(new Rect(25, 25, 100, 30), toggleBool, "Toggle");
-
}
-
}
Toolbar工具栏
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private int toolbarInt = 0;
-
private string[] toolbarStrings = { "Toolbar1", "Toolbar2", "Toolbar3" };
-
void OnGUI()
-
{
-
toolbarInt = GUI.Toolbar(new Rect(25, 25, 250, 30), toolbarInt, toolbarStrings);
-
}
-
}
SelectionGrid网格选择形式
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private int selectionGridInt = 0;
-
private string[] selectionStrings = { "Grid 1", "Grid 2", "Grid 3", "Grid 4" };
-
void OnGUI()
-
{
-
selectionGridInt = GUI.SelectionGrid(new Rect(25, 25, 300, 60), selectionGridInt, selectionStrings, 2);
-
}
-
}
HorizontalSlider水平滑动条
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private float hSliderValue = 0.0f;
-
void OnGUI()
-
{
-
hSliderValue = GUI.HorizontalSlider(new Rect(25, 25, 100, 30), hSliderValue, 0.0f, 10.0f);
-
}
-
}
VerticalSlider垂直滑动条
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private float vSliderValue = 0.0f;
-
void OnGUI()
-
{
-
vSliderValue = GUI.VerticalSlider(new Rect(25, 25, 100, 30), vSliderValue, 10.0f, 0.0f);
-
}
-
}
HorizontalScrollbar水平滚动条
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private float hScrollbarValue;
-
void OnGUI()
-
{
-
hScrollbarValue = GUI.HorizontalScrollbar(new Rect(25, 25, 100, 30), hScrollbarValue, 1.0f, 0.0f, 10.0f);
-
}
-
}
VerticalScrollbar垂直滚动条
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private float vScrollbarValue;
-
void OnGUI()
-
{
-
vScrollbarValue = GUI.VerticalScrollbar(new Rect(25, 25, 100, 30), vScrollbarValue, 1.0f, 10.0f, 0.0f);
-
}
-
}
ScrollView滚动视图
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private Vector2 scrollViewVector = Vector2.zero;
-
private string innerText = "I am inside the ScrollView";
-
void OnGUI()
-
{
-
// Begin the ScrollView
-
scrollViewVector = GUI.BeginScrollView(new Rect(25, 25, 100, 100), scrollViewVector, new Rect(0, 0, 400, 400));
-
// Put something inside the ScrollView
-
innerText = GUI.TextArea(new Rect(0, 0, 400, 400), innerText);
-
// End the ScrollView
-
GUI.EndScrollView();
-
}
-
}
Window窗口,控件的可拖动容器
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private Rect windowRect = new Rect(20, 20, 120, 50);
-
void OnGUI()
-
{
-
windowRect = GUI.Window(0, windowRect, WindowFunction, "My Window");
-
}
-
void WindowFunction(int windowID)
-
{
-
// Draw any Controls inside the window here
-
Debug.Log("WindowFunction");
-
}
-
}
changed判断数据变化
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
private float hSliderValue = 0.0f;
-
void OnGUI()
-
{
-
hSliderValue = GUI.HorizontalSlider(new Rect(25, 25, 100, 30), hSliderValue, 0.0f, 10.0f);
-
if (GUI.changed)
-
{
-
Debug.Log(hSliderValue);
-
}
-
}
-
}
BeginGroup/EndGroup
分组
组内成员坐标相对于组的坐标。
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
public class TestOnGUI : MonoBehaviour
-
{
-
void OnGUI()
-
{
-
GUI.BeginGroup(new Rect(Screen.width/2-50,Screen.height/2-50,300,300));
-
GUI.Box(new Rect(0,0,200,200),"我的界面");
-
GUI.Button(new Rect(20, 50, 100, 30),"我是个按钮!");
-
GUI.EndGroup();
-
}
-
}
http://www.cnblogs.com/sanyejun/p/8483759.html
https://blog.csdn.net/u011480667/article/details/77542226
一些基本使用:
GUI.Button可以创建一个按钮、GUI.Box则能创建一些简单的信息,其中Box的第一个参数Rect需要四个int参数,前两个是对锚点的偏移,而后两个是Box本身的宽高。
在UGUI中,大家一开始就会接触锚点和轴点以保证UI的适配,而在OnGUI中没有那么明显的设置,需要通过Screen.Width和Screen.height获取当前屏幕的宽高来手动调节锚点。
举两个例子:
1.右上:new Rect(Screen.width - 100, 0, 100, 50);
2.中央:new Rect((Screen.width - 100) / 2 , (Screen.heigth - 50) / 2, 100, 50)。
通常GUI的第一个参数就是上面的Rect,而第二个参数能控制显示具体的内容:string、Texture2D。
如果需要string和Texture2D同时显示,则可以使用GUIContent类,不过提供的显示效果有限,只能图片后面跟着文字。
显示控制:
这边介绍一些GUI常用的方法,比如GUI.Label可以创建一个文字标签。
当然比起GUI,更常用的是GUILayout,因为GUILayout可以自动进行布局,而GUI的所有控件的显示必须指定Rect,不过除了是否自动布局这点,其他的都是一样的。
♦ Label
单纯的显示一些文字图片,不能被点击。
♦ Button
按钮,在点击释放的时候就会触发if内的代码。
♦ RepeatButton
同样是按钮,不同的是,按住的时候每帧都会触发if中的事件。我们可以通过下图看到差别:
♦ TextField
提供了可交互功能的Label,用户可以输入文字,返回值是文本框内的文字,用法:tmpStr = GUILayout.TextField(tmpStr)。
♦ TextArea
文本区域,类似TextField,但是他提供了多行显示。
♦ Toggle
复选框,返回值是当前选项的bool值,当然功能没有UGUI的Toggle可以控制显示很多效果。
♦ Toolbar
Toolbar是一组按钮,在同一情况下只能被选中一个,返回值是当前选中的int。UGUI提供的组件比这边的少很多,原因是很多都能进行替代,比如这个Toolbar就可以使用UGUI中的Toggle实现。
♦ SelectionGrid
类似Toolbar,但可以显示多行按钮。
♦ HorizontalSlider
水平的滑动条,最小值和最大值需要自己指定。
♦ VerticalSlider
垂直的滑动条。
♦ HorizontalScrollbar
水平滚动条,其实跟Slider差不多,只是显示效果不太一样。
♦ VerticalScrollbar
垂直滚动条。
♦ ScrollView
滚动视图,自带两个滚动条,返回值是Vector2,指明当前滚动到的位置。参数中第二个Rect指明里面内容的大小。
♦ Window
一个可以拖动的窗口,这个可以看作是一个独立的UI页,需要单独显示在一起的UI组可以放到其中,并且在其回调方法中可以指定被拖动的范围。
// 位置大小设定
Rect rect = new Rect(20, 20, 120, 50);
void OnGUI()
{
rect = GUI.Window(0, rect, WindowFunction, "window");
}
// 拖动时执行的方法
void WindowFunction(int windowID)
{
// 窗口内部按钮
if (GUILayout.Button("btn"))
print("click");
// 指定可以拖动,该Rect并不是想象中的一个拖动范围,只是指定点窗口的哪个区域可以拖动
// 而且可拖动区域不会超过该窗口
GUI.DragWindow(new Rect(0, 0, 120, 50));
}
♦ GUI.changed
当前UI是否变化,可以通过该值来处理值变化后的一些情况。
OK,内容不算多
讨论OnGUI的剩下的内容,包括Skin和Style、Layout自动布局等。OnGUI的研究会对这套系统更加的了解。
Customization 皮肤定制:
这边讲到了GUIStyle和GUISkin,功能是对GUI的界面皮肤进行定制,当然只使用默认皮肤根本也不会影响代码的功能。
可以通过在Project窗口下右键新建一个GUISkin:
这边的GUISkin就包括了一套皮肤,包括Box、Button、Toggle等,而所谓GUIStyle是指某个组件的皮肤,比如点开上图的Box就是一个Style,Button又是另一个Style。
以下是应用一个GUIStyle的代码,只需要添加最后一个参数就OK了:
public GUIStyle customButton;
void OnGUI()
{
GUI.Button(new Rect(10, 10, 150, 20), "I am a Custom Button", customButton);
}
GUISkin的用法是修改当前环境中的皮肤,也很方便:
public GUISkin mySkin;
void OnGUI()
{
GUI.skin = mySkin;
GUI.Button(new Rect(10, 10, 150, 20), "Skinned Button");
}
*需要注意的是别图省事直接修改默认的皮肤了,这样会导致Unity自己本身自带的窗口显示异常,修改皮肤就使用以上两种方法就够了。
自动布局 Layout:
再次强调一遍,GUI类下的组件都是固定摆放的,而GUILayout类是自动布局的,两者功能上是完全相同,区别仅仅是是否自动布局这点。
GUI.BeginGroup(Rect)和GUI.EndGroup()成对使用时,可以改变其中的组件的相对位置,相当于是放在了其父物体下:
void OnGUI()
{
GUI.BeginGroup(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 100));
GUI.Box(new Rect(0, 0, 100, 100), "Group is here");
GUI.Button(new Rect(10, 40, 80, 30), "Click me");
GUI.EndGroup();
}
以上的代码下,虽然Box的位置是(0, 0),但因为使用到了Group放在了中间,所以Box的位置也是在中间。
下面开始讲自动布局。
GUILayout.BeginArea(Rect)和GUILayout.EndArea()成对使用,效果类似于GUI的Group,不多说。
GUILayout中最重要的两个组是BeginHorizontal()和EndHorizontal()、BeginVertical()和EndVertical(),可以自动进行水平和垂直布局:
float sliderValue = 1.0f;
float maxSliderValue = 10.0f;
void OnGUI()
{
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();
}
布局之间的嵌套应用完全也是没有问题的。
一、Label
#region 四个角定位
GUI.Label(new Rect(30, 10, 100, 200), "zzzzzz");GUI.Label(new Rect(30, Screen.height - 50, 100, 200), "zzzzzz");
GUI.Label(new Rect(Screen.width - 50, Screen.height - 50, 100, 200), "zzzzzz");
GUI.Label(new Rect(Screen.width - 50, 10, 100, 200), "zzzzzz");
#endregion
二、Button
GUI.Label(new Rect(30, 30, 100, 200), "Button");
GUI.Button(new Rect(30, 50, 50, 50), "这个是一个按钮");
GUI.Button(new Rect(90, 50, 50, 50), text);
//带图片带文字的按钮
GUIContent guic = new GUIContent("按钮", text);
GUI.Button(new Rect(150, 50, 50, 50), guic);
//按键从上往下排 自动排序
if (GUILayout.Button("1"))
Debug.Log("1");
if (GUILayout.Button("2"))
Debug.Log("2");
if (GUILayout.Button("3"))
Debug.Log("3");
if (GUILayout.Button("4"))
Debug.Log("4");
if (GUILayout.Button("5"))
Debug.Log("5");
if (GUILayout.Button("6"))
Debug.Log("6");
if (GUILayout.Button("7"))
Debug.Log("7");
if (GUILayout.Button("8"))
Debug.Log("8");
三、Toggle控件
GUI.Label(new Rect(30, 100, 100, 200), "Toggle");
toggle1 = GUI.Toggle(new Rect(30, 120, 100, 30), toggle1, "Toggle");
toggle2 = GUI.Toggle(new Rect(30, 150, 100, 30), toggle2, text);
四、滑动条
GUI.Label(new Rect(30, 180, 100, 200), "滑动条");
hSliderValue = GUI.HorizontalSlider(new Rect(30, 200, 100, 30), hSliderValue, 0, 10);
Show("水平滑动条:" + hSliderValue);
vSliderVaule = GUI.VerticalSlider(new Rect(0, 200, 30, 100), vSliderVaule, 0, 10);
五、Toolbar
toolbarInt = GUI.Toolbar(new Rect(30, 250, 250, 30), toolbarInt, new string[] { "功能一", "功能二", "功能 三" });
if (lastValue != toolbarInt)
{
if (toolbarInt == 0)
Debug.Log(1111);
if (toolbarInt == 1)
Debug.Log(2222);
if (toolbarInt == 2)
Debug.Log(3333);
lastValue = toolbarInt;
}
六、Scrollbar
GUI.Label(new Rect(30, 300, 100, 200), "Scrollbar");
hSbarValue = GUI.HorizontalScrollbar(new Rect(30, 320, 100, 30), hSbarValue, 1.0f, 0.0f, 10.0f);
vSbarValue = GUI.VerticalScrollbar(new Rect(0, 320, 30, 100), vSbarValue, 1.0f, 0.0f, 10.0f);
七、菜单
GUI.Box(new Rect(30, 350, 100, 100), "Menu");
if (GUI.Button(new Rect(40, 370, 80, 20), "1"))
八、TextField
useNmae = GUI.TextField(new Rect(Screen.width / 2, Screen.height / 2 - 200, 150, 30), useNmae);
//*****密码字符的掩码字符
passWord = GUI.PasswordField(new Rect(Screen.width / 2, Screen.height / 2 - 150, 150, 30), passWord, '*', 25);
if (GUI.Button(new Rect(Screen.width / 2, Screen.height / 2 - 50, 150, 30), "登录"))
{
isBntLogin = true;
Debug.Log(isBntLogin+ "isBntLogin");
if (useNmae.Equals("admin") && passWord.Equals("123"))
{
isSuccess = true;
GUI.Label(new Rect(500, 350, 150, 30), "登录成功");
}
else
{
isSuccess = false;
GUI.Label(new Rect(500, 350, 150, 30), "登录失败");
}
}
if (isBntLogin)
{
if (isSuccess)
GUI.Label(new Rect(Screen.width / 2, Screen.height / 2 + 50, 150, 30), "登录成功");
else
{
GUI.Label(new Rect(Screen.width / 2, Screen.height / 2 + 50, 150, 30), "登录失败");
}
}
Unity的官方文档中下一篇讲到了对原本的OnGUI进行扩展,其实就是将几个组件封装到一个方法里,不多说了,但是在真正写一个窗口时很重要,比如说Vector3的三个水平的输入框,可以封装成一个方法,以后要调用到类似的就可以直接使用。
引用:
http://blog.sina.com.cn/s/blog_1882ae9cf0102xcf2.html
https://www.cnblogs.com/csymaet/p/9622147.html
https://blog.csdn.net/u011480667/article/details/77542226
https://blog.csdn.net/ncz9_/article/details/88552513