Unity3D4.6UGUI开发设计及案例讲解

发布时间:2021-08-29

word Unity4.6 UGUI开发设计与案例讲解
1 Unity4.6跟以前的版本的最大区别首先在于在层级视图中点鼠标右键时出现的弹出菜单上,它把以前许多的菜单项进展了归类,比如cube sphere capsule.等整合到“3D Object子菜单中,而且多出一个UI子菜单,它就是UI组件了。
当我们点击UI->Canvas时,就会在场景视图里创建一个画布,不过视图默认是3D示方式,Unity4.3以后,增加了一个2D3D转换按钮,单击此按钮可在3D2D显示样式之间转换。 UI2D,为何还要3D呢,在做一些比拟复杂的项目时,给用户看时是2D,但我们编辑时,有时还是要用到3D模式的。 2 Canvas是画布,所有的UI组件就是绘制在这个画布里的,脱离画布,UI组件就不能用。 创建画布有两方式。一是通过菜单直接创建,二是直接创建一个UI组件时,会在创建这个组件的同时自动创建一个容纳该组件的画布出来。 不管那种方式创建出画布时,统都会自动创建出一个EventSystem组件,这是UI的事件系统。
一.Canvas组件
1 Canvas组件的三种渲染模式
Canvas中有一Render Mode属性,它有3个选项,分别对应Canvas的三种渲染模式:Screen Space OverlayScreen Space CameraWorld Space 2 Screen Space Overlay
此模式不需要UI摄像机,UI将永远出现在所有摄像机的最前面〔即在某个UI的前面是不能再添加其他组件的〕,就好似是给摄像机贴上了一层膜。它的最大好处是不需要摄像机,不需要灯光。
3 Screen Space Camera

此模式需要提供一个UICamera,它支持在UI前方显示3D模型与粒子系统等容。 不过此模式下,就需在中给它挂一个摄像机。
当挂上摄像机并选择3D显示模式时,我们选中这个摄像机,并移动它,可发现画布会跟随摄像机的移动而移动,且Game视图显示的UI其位置与大小均保持不变,如如如下图所示:
1 / 114
word
种模式,虽然UI的显示效果与第一种模式没有什么两样,然而,因在画布与摄像机之间可放置三维物体或粒子系统,那么就可做出许多绚丽的特效。
这一项为哪一项设置Canvas与摄像机之间的距离,其值越大,可在画布与摄像机之间放很多的三维物体,默认是100,建议设置为100200之间即可。
4 World Space

这个就是完全3DUI,也就是把UI也当成3D对象,如摄像机离UI远了,其显示就会变小,近了就会变大。
5 其它一些属性:
当有多个画布时,决定谁在前,谁先显示。
二.Canvas Scaler画布的大小

Ui Scale Mode〔大小模式〕
当我们把Canvas中的Render Mode设为Screen Space Overlay Screen Space Camera时,Canvas Scale中的Ui Scale Mode〔大小模式〕就可用,且其中有3个选项:
2 / 114
word 1 Constan Pixel Size:固定像素尺寸

2 Scale With Screen Size以宽度为标准缩放〔屏幕自适应特性〕

2.1 Reference Resolution:参考分辨率
在不同分辨率下,控件显示的大小有所不同,这要根据实际情况综合考虑。
2.2 Screen Match Mode:屏幕匹配模式
Match Width Or Heigt:匹配宽度或高度
此模式下会出现Match调节滑杆,调节其控块位置,也会影响UI元素显示的大小。 Expand:扩展 Shrink:收缩

3 Constant Physical Size:固定物理尺寸

三.Panel 面板
当我们初次创建Panel后,它会充满整个画布,如下左图:

此时通过拖动该面板控件的4个角点或四条边可调节面板的大小,如上右图
面板实际上就是一个容器,在其上可放置其他UI控件,当移动面板时,放在其中的UI组件就会跟随移动,这样我们可以更加合理与方便的移动与处理一组控件。也就是通过面板,我们可以把控件分组。一个功能完备的UI界面,往往会使用多个Panel容器控件。而且一个面板里还可套用其他面板。
当我们创建一个面板后,此面板会默认包含一个Image(Script组件:

该组件中的Source Image是设置面板的图像。
3 / 114
word Color,可改变面板的颜色。
四.EventSystem事件处理系统
当我们创建一个画布时,Unity系统会自动为我们创建一个EventSystem

该事件处理器中有3个组件:
1 Event System:事件系统组件〔事件〕
2 Standalone Input Module:独立输入模块 〔输入〕 3 Touch Input Module:触控输入模块 〔触控〕
如果我们将Event System (Script 前的勾去掉,如此管理整个场景的事件系统如此不起作用了,此时运行程序,如果有Button,单击它时就不会有反响了。
五.Text控件
UGUI中,我们所创建的所有UI控件,它们都有一个UI控件特有的Rect Transform组件:

我们所创建的三维物体,是Transform,而UI控件是Rect Transform,它是UI控件的矩形方位,其中的指的是UI控件在相应轴上的偏移量。
UI控件除了上面Rect Transform控件外,每个UI控件都还一个组件,它是画布渲染,一般不用管它,因它不能点开的。
Text控件的相关属性: Character:〔字符〕
Font:字体
Font Style:字体样式 Font Size:字体大小
4 / 114
word Line Spacing:行间距〔多行〕 Rich Text“富〞文本。例如:UGUIyellow> Color:字体颜色
Paragraph:〔段落〕
:设置文本在Text框中的水平以与垂直方向上的对齐方式。
:水平方向上溢出时的处理方式。它有两种:Wrap隐藏;Overflow溢出。 :垂直方向上溢出时的处理方式。它有两种:Truncate截断;Overflow溢出。
隐藏了或截断了,信息显示不全当然不好,但如果溢出又会破坏版面,想两全齐美的话,就可选中:,如果文字多时,它会自动缩小以适应文本框的大小,当选中该项后,在其下边会出现Min SizeMax Size两输入框,可设置字体变化时的最小与最大值。
六.Image控件
Image控件除了两个公共的组件Rect TransformCanvas Renderer外,默认的情况下就只有一个Image(Script组件:

Source Image是要显示的源图像,但如果我们把一个普通的图像往里拖放时,却不能成功放入,认真研究一下不难发现,放图像的框中,除了None表示还没有图像外,还有一个括号注释的Sprite,它的意思是精灵,可理解为它是贴图的一种特殊形式,它不具备其他功能,只给UI做显示图片用,故我们给它取了一个特殊的名字:精灵Sprite,所以在Unity4.6中,要想把一个图片赋给Image如此需要把该图片转换成精灵格式,转换方法为,Project中选中要转换在图片,然后在Inspector检视图中,单击Texture Type〔纹理类型〕右边的下拉框,在弹出的菜单中,第三项Editor GUI and Legacy GUIUnity4.6以前版本所用的,中它时,图片不会被拉伸,现在几乎不用,是为了兼容,而第四项Sprite(2D and UI,就是4.6版本所用的,它虽然比前一项适用的围更窄,但其效率更高。我们选中该选项Sprite(2D and UI并点击下方的Apply〔应用〕按钮就可把此图片转换成精灵格式,随后就可拖放到ImageSource Imag中了,如如如下图所示:
5 / 114
word

另:当我们把一个普通的图片转换成精灵格式后,在Project中,将发现该图片将包含一个子对象如图:,以后可以把一个图片划分为多个图片。
当我们把精灵图片赋给了Image后,其组件样式如如如下图:

Color:可改变图片的颜色;
Material:材质,这是针对一些复杂的贴图使用。 Image Type:贴图的类型,这是最重要的属性。

1 Simple:简单
6 / 114
word

Preserve Aspect:翻译过来是:维持外貌,选中该项后,该精灵图片的长宽比将保持原状,当调节图片的大小时,它将在保持原长宽比的前提下尽量铺展到图片框中,即不会拉伸或压缩以适应图片框而铺满。
Set Native Size:本来的大小。如果调整后大小变乱了,单击此按钮,可将此图片设置本钱来的大小 2 Sliced:片
应用该种类型时,应先将贴图进展“九宫格〞处理后才可以应用。否如此其下会出现黄色的警告 This Image doesnt have a border这个图片没有边框,如如如下图:

怎样进展九宫格的处理呢?
先在Project中选中该图片精灵,然后在其Inspector检视图中单击“Sprite Editor〞按钮即可进入九宫格处理Sprinte Editor视窗中,如下两个图所示:
7 / 114
word

在这个Sprinte Editor视窗中,我们可以拖动图像四条边上的绿色线,调节九宫格的布局大小,调好后单击顶端的Apply按钮应用即可,回到Image的检视图中,我们将发现原来的警告消失了:

Image TypeSliced时,当对图像进展大小调节时,其中心会缩放以适合矩形,但边界会保持不变,这样当你显示不同尺度图像时,不用担心扩大与缩小时其轮廓会发生变化。如果你只想要边界,不要中心,可以禁用Fill Center〔填充中心〕属性。
3 Tiled:平铺

图像保持其原始大小,重复屡次填补空白。这往往用于做背景。
4 Filled:填充
图像填充满整个Image矩形区域,再结合Fill Amount属性,可做一些特效。
8 / 114
word


当图片类型为Filled时,Image组件的属性视图如上图所示,Fill Method〔填充方法〕选择框中有5种:
Horizontal:水平填充,如果我们手动拖动Fill Amount〔填充数量〕滑块,就可看到图片在水平方向上的填充变化〔动画〕,如如如下图列所示:

Vertical:垂直填充,同理当我们手动拖动Fill Amount滑块,就可看到图片在垂直方向上的填充变化〔动画〕,如如如下图列所示:

Radial 90径向90度填充,同理当我们手动拖动Fill Amount滑块,就可看到图片在90度方向上的填充变化〔动画〕如如如下图列所示,默认是以左下角为圆心,顺时针90度填充。

Radial 180:径向180度填充,同理当我们手动拖动Fill Amount滑块,就可看到图片在180度方向上的填充变化〔动画〕,如如如下图列所示,默认是以底边中点为圆心,顺时针180度填充。
9 / 114
word

Radial 300:径向180度填充,同理当我们手动拖动Fill Amount滑块,就可看到图片在360度方向上的填充变化〔动画〕,如如如下图列所示,默认是以图片的中心点为圆心,顺时针360度填充。


如果我们使用脚本来控制Fill Amount的值,就可制造出这五种动画来,为特效的制作增加了一些有效的手段。

七.Button控件
当我们创建一个Button后,其Inspector视图如下:
10 / 114
word

除了公共的Rect TransformCanvas Renderer两个UI组件外,Button还默认拥有Image(ScriptButton(Script两个组件。
组件Image(Script里的属性与前面所讲的Image控件的Image(Script组件里的属性是一样的,例如Source Image的图像类型仍为一个Sprite〔精灵〕,通过为此赋值,就可改变此Button的外观了,如果你为属性赋值了图片精灵,那么此Button的外观就与此精灵一致了。
Button是一个复合控件,它中还包含一个Text子控件:,通过此子控件可设置Button上显示的文字的容、字体、样式、字大小、颜色等,与前面所讲的Text控件是一样的。
11 / 114
word Button(Script组件里的属性:

1 Interactable:是否启用〔交互性〕
如果你把其后的对勾去掉,此Button在运行时将点不动,即失去交互性了。
2 Transition:过渡方式
它有四个选项,默认为Color Tint〔颜色色彩〕 1 None:没有过渡方式。 2 Color Tint:颜色过渡

Target Graphic:目标图像 Normal Color:正常颜色
Highlighted Color:经过高亮色 Pressed Color:点击色 Disabled Color:禁用色 Color Multiplier:颜色倍数 Fade Duration:变化过程时间
3 Sprite Swap:精灵交换。需要使用一样功能不同状态的贴图。

Target Graphic:目标图像
Highlighted Sprite:鼠标经过时的贴图 Pressed Sprite:点击时的贴图 Disabled Sprite:禁用时的贴图

12 / 114
word 4 Animation:动画。最复杂,效果最绚丽。

其中的Normal TriggerHighlighted TriggerPressed TriggerDisabled Trigger等属性是不能赋值的,它们是自动生成的。
当单击“Auto Generate Animation〞〔自动生成动画〕按钮时,系统会为你打开一New Animation Contoller〔新建动画控制器〕窗口,要求你选择动画存放的路径,所以我们要先在Project中新建一个文件夹,专门用来存放动画,比如此文件夹取名为_Animator,此时就可选中此文件夹,并给此动画取名〔动画的名默认为该Button的名字,当然其扩展名为controller,创建成功后,会在Project中的_Animator文件夹中可看到刚刚创建的动画文件〔动画的名默认为该Button的名字〕,且在这个ButtonInspector检视图中可看到会为此Button增加一个Animator组件:

此组件的Controller的属性值就为刚刚创建的动画,双击它即可打开该动画的Animator窗口,其中记录的有四个动画:NormalHighlightedPressedDisabled〔通常状态、鼠标经过状态、按下状态、失效状态〕,如如如下图所示:
13 / 114
word

其实这个动画还没有,要做出这个动画,需先选中这个Button,然后点击系统菜单Window->Animation〔注意不是Animator,就会打开一个Animation动画编辑窗口:

我们以此工具先来做一个简单的帧动画,在帧数框上单击一下,原来的0便会选中,此时输入数字1,表示对第1帧做动画,此时的录制按钮以与系统的播放按钮和动画编辑窗中的帧数线均会变红,表示现在处于记录模式,你所做的操作会记录成动画的动作,如如如下图所示:
14 / 114
word

假设我们想使它在第一帧时,该按钮变大一点,我们就在Inspector中的Rect TransformrScale中操作,比如在xy轴向上均增大到原来的1.05〔因UI是在x-y平面上显示,故不需设置Z值〕,如如如下图所示:

同理,当第一帧设置完后,我们在帧数框中直接输入数字2就可编辑第2帧的动画了,比如在xy轴向上均增大到原来的1.1倍,再继续设置第3帧在xy轴向上均增大到原来的1.15倍,假设我们现在就只做这3帧动画,已经完成了,那么我们点击一下那个处于红色晕光状态下的录制按钮,完毕录制,再保存一下场景,就会发现在Project视图中_Animator/Button1下会增加4个动画文件DisabledHighlightedNormalPressed〔如果不保存将看不到这4个动画文件〕,这四个动画剪辑就是源于我们刚刚的录制,虽然刚刚我们只录制了一次,而系统会为我们自动产生这四个动画文件。
动画成功制作出来了,可运行起来看看效果了,但当我们运行起来时,就会发现那个按钮会自动无限次地播放那个动画,看起来就是不断地颤动,那么是什么原因呢?
我们在Project视图中,选中任意的一个动画剪辑比如Disabled,在其Inspector视图中可看到它的Loop Time属性是处于选中状态,意思是循环播放,那么我们把它去掉即可。

15 / 114
word 而这里,如果我们只去掉DisabledLoop Time还是不行的,当然把这4个动画剪辑的Loop Time全去掉是能成功的,那么到底是那个剪辑在起作用呢?实际上是Normal所以我们只需去掉NormalLoop Time即可。其原因请看如下表示。
HierarchyButtonWindow->Animation〔注意不是Animator,就会打开刚刚的动画编辑窗口:

单击其中的Normal框,会出现下拉选择:

从这下拉选择列表中可看出Normal前边有个勾,这说明我们刚刚所做的动画是Normal那么根据此原理,我们可分别做出鼠标经过该ButtonHighlightedButton按下的Pressed以与该Button失效的Disabled动画了。
3 Navigation

None:没有
Horizontal:水平 Vertical:垂直 Automatic:自动 Explicit:明确的
16 / 114
word 4 Visualize:显现 5 On Click( Button组件的下方有一个OnClick(选项,这就是Button控件处理事件的重要机制。 OnClick(意思为当该按钮被点击时所发生的事件,而此事件在UI中是委托机制,要理解这个机制,我们先做一些准备工作。
1 建立脚本文件
假设此脚本文件被命名为ButtonEvent using UnityEngine; using System.Collections; public class ButtonEvent : MonoBehaviour { // Use this for initialization void Start ( { }

// Update is called once per frame void Update ( { }
} 这是系统默认的文件容,现在我们要把它应用于UI,故必须引入UI的命名空间,即脚本的首部增加一行:using UnityEngine.UI;
假设我们单击一个按钮后,让系统在后台显示一句话:点击了Button,那么我们可以在此脚本中增加一个方法,该方法为公共的public,假设方法名为DisplayInfo
Public void DisplayInfo({ Print(点击了Button!〞; } 此时整个脚本文件的容如下:
using UnityEngine; using System.Collections; using UnityEngine.UI; public class ButtonEvent : MonoBehaviour { // Use this for initialization void Start ( { }

Public void DisplayInfo({ Print(点击了Button!〞; }
// Update is called once per frame void Update ( { 17 / 114
word }
} 2 Hierarchy视图的Canvas中创建一个空对象,并假设命名为Event,并把上面的脚本作为组件挂到这个空对象上,那么这个对象是具有事件处理能力的object了。
3 某个按钮添加其事件处理的委托对象
我们在层级面板中选中要产生单击事件的按钮比如Button1然后拖动其Inspector面板右边的滚动条,使其Button(Script组件下的OnClick(显现出来:

此时其事件列表为空:List is Empty,我们单击其下的“+〞按钮为其添加一个事件:

此时事件虽被添加了,但其委托的事件处理对象为空:None(Object,当然连事件处理对象都没有,其事件处理方法自然也就为空:No FunctionRuntime Only此项我们可先不管它,以后用到时再讲〕
那么怎样委托事件处理对象与选择事件处理方法呢?
很简单,我们把层级面板中刚刚建好的并已挂上了事件处理脚本的Event对象拖放到None(Object框中即可,此时此框中显示的容即为委托的此事件处理对象的名称了:Event有了事件处理对象了,然后使用该对象的什么方法来处理事件呢?这还需我们给它指定,方法是单击显示容为No Function的那个事件方法框,会弹出菜单列表:

当我们的鼠标指向最后一项ButtonEvent时会继续展开,其中就有我们在脚本中编写的事件处理方法:DiaplayInfo(,选中它即可,这样就完成了事件的委托,当我们运行时,单击那18 / 114
word Button,就会在后台里打印出“点击了Button!〞。
一个按钮可以有多个处理事件。
下面我们采用另一种显示信息的方式。
我们先在场景中的画布上增加一个Text控件,同时设置好相关的显示样式,然后在那个脚本中增加一个公共变量:public Text Txt_Info,回到场景视图中,在层级面板中选中挂有该脚本的对象Event,在其Inspector视图的ButtonEvent脚本组件里就会出现刚刚增设的公共变量名:Txt_Info〔脚本需保存且界面需刷新〕,我们可把增加的那个Text拖到此处即可为此变量赋值了,接下来我们就可通过脚本修改这个文本框控件的Text属性,让打印在后台的信息显示在这个文本框上了。其脚本文件容如下:
using UnityEngine; using System.Collections; using UnityEngine.UI;
public class ButtonEvent : MonoBehaviour { public Text Txt_Info; // Use this for initialization void Start ( { } // Update is called once per frame void Update ( { } public void DisplayInfo({ print ("点击了Button"; }
public void DisplayInfoText ({ Txt_Info.text="Button被点击!"; }
} 然后再给那个Button增加一个单击事件〔委托的事件对象仍为Event,方法如此设为DisplayInfoText (

再次运行程序,单击按钮时,后台输出“点击了Button!〞的同时,场景中的Text本框的容变为:Button被点击了!
Anchor锚点与屏幕自适应
每个控件都有下Anchor的属性,其作用是当改变屏幕分辨率的时候,当前控件做如何的位置变换。即控件的屏幕自适应。
当我们创建一个Canvas后,在层级视图中选中它后,我们将发现这个Canvas在场景视图中的样式如如如下图所示:
19 / 114
word

这个Canvas除四边、四个角点外,其中心还有一个蓝色的小圆圈,这个小圆圈即为这Canvas的中心点。
如果此时我们在此Canvas上创建一个Button,如如如下图所示:

Button同理也有四条边、四个角点、一个中心点,此时我们选中Button,在Canvas心点位置会出现一个小雪花图案,这就是ButtonCanvas上的锚点,可用鼠标拖动它,且拖动的过程中会实时显示此锚点距上、下、左、右的百分比,如如如下图所示:

而且在ButtonInspector面板中,单击Rect Transform中按钮,会打开一个Anchor 20 / 114
word presets锚点调整窗,如如如下图所示:

如果我们单击 时,其锚点就会跑到Canvas的右上角,如如如下图所示:

同理单击其他位置时,也就把锚点调整到相应的位置上,即可把此锚点调整到画布的中心点上、四个角上、四条边的中点上。
以上是锚点整体移位。实际上,我们还可以拖动小雪花中的任意一个花瓣,使其分散成四个锚点,如如如下图所示:
21 / 114
word

当我们单击这个窗中的最右边或最下边中一些按钮可将锚点分散在两边或上下或四个角点上。
原来这个雪花状的锚点是由四个锚点组成的复合体。 说了这么多,那它到底有什么用途呢? 两个字,定位。
22 / 114
word 如图:,当屏幕大小发生改变时,Button的四个角点与对应的4个锚点的距离会保持不变,从而保证布局不会随着屏幕大小或者分辨率的改变而改变,可相对有效地保证布局不会混乱,以达到屏幕自适应的目的。
但要注意,控件的锚点总是相对于自己的上一级来定义的。例如,我们再在这个Canmas中创建一个Panel并调小它的大小,在Panel中创建一个Text,我们去调节这个Text的锚点时我们将会发现这个锚点总是相对于Text的上一级Panel来定义与变换位置的。
九、应用:登录界面
在画布上:
1 两个Text控件,分别命名为:Tex_UserNametxt_PasswordText值分别为“用户名称:〞与“登录密码:〞
2 两个InputField控件,分别命名为:Inp_UserNameInp_Password
这两个输入域控件是前面还没有介绍的新控件,在其层级Hierarchy视图将其展开,可发现它也为一个复合控件,在主控件上还包含两个子控件,一个为PlaceholderText,其Text就是前面所介绍的文本控件,程序运行时用户所输入的容就保存在这个Text中,而Placeholder是占位符,它表示程序运行时在用户还没有输入容时显示给用户的提示信息,这里我们把它设置为“请输入〞,设置方法是在层级视图中展开这个InputField控件,选中其子控件Placeholder,在Inspecter视图中可发现其Text(Sript组件,修改其值为“请输〞即可,如如如下图所示:

InputField控件与其他控件一样,也有Image(Script组件,自身组件InputField(script也有变换Transition属性,其默认值也为颜色变换,除此之外,它有一个重要的属性:ContentType〔容类型〕,有10个选项,如如如下图:
23 / 114
word

1 Standard:标准的
2 Autocorrected:自动修正 3 Integer Number:整数
4 Decimal Number:十进制小数 5 Alphanumeric:字母数字 6 Name:人名 7 Email Address 8 Password:密码 9 Pin
10 Custom:定制的
据此,我们把第一个InputField的容类型设为第5Alphanumeric:字母数字,第二个InputField的容类型设为第8Password:密码,这样程序就可启用其自动验证功能,例如在用户名称输入框中如果你输入的不是字母或数字如此不能输入进去,第二个密码框中输入密码时它会默认以*号占位输入的密码。
3、创建一个Text,用于显示登录是否成功等提示信息用,在其Inspector视图中,去掉其默认显示的容,即让其才开始运行时不显示任何容,并把其Best Fit勾选上,让其提示信息自适应文本框的大小:
24 / 114
word

4、最后创建一个提交按钮,其整个界面如如如下图所示:

5、创建脚本〔红色局部为新增容〕
using UnityEngine; using System.Collections; using UnityEngine.UI;
public class LogonSystem : MonoBehaviour { public Text Txt_DisplayInfo; public InputField Inp_Username; public InputField Inp_Password; // Use this for initialization void Start ( { }

25 / 114
word public void DisplayInfo({ string strUserName = Inp_Username.text; string strPW = Inp_Password.text; if(CheckLogonInfo(strUserName,strPW{ Txt_DisplayInfo.text="登录成功!"; }else{ Txt_DisplayInfo.text="用户名称或登录密码错误 请重新输入!"; } } private bool CheckLogonInfo(string strUserName,string strPW{ bool ReturnFlag = false; if (strUserName != null && strPW != null { if(strUserName.Trim(.Equals("Admin" && strPW.Trim(.Equals("123456"{//两个输入框中的容去掉前后空格,如果用户名称为Admin、登录密码为123456时,如此表示登录,将ReturnFlag标记为真true
ReturnFlag=true; }
} return ReturnFlag; } } 脚本创建好了后,我们在Hierarchy中创建一个空对象,命名为_LogonSystemEvent把这个脚本挂在它身上,而且在其Inspector视图中,为其3个公共变量赋值〔把相应控件拖放到对应变量的值框中〕

运行程序,如果用户名称或密码错误,提示信息框中会显示:用户名称或登录密码错 请重新输入!,否如此显示:登录成功!,如如如下图所示:

十、Toggle控件动态事件
Toggle:开关,当我们创建它后,可发现它也为一个复合型控件,它有BackgroundLabel两个子控件,Background控件中还有一个Checkmark子子控件,如果我们将其拖散26 / 114
word 可清楚地看见,Background是一个图像控件,而其子控件Checkmark也是一个图像控件,Label控件是一个文本框,它们与我们所讲的控件是一致的,我们通过改变它们所拥有的属性值,即可改变Toggle的外观,如颜色、字体等等。下面来看看Toggle的一些重要属性。
1 Is On:目前是处于开还是关。
当我们运行起来,用鼠标点击那个Toggle按钮,将发现其中的对勾符号会在出现与不出现之间切换,同时与之相对应的,在其Inspector面板中,属性In On后面的对勾也在勾选与不勾选之间切换。
2 Graphic:图像
实际上,用鼠标点击那个Toggle按钮,其对勾符号会在出现与不出现之间切换,它的原理就是控制那个对勾图像出现与不出现而实现的,这个Graphic就是设置这个属性值的,你可点击最后那个设置按钮,在出现的窗体中选择另外的图像如Background,同时将中的Target Graphic的值设为Checkmark,即将它们两者的值互换,将发现,当我们点击Toggle按钮时,其对勾不会消失与出现,而是背景消失与出现。这样做虽然没有多大实用价值,但说明Unity可以方便地控制这个按钮的外观。
3 Group:组〔单项选择框功能〕
Hierarchy面板中,选中我们刚刚创建的Toggle然后按键盘Ctrl+D两次,就可复制出两个Toggle了,并在场景视图中拖动它们的位置,使它们都可见,运行,我们将发现这个三个都可选中,即它们是复选框。
那么怎样做出单项选择的效果呢?
前面所创建的按钮是独立的,互不关联,当然就可独自地选与不选。如果我们把这三个组成一个组,让它们关联,就可做成单项选择了。

Group属性可看出它需要一个ToggleGroup
我们先在画布上建立一个空对象,并命名为_ToggleGroup,在其Inspector中单击这个按钮,为其添加组件,在弹出的菜单中选择UI,在后续弹出菜单中
27 / 114
word

选择“Toggle Group〞,这样我们就为此对象添加了ToggleGroup组件了。
Hierarchy中同时选中要成组的那3Toggle,把已添加了ToggleGroup组件的_ToggleGroup拖到Inspector中即可,这样我们便把这3Toggle成组了,于是它们3个就只能单项选择其中一个了。
为了更完美,首先调整空对象_ToggleGroup的位置与大小,让其包含那3Toggle件,然后在Hierarchy中,把3Toggle选中并拖到_ToggleGroup中成为子物体,这样在逻辑上与外观上均完备,且移动父物体时子物体也会跟着移动。

4 Toggle控件动态事件On Value Changed(Boolean 这是Toggle的事件处理,它与Button的事件有所不同,下面来看看怎样给Toggle添加事件。
我们把Toggle的标签改成装备名称,再在场景中增加一个显示选取的装备名的文本框:

编写脚本:
using UnityEngine;
using System.Collections; 28 / 114
word using UnityEngine.UI;
public class _ToggleEvent : MonoBehaviour { public Text Display; private string info; // Use this for initialization void Start ( { } public void Toggle1(bool isclik{
if (isclik { info="屠龙宝刀"; Display.text=info; } } public void Toggle2(bool isclik{ if (isclik { info="倚天剑"; Display.text=info; } } public void Toggle3(bool isclik{
if (isclik { info="降龙十八掌"; Display.text=info; } }
} Canvas中创建一个空对象,把此脚本挂接到此对象上,并把场景中的Text赋给public Text Display这个变量,然后分别选中那3Toggle在其检视图中单击事件下的+〞号:单击后就为该控件添加了事件,如如如下图:

然而,事件要委托给一对象,现在还没有,显示的是,此时把已经挂接上了脚本的那个空对象拖放到此处,便委托事件处理对象了,如如如下图所示:

有了事件处理对象,但还没有指定方法,此时单击会出现如如下图所示的菜单:
29 / 114
word

鼠标指向我们为此对象所挂的脚本名_ToggleEvent时就会继续展开一个菜单,其中就有我们在此脚本中编写的方法Toggle1(boolToggle2(boolToggle3(bool这个菜单与Button的有所不同了,Button的如如如下图所示:

比拟这两个菜单可发现Toggle多了上面的那局部:
30 / 114
word

下面的是静态方法,上面的是动态事件,是系统自动生成,其bool型参数已被封装在其中了,此时我们不能象Button那样去选择其静态方法了,而要选择与之对应的动态事件才可正常运行了。
ToggleButton在事件处理上的的区别不只是上面所谈到的那一点,还有其他区别,如:
Button事件组件面板的上部显示的是 Toggle事件组件面板的上部显示的是 Button是当Button被单击时发生,Toggle是当Toggle选中与不选中〔即其值发生改变〕时发生,且还有一个布尔型参数,选中时传进给参数的值为真,反之为假,所以在前面脚本编写中,其方法里我们要设置对应的布尔型参数来承受这个值:
public void Toggle1(bool isclik{
if (isclik { info="屠龙宝刀"; Display.text=info; } }
根据上面的分析可知,Toggle选中与取消选中时都会产生事件,那么在一组单项选择按钮组中,当我们点选另一个按钮同时会取消前一个按钮的选择,那么这两个按钮就都会产生事件,为了证明这一点,我们将前面的脚本稍作改变:
public void Toggle1(bool isclik{ print("屠龙宝刀"; if (isclik { info="屠龙宝刀"; Display.text=info; } } public void Toggle2(bool isclik{ print(倚天剑"; if (isclik { info="倚天剑"; Display.text=info; } } public void Toggle3(bool isclik{ print(降龙十八掌";
if (isclik { info="降龙十八掌"; Display.text=info; } }
以前的代码是当选中即isclik为真时才显示相关信息,而取消选中,虽然事件也产生,但因isclik为假,所以不会显示信息,所以我们便觉察不出来,而现在加上了一个print句,这样只要事件发生了,就都会在后台里打印出相关信息来,如如如下图所示:
31 / 114
word

这是首次运行选中“屠龙宝刀〞时的情况。

接着我们选中“倚天剑〞时,“屠龙宝刀〞也被取消,“倚天剑〞与“屠龙宝刀〞都产生了事件,所以会打印出各自的信息。
32 / 114
word

再在这根底上选中“降龙十八掌〞,“倚天剑〞被取消,同时“倚天剑〞与“降龙十八掌〞均产生了事件,所以倚天剑与降龙十八掌相关信息都会打印出来。
以上就是Toggle的事件处理机制,如果我们Toggle不是单项选择而是复选,那么我们又怎样在那个文本框中显示出多项选择信息呢?
这个问题看似很难,实际上很简单,代码如下: public void Toggle1(bool isclik{ if (isclik { info += "屠龙宝刀"; Display.text=info; } } public void Toggle2(bool isclik{ if (isclik { info += "倚天剑"; Display.text=info; } } public void Toggle3(bool isclik{
if (isclik { info += "降龙十八掌"; Display.text=info; } }
info的赋值符号=变成+=这样就把info的值累加起来了,也就记录下了多项选择值了。这虽然简单,但不完善,如果先选中,然后又去掉,但先添加进去的值却不会去掉,这需要进一步地处理才行。
33 / 114
word 5 事件运行模式
在事件组件面板中,第一个选项框中的值我们在Button时就是一直使用的是其默认值:Runtime Only,如如如下图所示:

当我们单击该选项时,出现的下拉菜单如下:

Off:关闭事件处理功能;
Editor And Runtime:编辑与运行时,其事件处理功能均起作用; Runtime Only:仅在运行时,其事件处理功能才起作用。

我们假设把Toggle1方法改成如下所示: public void Toggle1(bool isclik{ print ("屠龙宝刀"; info = "屠龙宝刀"; Display.text=info; }
然后把第一个Toggle的事件处理对象与方法置空,并把事件运行模式变为Editor And Runtime,此时再为它添加事件对象与方法,我们将发现在添加完毕后,其事件便立即发挥作用了,如如如下图所示,当然程序运行时也能发挥其成效的,这就是“编辑与运行时,其事件处理功能均起作用〞的意思。

此功能可以为我们程序员提供预览、事前先知的功能,方便我们编辑。
34 / 114
word 十一、Slider控件〔滑动条〕
1 Slider也是一个复合控件,Background是背景,默认颜色是白色,我们保持不变;Fill Area是填充区域,其子控件Fill中只有一个Image(Script专有组件,假设我们将其颜色改为红色;Handle Slice Area中的子控件Handle〔手柄〕中也只有一个Image(Script专有组件,假设我们将其颜色改为黄色,那么Slider的外观为:
2 当我们在Hierarchy中选中Slider控件,其Inspector中的Slider(Script属性面板如如如下图所示:

上部的InteractableTransition与前面介绍的控件是差不多的,下面谈谈它特有的一些属性:
Fill Rect:填充矩形区域 Handle Rect:手柄矩形区域
DirectionSlider的摆放方向,可以从左到右、从右到左、从上到下、从下到上 Min Value:最小数值 Max Value:最大数值
Whole Numbers:整数数值。假设我们将Min Value设为1Max Value设为100,那么调节手柄时,对应的值在1100之间,而且是一个小数,如55.67,有时我们希望它是整数,那么选中该项即可。
上面的后4DirectionMin ValueMax ValueWhole Numbers都比拟好理解,而前2Fill RectHandle Rect较困难,下面我们做一个实验便可知其意义了。
35 / 114
word 我们再创建一个Slider控件并命名为Slider2并把其所有子控件的名字改成在其默认名后加2的名字,再把先前的那个Slider改名为Slider1也把其所有子控件的名字改成在其默认名后加1的名字,如如如下图:

此时我们先选中Slider2,然后把Slider1的子子控件Fill1拖到Slider2Fill Rect中,如图:

运行程序,当我们调节Slider2的手柄时,我们将发现Slider1的填充区域在发生变化,为什么呢?因为默认情况下Slider2Fill Rect是它自己的Fill2,而我们现在把Slider1Fill1赋给了它,作为它现在的Fill Rect对象,所以就会出现此种情况,这就是Fill Rect成效。
在上面的实验中,我们把Slider1用来做显示,Slider2用来控制,如果能把Slider1中黄色手柄隐藏起来就更好了:

这也是能做到的,我们选中Slider1的子子控件Handle1,在其Inspector视图中,将其Image(Script前面的对勾去掉,这样就不会显示那个手柄了:

3Slider的动态事件
假设我们想在拖动手柄的时候,让其值显示在右边的一个文本框中,如如如下图所示:

这就要用到Slider的动态事件了
指的是Slider的滑块滑动其值发生改变时而产生的动态事件,它有一个参数Single:单精度,实际上这里指的是float,整个事件的机理是,当滑动滑块时,其值发生改变,事件产生,而且会实时将滑块所对应的值传给此事件,保存在这个参数中,供程序使用。
根据此原理,我们建立如下脚本SliderDemo
using UnityEngine; using System.Collections; using UnityEngine.UI;
public class SliderDemo : MonoBehaviour { public Text Txt_diaplayValues; // Use this for initialization void Start ( { }
public void DisplaySliderNumber(float floValues{ Txt_diaplayValues.text = floValues.ToString (; } } 然后在场景中创建一个空对象,把此脚本作为组件挂在这个空对象上,再在场景中创建一个文本框,并赋给 public Text Txt_diaplayValues变量。
最后一步就是注册事件了,单击中的“+〞按钮,为其添加事件,把前面创建的并已挂上脚本的那个空对象拖到中为其委托事件处理对象,再指定事件方法,单击:
36 / 114
word

SliderDemoDisplaySliderNumberDisplaySliderNumber(float,而要选上面的DisplaySliderNumber动态事件〔其原因请见前一节的表示〕
运行程序就可达到要求了。
十二、ScrollBar控件〔滚动条〕

37 / 114
word 其属性:与前面的Slider差不多,动态事件也是一样的,这里就只谈其特有的属性:
Value:当拖支滑块时,其值是在01之间变化的
Size:是滑块的大小,如果把它改成0.5,滑块就会大到占滑条的一半大。
Number Of Steps:数值的步骤。假设设定为5,那么就会把Value分成5个值,调节滑块时其值就在这5个值中变化。
38 / 114
word 十三、一个简单的游戏主界面

右边蓝底色中的“生化危机〞为Text;开始、设置、完毕为Button,并加上简单的帧动Highlighted见前面的动画过渡
左边淡黄底色区域为面板panel它为父控件,其中所包含的所有控件均为它的子控件,游戏难度下的三个选择钮为单项选择按钮组,其设置方法请参见前面Group
这个面板,通常情况下是不可见的,当单击“设置〞按钮时面板从左外侧滑入而可见,进展设置后单击面板中的“确定〞按钮后,面板又滑出到左外侧处于不可见状态。这是一个动画,其设置方法与Button动画相似,但它不是利用Button那种自动生成动画的方法而建立的。
下面我们先来建立面板的动画过程: 首先,Hierarchy面板中选中要建立动画的Panel单击主菜单Window中的Animation〔注意不是Animator〕出现Animation窗口:
39 / 114
word

此时单击顶端最左侧红色按钮,它为动画录制按钮,会弹出一个对话框,要求为将要录制的动画选择保存位置与动画的名称,如如如下图:

假设我们将此动画保存在Assets下的_Animation文件夹中,并取名为,单击保存后,其界面如下:

40 / 114
word 录制的动画是面板从不可见到可见的显示动画,那么在第0帧时面板是不见的,所以此时把面板水平向左拖动到画布的左外侧,如如如下图所示:
动画录制机会记录下此时对象的位置,Inspector面板中的RectTransform参数会发生改变: ,即在第0帧时,面板在X-140Y:处。
接下来我们把帧数框中的帧数改为60帧,即设置第60帧时面板的位置〔设为60帧的原因是,面板从第0帧的位置变化到第60帧的位置时其动画时间大约为1秒钟〕此时录制面板中的那条红色竖线将移动到1:00处,如如如下图:

根据动画设计要求,此时面板应该是完全可见的,所以我们把面板水平向右拖到画布中,动画录制机同样会记录下此时面板的位置,其设置窗口如如如下图:
41 / 114
word

我们还可发现,在现在位置的红线处会出现象0帧处的关键帧图标:
我们在上单击一下,其展开图如下:
展开的那两项分别表示在此过程中,对象在X轴上位移了131Y轴上为0
从底部的处可见,现在的视图是Dope Sheet〔关键帧清单〕,当点击Curves〔曲线〕时,会转换为曲线视图,如如如下图
42 / 114
word

如果曲线过大显示不全或过小看不清时,可调节鼠标中键滑轮,缩放曲线到适当大小。 图中水平绿色线所包含的区域即为动画区域,曲线上的红色点为关键帧点,可看出此动画只有两个关键帧,用鼠标单击关键帧时,Scene视图中的面板就会移动到所设置的位置上。
设置好后,单击红色的录制按钮一下,即可停止录制且保存动画。 这是显示面板的动画,下面我们来设计隐藏面板的动画。
单击已经显示出刚刚录制的动画名为ShowPanel这个框右边的按钮,弹出:

单击[Create New Clip],创建一个新的动画剪辑,此时会同样弹出一个要求你为新动画取名以与选择保存路径的对话窗,假设我们为此动画取名为HidePanel.anim,路径与前一个动画一样,其后的动画设计与前边一样,只不过第0帧时,面板在画布上,第60帧时,面板在画布外。
动画创建完毕后,即可直接关闭录制窗体,系统会自动保存动画文件。回到系统界面下,Project视图中的我们事先设定的保存动画的_Animator文件夹下将会新增三个文件:而且在Hierarchy视图中选中已设置了动画的控件Panel,在其Inspector视图中将发现系统会为其自动增加动画组件Animator
好了,万事具备,运行程序,但发现那个面板的显示动画会不断地重复播放,其原因是其Loop Time的属性值为True如果设为False即可去掉其默认的自动播放特性。方法为,Project视图中选中动画,然后在其Inspector视图中,把后的钩去掉即可〔同理,HidePanel动画也做这样的处理〕但程序运行时,面板虽不会重复播放显示动画了,但它会播放一次,这与我们的设计初衷不符,我们的初衷是程序运行时不显示面板,当我们点击设置按钮后才会显示面板,点击面板中确实定按钮后,隐藏面板。要达到这种功能,就要设置动画状态机中的一些属性以与配合使用脚本才能完成。
首先,让动画不自动播放。
Hierarchy视图中选中设置了动画的控件Panel,可发现其Inspector视图中Animator组件中的第一个属性Controller〔控制器,也称动画状态机〕的值为前边录制的动画:Panel如图:,单击其后的设置按钮可更改为其他动画,不过这里是不需更改的,我们双击动画框中的已有的动画Panel,会打开Animator窗口:
43 / 114
word

其中有两个按钮代表的就是按钮文字所指示的动画剪辑:ShowPaneHidePanel,即现在这个Panel动画里有两个动画剪辑。我们在面板的空白地方单击鼠标右键:,选择第一项Create State中的Empty,创建一个空动画,其默认名为New State,如图:

New State上点右键,在弹出的中选第二项Set As Default,即设置这个空动画为默认44 / 114
word 播放的动画,既然为空动画,自然就不会播放动画,经此设置后的窗口如如如下图所示:

比拟设置前后两图可发现,代表默认动画的按钮的颜色为黄红色。即哪个按钮为黄红色,那个动画剪辑就是当前动画播放时的状态位置,动画状态机的命名来源也许就是这个原因。
经此设置后,再次运行程序,就不会有动画播放了。但也许你会发现那个面板仍然显示出来了,出现这种情况,不是动画造成的,因现在虽然没有动画,但那个面板本来是存在的,当然要显示出来,如果想要它一开始就不显示,我们只需在场景编辑视图中将其位置拖到画布之外即可达到目的,如如如下图:

通常情况下,一个动画里有许多的动画剪辑,到底播放哪个动画,是动画状态机来决定45 / 114
word 的。这个界面就是动画状态机界面,它表示现在的动画播放的是它中的哪个动画剪辑。那么,我们有什么方法来控制动画状态,或者说让动画在不同的剪辑替转换呢?
我们在“New State〞上单击鼠标右键,选择第一项Make Transition〔设置转换〕,然后直接移动鼠标,将会出现一个带前头的连线,再在〞ShowPanel〞上单击鼠标左键,即可在这两个动画剪辑上建立转换联接:,这个连线表示,当满足某个条件时,就可由播放剪辑New State变成播放剪辑ShowPanel,即使ShowPanel处于播放状态。这个条件又在哪里设置呢?单击右边的“+〞按钮,在弹出的中Bool,即设置一个布尔型参数,并把此参数假设命名为IsDiaplay,如图。
设置好参数后,用鼠标单击那根连接线,它将变成蓝色,表示选中,如图:

接下来,在其Inspector视图中的Conditions设置条件变量为刚刚建立的IsDiaplay,条件值为true,如如如下图:

其意思为,当IsDiaplay为真true时,动画播放状态由New State转变为ShowPanel 同理,可设置由HidePanelShowPanel转变条件也为当IsDiaplay为真true时。
46 / 114
word

这两步设置的结果我们可以这样理解,IsDiaplay为真true时,动画播放状态处于New StateHidePanel时,都将转到去播放ShowPanel
依此类推,当IsDiaplay为假false时,动画播放状态如果处于ShowPanel时,将转到去播放HidePanel。这样其动画状态我们就设定完了,如如如下图:

接下来我们利用脚本去改变那个变量的值,就可实时控制动画的播放了。 脚本容如下〔红色局部为增加的脚本容〕
using UnityEngine;
using System.Collections; public class SettingPanelDisplay : MonoBehaviour { public Animator Ani_SetPanel; void Start ( { } public void ShowPanel({
Ani_SetPanel.SetBool ("IsDiaplay",true; } public void HidePanel({ Ani_SetPanel.SetBool ("IsDiaplay",false; } } 在场景中创建一个空对象,把脚本挂在它身上,并在Inspector视图中把Hierarchy中的Panel赋给Ani_SetPanel,如图:
脚本中Ani_SetPanel变量是Animator类型,为何可以把控件Panel赋值给它呢?道理Panel控件已经有了Animator组件,程序会自动抽取其中的Animator出来赋值给变量Ani_SetPanel
Ani_SetPanel.SetBool ("IsDiaplay",true;其中的IsDiaplay就是在状态机中增设的参数,其拼写必须与状态机中的完全一致,否如此不能运行。
47 / 114
word 最后设定“设置〞与“确定〞两个按钮的委托事件,具体设定过程请参见前面的Button事件
至此,这个简单的游戏主界面便创建完工,可运行程序查看效果了。
十三、高级控件 滑动区域ScrollRect 滑动区域控件ScrollRect是在一个较小区域显示较多部控件的一种机制。UI系统中,这种控件的原型是没有的,它是我们开发者利用UI系统里已有的根本控件组合而成的。不过在UI系统里有ScrollRect这个类,即它是一个组件,不是控件。控件与组件有什么区别呢?简单地说,在一个控件里可以添加组件,如在Button上可添加Animator组件。有些控件在创建时,它会默认自带一些组件,Panel会自带Image组件,如图:其带括号的Script就表示这个Image是组件,因在UI系统里有Image这个根本控件的,故加上一个带括号的Script来区别控件与组件,说明此处的Image是组件而不是控件。同理,当我们创建一个Button控件时,默认情况下我们可以在其Inspector视图里发现它带有ImageButton两个组件的,如如如下图:

因在UI系统里有ImageButton这些根本控件,这里加上(Script说明这个ImageButton不是控件而是组件。
这好似有点混,怎么Button控件里含有Button组件呢?
实际上我们可以这样理解,组件是一个脚本,是一个类,控件是这个类的实例化对象,是一个具体实现,所以Button控件里含有Button组件就好理解了。再一个,类之间可以继承,所以一个控件可以包含多个不同类型的组件。
根据上面的表示,ScrollRect是待开发者自己去建立的控件,我们姑且把它称作隐形控件。下面我们来创建这个控件。
1 创建一个画布Canvas,在画布上创建两个空对象,其中一个命名为ScrollRect,另一个命名为Content,再创建一个Scrollbar。调整它们的大小与位置,大致如下:
ScrollRect Canvas Content Scrollbar
2 Content上创建几个子对象,这里我们创建4Button,并调整它们的位置,使它们平铺在Content中,同时设置ButtonImageSourceImage的值〔挂上图片,普通图像挂不上,应转换成精灵,请参见前面的Image
48 / 114
word

3 组装ScrollRect3个组件2个属性
添加ScrollRect组件:选中空对象ScrollRect在其Inspector视图中单击Addponent按钮,选择UI中的Scroll Rect这样便为这个空对象添加上了ScrollRect组件。此组件里有2个重要属性ContentHorezontal Scrollbar,其功能简单说是用滑动条的滑动去控制容区域的移动。根据此原理我们把Hierarchy视图中的ContentScrollbar分别拖挂到这两属性值框中即完成了对象的指定工作。试运行程序并拖动滑动条,发现Content4个按钮图片确实能随着滑动条的移动而移动了,如图:

但这还不完美,如果能隐藏多余的容,只显示特定区域的容,就象网页中的滚动条那样就好了,如如如下图所示:

要达到此功能,还要为已添加了ScrollRect组件的对象增添ImageMask〔遮罩〕两个组件,其添加方法与上一致。
至此,组装ScrollRect3个组件ScrollRectImageMask 2个属性:ScrollRectContentScrollRect中的Horezontal Scrollbar已完备,但当我们运行时,其效果仍然与前面一样,不能隐藏多余局部。如果在Hierarchy视图中我们把Content拖到ScrollRect上,使Content成为ScrollRect的子对象,就可达到我们想要的效果了。

其原因是,我们所添加的ImageMask是在ScrollRect上,那么用图像去遮罩的对象ScrollRect,所以我们要把Content作为ScrollRect的子对象才能达到此效果。
49 / 114
word 十四、高级控件 标签页面TabPage
如图,当我们点击顶部不同的标签时,下部的容区域会显示对应的容版面。
1、在画布上创建一个空对象,命名为Lable,创建一个Image,布局上Lable在上面,Image在下面,如如如下图:

2、在Lable中创建三个子控件,它们均为Toggle,命名为Toggle1Toggle2Toggle3并调整它们的BackgroundCheckmark,使其看起来像按钮:
50 / 114

Unity3D4.6UGUI开发设计及案例讲解

相关推荐