Unity-------------------------关于GUI绘制的编程
转载:在这篇文章中我将给读者介绍Unity中的图形用户界面(GUI)编程.Unity有一个非常强大的GUI脚本API.它允许你使用脚本快速创建简单的菜单和GUI.
简介
Unity提供了使用脚本创建GUI界面的能力.在写这篇文章的时候,Unity还没有提供一套原生的可视化GUI开发工具,尽管你可能会在Unity Asset商店找到一些使用某种形式的图形化脚本编程编写GUI的工具.Autodesk Scaleform也提供了一个可以单独购买并整合进Unity的插件但这超出了这篇文章的范围.如果你对Scaleform插件的unity版本感兴趣,我推荐你看看Scaleform Unity Plugin.
Unity提供了两个主要的类来创建GUI.GUI类用于创建手动放置的GUI控件.GUILayout类用于创建自动放置的GUI控件.这两个类之间的区别将在文章后面搞清楚.
Unity也提供了GUISkin资源(asset翻译成套件?).它可以被应用于给你的GUI控件提供一种通用的的"外观和感觉".一个GUISkin只是GUIStyle对象的集合.每个GUIStyle对象定义了单个GUI控件的样式,比如按钮,标签或者文本域.
GUiText组件可被用于渲染单个的文本元素,GUITexture组件可以被用于渲染2D材质到屏幕.GUIText和GUITexture都适用于为你的游戏绘制GUI元素(就像HUD),但这些组件不适用于在游戏中绘制菜单.对于游戏中的菜单(像等级选择和选项设置页面)你应该使用GUI和GUILayout类.
这些不同的类,资源(Asset)和组件每一个本文中都会阐述
创建菜单
首先我讲述一下如何在使用GUI和GUILayout在Unity中创建菜单.我也会向你展示如何使用GUISkin和GUIStyle来自定义GUI控件的外观
OnGUI回调函数
GUI的渲染是通过创建脚本并定义OnGUI函数来执行的.所有的GUI渲染都应该在该函数中执行或者在一个被OnGUI调用的函数中执行
ButtonDemo.js
- function OnGUI()
- {
- var buttonWidth = 100;
- var buttonHeight = 50;
- var buttonX = (Screen.width - buttonWidth) / 2.0f;
- var buttonY = (Screen.height - buttonHeight) / 2.0f;
- //在屏幕中间绘制一个button组件
- if(GUI.Button(Rect(buttonX,buttonY,buttonWidth,buttonHeight),"Press Me!"))
- {
- //在调试控制台打印一些文字
- Debug.Log("Thanks!");
- }
- }
脚本ButtonDemo.js将会在屏幕中间绘制一个按钮,松开按钮文字"Thanks!"就会被打印到调试控制台.
GUIContent
大多数通用控件比如按钮和标签允许你指定控件上该呈现在控件上的的文本或者材质.如果你想在一个控件上指定文本与材质,那必须使用GUIContent结构.
CUIContent结构有几个构造函数允许你创建一个带有文本,材质和tooltip的CUIContent对象.
下面的例子扩展了之前的例子,但在这个例子中按钮的内容由GUIContent结构指定.
ButtonDemo.js
- #pragma strict
- var texture:Texture;
- var text:String = "hello text";
- var toolTip:String = "hello toolTip";
- function OnGUI()
- {
- var buttonWidth = 100;
- var buttonHeight = 50;
- var buttonX = (Screen.width - buttonWidth) / 2.0f;
- var buttonY = (Screen.height - buttonHeight) / 2.0f;
- //在屏幕中心绘制一个带有文本和图像的按钮
- if(GUI.Button(Rect(buttonX,buttonY,buttonWidth,buttonHeight),GUIContent(text,texture,toolTip)))
- {
- //在调试控制台打印一些文字
- Debug.Log("Thanks!");
- }
- }
改进后的ButtonDemo.js脚本将会在屏幕上显示一个文本与材质.材质,文本和tooltip参数可以在检视器(inspector)中指定.
ButtonDemo.js脚本会产生如下结果.
放置控件
使用GUI类你必须手动的摆放屏幕上的控件.控件使用GUI静态函数的position参数来摆放.为了在屏幕上摆放控件,必须将一个Rect结构作为第一个参数传递给GUI控件函数.Rect结构的为控件定义了X,Y,Width,Height属性.X,Y,Width和Height单位都是像素.
Screen.width和Screen.height属性可以被用于检视当前屏幕的范围.
脚本ScreenDimension.js可以被用于渲染上面的截图.
ScreenDimensions.js
- function OnGUI()
- {
- var width = Screen.width;
- var height = Screen.height;
- GUI.Label(Rect(0,0,100,20),"Top Left");
- GUI.Label(Rect(width - 100,0,100,20),"Top Right");
- GUI.Label(Rect(0,height - 20,100,20),"Bottom Left");
- GUI.Label(Rect(width - 100,height - 20,100,20),"Bottom Right");
- }
ScreenDimension.js脚本将绘制4个标签.每个标签都使用Screen.width和Screen.height属性来决定其屏幕位置并对齐到屏幕角落里(测量单位为像素)
GUI类
GUI类是Unity用于将控件渲染到屏幕上的主要类.GUI类使用手动摆放来决定屏幕上控件的位置.这意味着在渲染控件时你必须显式的指定控件在屏幕上的位置.使用这种方法手动摆放控件需要多做些工作但他可以让你精确地控制屏幕上的控件位置.如果你不想手动的指定GUI控件的位置,那你应该使用GUILayout类.我们后面再详细阐述GUILayout.
GUI控件
在下面的章节中,我将介绍在使用GUI和GUILayout时可利用的不同控件这些类提供的默认控件是box,button,label,window,texture,scroll bars,sliders,textfield,textarea,toggle和toolbar
GUI.BUTTON
可能你最常用的控件之一就是按钮了.你可以使用GUI.Button()静态函数来创建一个按钮.这个函数用于将按钮渲染到屏幕上,当松开按钮时函数返回true.
这里值得一说的是GUI.Button函数只会在鼠标在按钮上按下并且在按钮上松开时才返回true,如果用户按下按钮移动鼠标在按钮外面释放鼠标,则函数不会返回TRUE,同样的如果用户按下了鼠标之后将光标移动到按钮上然后释放鼠标该函数也不会返回TRUE.要使该函数返回true,鼠标必须在按钮上按下并释放.
以下代码可用于使用按钮创建一个简单的等级选择屏幕(假定你在Build Settings对话框中有多个场景文件要设置)
LevelSelect.js
- function OnGUI()
- {
- var groundWidth = 120;
- var groundHeight = 150;
- var screenWidth = Screen.width;
- var screenHeight = Screen.height;
- var groupx = (screenWidth - groundWidth) / 2;
- var groupy = (screenHeight - groundHeight) / 2;
- GUI.BeginGroup(Rect(groupx,groupy,groundWidth,groundHeight));
- GUI.Box(Rect(0,0,groundWidth,groundHeight),"Level Select");
- if(GUI.Button(Rect(10,30,100,30),"Level 1"))
- {
- Application.LoadLevel(1);
- }
- if(GUI.Button(Rect(10,70,100,30),"Level 2"))
- {
- Application.LoadLevel(2);
- }
- if(GUI.Button(Rect(10,110,100,30),"Level 3"))
- {
- Application.LoadLevel(3);
- }
- GUI.EndGroup();
- }
将脚本添加到空的场景中会产生如下结果:
你也许会想看看Unity脚本参考里的GUI.Toggle和GUI.RepeatButton,这些与GUI.Button控件类似但略有不同的功能.
GUI.Label
GUI.Label()静态函数用于绘制一个标签.标签通常实在屏幕上指定位置绘制的文字.标签控件最常用的是在菜单屏幕中指定选项名称(比如文本框和文本域).
标签可包含文字,材质或者两者兼有(使用之前讲过的GUIContent结构)
下面的例子在屏幕上显示绘制了两个选项.选项名称和滑块的值使用标签呈现
OptionsMenu.js
- #pragma strict
- private var masterVolume:float = 1.0;
- private var sfxVolume:float = 1.0;
- function OnGUI()
- {
- var groupWidth = 380;
- var groupHeight = 110;
- var screenWidth = Screen.width;
- var screenHeight = Screen.height;
- var groupX = (screenWidth - groupWidth) / 2;
- var groupY = (screenHeight - groupHeight) / 2;
- GUI.BeginGroup(Rect(groupX,groupY,groupWidth,groupHeight));
- GUI.Box(Rect(0,0,groupWidth,groupHeight),"Audio Settings");
- GUI.Label(Rect(10,30,100,30),"Master Volume");
- masterVolume = GUI.HorizontalSlider(Rect(120,35,200,30),masterVolume,0.0,1.0);
- GUI.Label(Rect(330,30,50,30),"(" + masterVolume.ToString("f2") + ")");
- GUI.Label(Rect(10,70,100,30),"Effect Volume");
- sfxVolume = GUI.HorizontalSlider(Rect(120,75,200,30),sfxVolume,0.0,1.0);
- GUI.Label(Rect(330,70,50,30),"(" + sfxVolume.ToString("f2") + ")");
- GUI.EndGroup();
- }
OptionsMenu.js脚本运行结果如下:
你也应该改看看GUI.TextField和GUI.TextArea这些控件允许你创建可编辑文字输入控件.
GUI.HorizontalSlider和GUI.verticalSlider
GUI.HorizontalSlider和GUI.verticalslider静态函数可相应的用于绘制水平和竖直滑块.滑块用于指定在一定范围内的一个数值.在上面的例子中,使用了两个水平滑块来指定主音量和音效范围为0到1
Slider函数接受当前滑块值和滑块最小值和滑块最大值.上面的例子展示了如何使用水平滑块,竖直滑块使用与水平滑块同样的参数只是滑块是竖直绘制而不是水平绘制.
下面的例子展示了使用竖直滑块来创建一个音频均衡器
- #pragma strict
- private var equalizerValues = new float[10];
- function OnGUI()
- {
- var groupWidth = 320;
- var groupHeight = 260;
- var screenWidth = Screen.width;
- var screenHeight = Screen.height;
- var groupX = (screenWidth - groupWidth) / 2;
- var groupY = (screenHeight - groupHeight) / 2;
- GUI.BeginGroup(Rect(groupX,groupY,groupWidth,groupHeight));
- GUI.Box(Rect(0,0,groupWidth,groupHeight),"Equalizer");
- for(var i = 0; i < equalizerValues.Length; i++)
- {
- equalizerValues[i] = GUI.VerticalSlider(Rect(i * 30 + 20,30,20,200),equalizerValues[i],0.0,1.0);
- }
- GUI.EndGroup();
- }
结果应类似下面的:
当使用水平滑块时,最小值在滑块的左边最大值在滑块的右边.当使用竖直滑块时,最小值在顶部,最大值在滑块底部.
您可能也想看看GUI.HorizontalScrollbar和GUI.VerticalScrollbar它们类似于滑块,但具有不同的功能。
GUI.WINDOW和GUI.DRAGWINDOW
GUI类提供了在屏幕上绘制窗口的函数,窗口可以使用外部函数(除了OnGUI)来渲染窗口的内容.
如果在窗口的回调函数中使用GUI.DragWindow函数,那窗口将会是可拖动的.
下面的代码创建了一个简单而可拖动的窗口
DraggableWindow.js
- #pragma strict
- //窗口的初始位置以及大小
- private var windowRect0 = Rect(20,20,150,0);
- function OnGUI()
- {
- //渲染窗口ID为0
- windowRect0 = GUILayout.Window(0,windowRect0,WindowFunction,"Draggable Window");
- }
- function WindowFunction()
- {
- GUILayout.Label("This is a draggable window!");
- //窗口的拖条(drag-strip),坐标相对于窗口的左上角
- GUI.DragWindow(Rect(0,0,150,20));
- }
如果在新场景中将脚本应用到GameObject上,你就会看到窗口,点击并拖动窗口标题你就可以在屏幕上把窗口拖来拖去.
在窗口中可以放置任意数量的控件.如果你想要Unity在窗口中自动布局控件(就像例子中一样)那你应该使用GUILayout.Window函数而不是GUI.Window函数.当使用GUILayout.Window函数时,unity会自动修改窗口的高度以适应内容.就像上面的例子展示的一样.
自动布局
在这里展示的绝大数例子,我都是用GUI类来创建菜单.GUI类需要我们手动地在屏幕上放置空间,在某些情况下,手动摆放控件很有用,但如果你想要unity为你自动布局控件,那你需要使用GUILayout类.这个类提供了许多像GUI一样的功能,但不要求你指定控件的大小
GUILayout.beginHorizontal和guilayout.beginVertical
默认情况下,当使用GUILayout函数时所有的视图中的组件都会竖直排列.你可以使用guilayout.beginhorizontal和guilayout.endhorizontal静态函数使控件相邻排放.每出现一次guilayout.BeginVertical必须有对应的GUILayout.EndVertical与其对应,每出现一次GUILayout.BeginHorizontal则必须有对应的GUILayouyudHorizontal与其对应
下面的例子展示了如何使用竖直和水平布局来创建复杂的表格
UserForm.js
- #pragma strict
- private var firstName:String = "First Name";
- private var lastName:String = "Last Name";
- private var age:uint = 0;
- private var submitted:boolean = false;
- private var windowRect0:Rect;
- function Start()
- {
- }
- function OnGUI()
- {
- var screenWidth = Screen.width;
- var screenHeight = Screen.height;
- var windowWidth = 300;
- var windowHeight = 180;
- var windowX = (screenWidth - windowWidth) / 2;
- var windowY = (screenHeight - windowHeight) / 2;
- //将窗口放置到屏幕中间
- windowRect0 = Rect(windowX,windowY,windowWidth,windowHeight);
- GUILayout.Window(0,windowRect0,UserForm,"User information");
- }
- function UserForm()
- {
- GUILayout.BeginVertical();
- //first name
- GUILayout.BeginHorizontal();
- GUILayout.Label("First Name",GUILayout.Width(80));
- firstName = GUILayout.TextField(firstName);
- GUILayout.EndHorizontal();
- //last name
- GUILayout.BeginHorizontal();
- GUILayout.Label("Last Name",GUILayout.Width(80));
- lastName = GUILayout.TextField(lastName);
- GUILayout.EndHorizontal();
- //Age
- GUILayout.BeginHorizontal();
- GUILayout.Label("Age",GUILayout.Width(80));
- var ageText = GUILayout.TextField(age.ToString());
- var newAge = age;
- if(uint.TryParse(ageText,newAge))
- {
- age = newAge;
- }
- GUILayout.EndHorizontal();
- if(GUILayout.Button("Submit"))
- {
- submitted = true;
- }
- if(GUILayout.Button("Reset"))
- {
- firstName = "First Name";
- lastName = "Last Name";
- age = 0;
- submitted = false;
- }
- if(submitted)
- {
- GUILayout.Label("submitted!");
- }
- GUILayout.EndVertical();
- }
这段代码看上去挺复杂的.这里面有些东西如果你不熟悉脚本编写的话可能看起来不熟悉.需要强调的一点是我使用一个静态窗口(不可拖动)的来把控件据合起来.窗口需要一个绘制其内部结构的函数.为此我是用了UseForm函数.
用户表格开头使用竖直布局.因为当使用自动布局时竖直布局是默认的,所以显式的指定它是可有可无的.
之后每一个字段都是用水平布局创建,标签旁边跟着文本.标签被显式的使用GUILayout.Width()函数设置为80像素.我这样做是为了确保所有的文本都整洁的对齐.文本域扩展填充窗口的剩余部分.
在两个文本之后,添加了两个竖直布局的按钮.按钮将扩展填充区域其高度由按钮的内容决定.
不要忘了常使用GUILayout.EndVertical()或GUILayout.EndHorizontal()函数结果竖直或水平布局.
脚本UserForm.js将会产生如下结果:
你可能也想看看GUI.BeginGroup,GUILayout.BeginArea和GUI.BeginScrollView.所有的这些函数都可以被用于创建组(或者可以自动布局的区域),这些组或者区域可以用于保持控件在特定区域内聚合起来.
样式和皮肤
unity为所有的GUI控件提供了默认的外观.作为一个快速解决方案的话默认的样式足够用了,但你可能不想在你要面市的游戏中使用unity的默认GUI样式.
GUISkin
使用自定义的GUISkin你可以更改按钮,标签,滑块,和滚动条的外观.
GUISkin是一个套件(asset),你可以从主菜单中选择Assets>Create>GUISkin来创建它.
如果你在项目视图(project view)里选择了GUISkin,你可以为你可创建的多种控件编辑单独的样式设置.
要使用你自定义的皮肤将默认皮肤替换掉,在GUI脚本里面设置GUI.skin属性为你自定义的皮肤.将GUI.skin属性设置为null将还原回默认的GUISkin.
GUIStyle
GUISkin只是一系列GUIStyle样式的集合.GUIStyle定义了一个控件所有可变状态的样式.一个控件有以下状态:
- 正常状态:控件的默认状态.鼠标既没有悬停到控件上控件也没有获得系统焦点.
- 悬停状态:鼠标当前悬停在控件上
- 注视状态:当前正选择控件,选中的控件将会接受键盘输入.这个状态对于按钮和可编辑文本控件.
- 活动状态:控件被点击,这个状态对于按钮,滑块和滚动条都是合法的.
GUIStyle可以在没有GUISkin的情况下使用以便改写控件的样式.要使用GUIStyle,简单的在脚本中创建一个GUIStyle类型的公开变量并在检视器(inspecot),当你想要为控件应用样式.简单把样式作为控件函数的最后一个参数数传进去就行.
作为练习,下载下面的Unity包并将其导入一个新的Unity工程中:
使用下面代码,创建一个名称为LevelSelect.js的脚本.
LevelSelect.js
- #pragma strict
- function OnGUI()
- {
- var groundWidth = 120;
- var groundHeight = 150;
- var screenWidth = Screen.width;
- var screenHeight = Screen.height;
- var groupx = (screenWidth - groundWidth) / 2;
- var groupy = (screenHeight - groundHeight) / 2;
- GUI.BeginGroup(Rect(groupx,groupy,groundWidth,groundHeight));
- GUI.Box(Rect(0,0,groundWidth,groundHeight),"Level Select");
- if(GUI.Button(Rect(10,30,100,30),"Level 1"))
- {
- Application.LoadLevel(1);
- }
- if(GUI.Button(Rect(10,70,100,30),"Level 2"))
- {
- Application.LoadLevel(2);
- }
- if(GUI.Button(Rect(10,110,100,30),"Level 3"))
- {
- Application.LoadLevel(3);
- }
- GUI.EndGroup();
- }
你可能注意到这就是上面按钮例子里面的代码,但是现在我们要为这些按钮设置一套自定的皮肤.
在检视器(inspector)中,在Button Style属性中设置如下选项:
- Normal.Background: roundedButton_Normal.psd
- Normal.Text Color: (0, 0, 0, 255)
- Hover.Background: roundedButton_Hover.psd
- Hover.Text Color: (0, 0, 0, 255)
- Active.Background: roundedButton_Active.psd
- Active.Text Color: (80, 80, 255, 255)
- Border.Left: 6
- Border.Right: 6
- Border.Top: 6
- Border.Bottom: 6
- Padding.Left: 6
- Padding.Right: 6
- Padding.Top: 12
- Padding.Bottom: 6
- Font: SHOWG
- Alignment: Middle Center
你会得到类似于下面的展示的.
Demo
下面是一个交互demo,它展示了如何使用多种控件,demo包含如下场景:
- GUI基础:描述了OnGUI函数并展示了一个使用按钮和箱子(box)组件的例子
- 控件:这个场景展示了多种你能创建的组件
- 自定义:如何创建皮肤和样式
- 布局:讲述了固定和自动布局模式.也展示了一个使用竖直和水平布局的例子
- 扩展Unity编辑器:这个场景展示了一个如何在unity中创建自定义编辑器窗口.下载这个unity工程并将其加载到Unity来看自定义的编辑器窗口.
下载并解压zip文件,在unity编辑器中打开Assets/Scenes/Introduction.unity场景文件
Unity-------------------------关于GUI绘制的编程的更多相关文章
- Unity用GUI绘制Debug/print窗口/控制台-打包后测试
Unity游戏视窗控制台输出 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- c++学习书籍推荐《C++ GUI Qt 4编程(第2版)》下载
下载地址:点我 百度云及其他网盘下载地址:点我 编辑推荐 <C++ GUI Qt 4编程(第2版)>讲授的大量Qt4编程原理和实践,都可以轻易将其应用于Qt4.4.Qt4.5及后续版本的Q ...
- Unity中OnGUI绘制贪吃蛇
Square.cs : public class Square : MonoBehaviour { public int row, col; public Rect rect; public Text ...
- 用Python做2048游戏 网易云课堂配套实验课。通过GUI来体验编程的乐趣。
第1节 认识wxpython 第2节 画几个形状 第3节 再做个计算器 第4节 最后实现个2048游戏 实验1-认识wxpython 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiy ...
- Unity3D编辑器扩展(三)——使用GUI绘制窗口
前两篇分别讲解了创建菜单https://www.cnblogs.com/xiaoyulong/p/10115053.html和创建窗口https://www.cnblogs.com/xiaoyulon ...
- Unity使用OpenGL绘制经纬线圈
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LatLonGr ...
- python tkinter GUI绘制,以及点击更新显示图片
tkinter 绘制GUI简单明了,制作一些简单的GUI足够,目前遇到的一个问题是不能同时排列显示多幅图片(目前没找到同时显示解决方法), 退而求其次,改成增加一个update按钮,每次点下按钮自动更 ...
- opencv实现人脸识别(五) 运用tkinter进行GUI绘制 整合人脸识别模块
因为之前学习过tkinter库,所以在学习了人脸识别模块的编写后, 打算绘制一个简单的GUI来应用人脸识别功能. 主界面如下所示: 签到打开在点开后直接进行人脸识别,如果成功则自动关闭视频窗口. 录入 ...
- Java基础(二十三)GUI图形界面编程(Java基础完)
这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...
随机推荐
- 每日英语:What You Like Best: Shopping, Food and Tech
In a year that featured one of history's biggest corporate buyouts, a stock-market surge reminiscent ...
- python将列表元素按指定数目分组
比如,有时候,我们需要将列表中的元素,按照每5个分组,分成好几个组时,可以采用下面的代码 a = [1,2,3,4,5,6,7,8,9,10,11] step = 5 b = [a[i:i+step] ...
- 【Android】Android消息处理机制
三大核心类 android的消息处理有三个核心类:Looper,Handler和Message. 其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了 Looper ...
- Java获取 ISO 8601格式时间
https://blog.csdn.net/fang323619/article/details/74909587 ****************************************** ...
- 7款让人惊叹的HTML5粒子动画特效
HTML5的很大一个优势就是可以更加便捷高效地制作网页粒子动画特效,特别是Canvas特性,可以实现在网页上绘制任何图形和动画.本文要分享7款让人惊叹的HTML5粒子动画特效,这些粒子特效都提供源代码 ...
- Delphi调用JAVA的WebService上传XML文件(XE10.2+WIN764)
相关资料:1.http://blog.csdn.net/luojianfeng/article/details/512198902.http://blog.csdn.net/avsuper/artic ...
- 基于jQuery果冻式按钮焦点图切换代码
基于jQuery果冻式按钮焦点图切换代码.这是一款基于jQuery+CSS3实现的图片切换代码.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div class=&quo ...
- with open
再考虑一个场景,要读取文件内容,并把年龄和名字的顺序交换存成新文件age_name.txt,这时可以同时打开两个文件:with open('name_age.txt', 'r') as fread, ...
- [转]mybatis如何直接 执行传入的任意sql语句 并按照顺序取出查询的结果集
原文地址:https://www.cnblogs.com/wuyun-blog/p/5769096.html 需求: 1.直接执行前端传来的任何sql语句,parameterType="St ...
- Mockito 简单使用
有一个月没写博客了,以后再忙也要抽时间写啊. 目的 正常情况下,如果要对 UserService 中方法的测试,那么其依赖的 UserDao 也要可以调通,但是,UserDao 可能并不是直接到 DB ...