天天看点

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

Unity 2-4 UGUI Unity5.1 UI 案例学习

任务1-1:UGUI简介

什么是GUI:

  游戏的开始菜单

  RPG游戏的菜单栏、侧边栏和功能栏(比如背包系统、任务列表等)

  设计用来控制移动的虚拟杆和攻击按钮

UGUI:

  Unity内置

  GUI也可以用第三方插件实现:如NGUI、DFGUI等

任务1-2:游戏案例介绍

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务1-3:创建游戏菜单

UGUI中的组件:

  UI -> Panel -- 面板

    Button -- 按钮

    Text -- 文本

    Image -- 图片

    Raw Image -- 可拖放的材质

    Slider -- 滑动器

    Scrollbar -- 滚动条

    Toggle -- 开关 (check box)

    Input Field -- 输入框

    Canvas -- 画布(所有的UI组件都位于Canvas下)

    Event System -- 事件系统(处理有关UI的事件)

几乎所有的UI组件都有

  Rect Transform -- 用来控制位置和Anchor信息

  Script脚本 -- 控制组件的功能

Button:

  Button->Text-> Text (Script) -- 可以修改文本显示

  Image (Script) -- 修改背景图片

Toggle:勾选框

  Toggle->Label-> Text (Script) -- 修改文本显示

  Toggle->Background-> Image (Script) -- 修改背景图片

  Toggle->Background->Checkmark-> Image (Script) -- 修改勾选的标志

Slider:滑动器

  Slider -> Value 当前滑块位置对应的float值 [0, 1]

  Slider->Background-> Image (Script) -- 修改后置背景(滑动块未滑动区域)

  Slider->Fill Area->Fill-> Image (Script) -- 滑动条前置背景:滑动块已滑动区域

  Slider->Handle Slide Area->Handle (Script) -> 滑动块背景

任务1-4:创建公告的文本列表

1. 创建Image,重命名为NoteBg,作为文本的背景

  修改Alpha值:透明度

2. 创建另一个Image,重命名为TitleBg,作为标题背景,为Note的子物体

3. 分别在NoteBg下和TitleBg下创建Text

4. 给NoteBg下的Text添加上下滚动功能

  1. 在NoteBg下创建一个Image,大小与NoteBg->Text一样

  2. 给Image添加Scroll Rect组件

    将Text作为Image的子物体

    Content属性:指定拥有滚动功能的控件,这里赋值Text(表示滚动的是Text)

    此时,Text就拥有了可以滚动的功能

    将水平方向的滚动取消勾选 Horizontal

  3. 此时滑动了一下,发现不行,只是出现了Text整块能够被拖拽走

    而且文字没有显示完全 -- 将Text拉伸直到文字完全显示出来

    此时,拖动文本就会发现有了拖动的效果

    但是,超出NoteBg多余的文本也显示了出来

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

  4. 通过Mask组件将多余的文字部分隐藏

    在Image下添加Mask组件即可

  5. 若不想要Image的背景显示(这里是纯白色)

    将Mask的Show Mask Graphic取消勾选即可

 5. 给文本右边添加滚动条

  在Image->Scroll Rect中,有两个Scrollbar

  在NoteBg下创建Scrollbar,修改Direction = Bottom To Top

  将该Scrollbar赋值给Image->Scroll Rect-> Vertical Scrollbar

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务1-5:监听按钮的点击事件

Button的点击事件

创建GameObject GameManager,添加脚本GameManager.cs

  public void OnStartGameButton() { // 自定义函数

    SceneManager.LoadScene("02-Game");

  }

创建新场景02-Game,用于点击StartGame后载入

在StartButton下的Button组件中,点击On Click()的加号

  将GameManager指定给它,并选择要被触发的方法,OnStartGameButton()

在Build Settings中添加这两个场景即可

任务1-6:创建旋转的小球游戏

创建Cube,将Cube放在Camera的视野中

旋转的方法:Transform.

  Rotate(Vector3 eulerAngles, Space relativeTo=Space.Self) -- 

    围绕x轴做eulerAngles.x的旋转,

    围绕y轴做eulerAngles.y的旋转,

    围绕z轴做eulerAngles.z的旋转,

    Space relateiveTo表示对于什么坐标(world/local)进行旋转,可设为Space.World

  RotateAround(Vector3 point, Vector3 axis, float angle) -- 

    围绕point点上的axis坐标旋转angle度(世界坐标)

  RotateAroundLocal() -- RotateAround()的局部坐标版本

在Cube中创建脚本Cube.cs

  public float rotatingSpeed = 90; // 旋转90度

  void Update() {

    tranform.Rotate(Vector3.up * Time.deltaTime * rotatingSpeed);

  }

任务1-7:使用Slider控制小球旋转的速度

在Cube.cs中

  public void ChangeSpeed(float newSpeed) {

    rotatingSpeed = newSpeed;

  }

在创建的UI->Slider中,在On Value Changed(Single)

  将Cube.ChangeSpeed()赋值

  表示当Slider的value改变时,会通知Cube gameObject,调用它的ChangeSpeed()方法

    而该方法的实参就是Slider中的value值

此时,当滑动Slider时,会将速度设置为0~1

设置Slider的Max Value和Min Value为0~360即可

任务2-1:案例介绍

素材为UI.unitypackage,导入

UI -> Source文件夹下都是psd文件(美工的ps源文件)

UI -> effect Picture文件夹中是psd文件的效果图(.jpg)

UI -> Sprite文件夹是切好的图

任务2-2:开始界面的背景和锚点Anchor介绍

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

创建场景01-Start

将Sprite文件夹中的图片的Texture Type设置为Sprite (2D and UI)

创建UI->Image,设置Image的Source Image为StartScreen,重命名为Background

  在Rect Transform中按住Alt,点击右下方的四周的stretch,

    作用1:将Background的大小拉伸至和父类(Canvas)相同

    作用2:将Background四周的Anchor分别设置在四个顶点上 -- 屏幕缩放时等比缩放

什么是Anchor:

  控件与锚点之间的距离是保持不变的,比如在屏幕缩放时

  如果四个锚点都在右上角,则屏幕缩放时,该控件相对于右上角的距离是不变的

可以利用Anchor锚点进行屏幕的自适应

任务2-3&2.4:按钮

之前都是通过UI->Button的方式添加按钮,这次用其他方法:

  UI->Image -- 按钮的背景

  在Image中添加Button组件,在Image下添加子物体Text

这就和UI->Button方式创建的按钮相同了

1. 添加左上方的声音按钮 ButtonSound

  a) UI->Image,将Source Image选择为Button Round的Sprite 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

    按住shift进行等比缩小

    注:按住Shift等比缩放时,以左上角为基准点;按住Shift+Alt时,以中心点为基准点

  b) UI->Image,作为a)的子物体,将Source Image选择为ButtonRoundForeground

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

    等比放大直到填充满Button Round

  c) UI->Image,作为a)的子物体,将Source Image选择为Sound的Sprite 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

    会发现图标太窄了,选择Set Native Size,并等比放大

  d) UI->Image,作为a)的子物体,将Source Image选择为Leave的Sprite 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

,并等比放大

  将a)重命名为ButtonSound,在其添加Button组件,这样就有了点击功能

    此时点击的时候会发现点击的视觉效果是ButtonRound颜色变暗

    发现Button组件里的Target Graphic为ButtonRound图片

      将其改为ButtonRoundForeground(设置点击的视觉效果)

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

2. 添加右上方邮件按钮 ButtonMail

  将Sound替换为Mail的Sprite 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

  将Anchor设置为右上角

3. 添加左下方的设置按钮 ButtonSettings

  UI->Image,重命名为ButtonSettings

    背景图片设置为ButtonRoundBackground的Sprite 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

    添加Button组件

  UI->Image,设置为子物体,背景图片设置为Settings的Sprite 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

4. 与3相似,Settings换为Controller 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务2-5:开始按钮 & 设置开始页面的自适应

创建Play按钮:ButtonPlay

创建UI->Image,设置背景图片为Button Red B 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

  Set Native Size

  添加Button组件

创建子物体UI->Text,居中,调整大小,颜色白色,字体选择自定义的造字工坊悦圆

  字体放大为40,内容为PLAY

  添加阴影:在Text里添加组件Shadow

屏幕自适应:

  ButtonSound的Anchor设置为左上角

  ButtonMail的Anchor设置为右上角

  ButtonSettings、ButtonController、ButtonPlay的Anchor设置为中心点

任务3-1:主场景 -- 头像面板

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

左上角:头像

右上角:体力

左边:设置按钮

下方:技能状态

新建UI->Image-> Source Image设为bg-02的Sprite

新建UI->Image,重命名为Headbar,背景设为bar 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

  Set Native Size,等比放大,放在左上角

在Bar下创建子物体Text,用来显示角色名字,颜色白色,字体造字工坊悦圆、大小25

相似的,创建子物体Text,用来显示Level

点击头像的时候,显示人物的详细信息:

  添加Button组件

头像:

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务3-2:体力的进度条(Slider和Filled Image)

UI->Slider 来实现体力的进度条(右上角)

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

Fill Area指的是填充部分,可以修改Fill的颜色为蓝色

Handle Slide Area指的是Slider的滑轮部分的显示,本案例中可以将其删除

自定义Slider的创建:

1. 背景

  创建UI->Image,背景图片设为BarBackground 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

  体力条的背景有两部分,一部分是棕色边框,一部分是黑色电池部分

  复制Image,缩小,将Color修改成黑色即可

2. 绿色的填充条

  复制Image,将Color修改成绿色的填充

3. 实现Slider效果

  将最外层的Image添加Slider组件,将BarForegroundGreen赋值给Slider的Fill Rect

    此时会发现,绿色的方块大小放大了

  将BarForegroundGreen的Image Type属性设置为Filled

    原因:可以选择显示该Image的某一部分

    Image Type的四种属性:Simple/ Sliced/ Tiled/ Filled详解见任务3-3

    将绿色部分调整大小

    Fill Method选择Horizontal,Fill Origin选择Left

  此时,修改Slider中的value,会发现绿色的部分会随着value的改变而填充

4. 叶子装扮

  UI->Image

5. 左边的体力标识

  UI->Image, Source Image为ButtonRoundBackground2、Battle

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

6. 体力值

  UI->Text,字体、字号、颜色、对齐等

7. 此时,外观实现了,但是,Slider是可以利用鼠标进行大小调节的,这样不行

  体力条是不需要与鼠标进行交互的,只能通过代码来修改

  将Slider上的Interactable选项取消勾选即可

8. EnergyBar的锚点设置为右上角

体力条:

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务3-3:Image中的类型simple, sliced, tiled, filled

Image中Image Type的四种属性:

  Simple/ Sliced/ Tiled/ Filled

Simple:普通模式 -- 仅仅将图片正常显示出来,大小与边框保持一致

Sliced:切图

  如果将某个图片放大,内部是填充色,而边框会出现失真

  一般来说,放大的时候不希望边框也放大导致失真

  实例:

    选择一个Sprite,在Inspector中打开Sprite Editor

    将绿色的小线框拖动,将图片分割成九个格子(4条线框)

    此时若图片缩放,四个角不会缩放,左右边框只会上下拉伸,上下边框只会左右拉伸

Tiled:按图片原来的大小进行平铺

Filled:显示图片的某一部分

  Filled Method:Radial 360°/ Radial 180°/ Radial 90°/ Horizontal/ Vertical

  Filled Origin:Top/ Bottom/ Left/ Right等等

  Clockwise: Check/ Uncheck

  实例:技能的冷却效果:

    FilledMethod: Radial 360°,FilledOrigin: Top,Anti-Clockwise

任务3-4:设置和对话框按钮

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

注:Anchor跟左边对齐

  记得把ButtonRoundForeground设为按钮的Target Graphic

任务3-5:技能和技能的冷却效果

创建技能按钮:

  UI->Image: Slot2 -- 技能背景

  UI->Image: Sword Icon

  UI->Image: 叶子 -- Leave

  UI->Text: 右上角的快捷键显示

    给字体添加外边框 -- 添加Outline组件即可

技能冷却显示:

  创建相同的Sword Icon的Image

    将颜色修改为黑色,将透明度修改为100

    Image Type设置为Filled

      Filled Method = Radial 360°

      Filled Origin = Top

      Anti-Clockwise

  此时,value从1-0的过程就是技能冷却结束的过程

技能的使用:

  添加脚本SkillController.cs

  检测按钮的点击,并开始冷却

public class SkillController : MonoBehaviour {

    public float cooldownTime = 2;
    private float timer = 0;
    private bool timerHasStarted = false;
    private  Image skillSwordCooldown;

    private void Start() {
        skillSwordCooldown = 
            transform.Find("Skill_Sword_Cooldown").GetComponent<Image>();
    }

    public void OnClick() {
        timerHasStarted = true;
    }

    private void Update() {
        if (timerHasStarted) {
            timer = timer += Time.deltaTime;
            skillSwordCooldown.fillAmount = 
                (cooldownTime - timer) / cooldownTime; // 冷却所占比例
            if(timer >= cooldownTime) {
                skillSwordCooldown.fillAmount = 0;
                timer = 0;
                timerHasStarted = false;
            }
        }
    }
}          

检测快捷键的点击,并开始冷却:

  public KeyCode keycode;

  在Update()中

  if(Input.GetKeyDown(keycode) {

    timerHasStarted = true;

  }

  将keycode设置为Alpha1即可

技能:

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务4-1:窗口边框

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

UI->Image: 背景为bg-01

UI->Image: 背景为window -- Image Type = Sliced -- 九宫格切图

  边框部分不会出现失真模糊

在Window下创建子物体UI->Image: Title

在Title下创建子物体UI->Text:白色、字体、居中、Title等

任务4-2:角色面板的背景和关闭按钮

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

按任务4-1创建一个窗口框架

右上角关闭按钮:UI->Image: ButtonRound + ButtonX + Leave1

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务4-3:头像

在PanelCharacter下创建线框:PenalHead,作为人物状态的背景

  UI->Image: frame2 -- Image Type = Sliced,放在Window的左半边

创建人物头像背景:PenalHead的子物体PortraitBackground

  UI->Image: portrait

创建人物头像:PortraitBackground的子物体Character

  UI->Image: character

创建等级:PortraitBackground的子物体Level

  UI->Text: 显示角色当前等级,黑色、字体、Bold、大小、

创建显示人物名字的叶子和下划线:空物体PlayerName

  UI->Image: Leave2

  UI->Image: Seperator 

  UI->Text: 居中、字体、白色、大小、Bold等 

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务4-4:人物属性

在PanelHead下创建人物属性:Strength

  UI->Text: PropertyName -- 血量、白色偏暗、字体、大小

创建属性值:为PropertyName子物体

  UI->Image: Input Background,重命名为PropertyValue

    UI->Text: 为InputBackground的子物体,字体、大小、颜色与上相同、居中等

创建属性值加点按钮:

  UI->Image: Button Plus,添加Button组件

创建其他两个属性:Dex和Focus

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务4-5:背包的选项卡(Toggle  -- 单选/多选按钮)

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

Toggle: Toggle组件,其中有IsOn组件,勾选时会显示下面赋值的Graphics物体

Background: Image组件,本例中为勾选框的背景白色正方体

Checkmark: Image组件,本例中为勾选的符号

Label: Text组件

创建背景:PanelKnapsack

  UI->Image: frame-01

创建选项卡:Tab1

  UI->Image: tab-normal,添加Toggle组件

  子物体UI->Image: tab-selected

  将Tab1的Toggle组件中的Graphic设置为tab-selected

    这样当IsOn为false的时候,tab-selected就不会显示了

  子物体UI->Text: 装备

创建其他两个选项卡Tab2和Tab3

任务4-6:控制面板的切换(Toggle)

Tabs的切换:

任务4-5中,使用Toggle实现了三个单选按钮

现在,需要把他们变为多选按钮 Toggle Group

  可以通过Toggle Group将一组Toggle进行分类

在PanelKnapsack下添加Toggle Group组件

对于Tab1、Tab2、Tab3,将它们的Group属性设置为PanelKnapsack

默认让Tab1处于IsOn开启状态,Tab2、Tab3关闭

创建Empty Object 称为Panel1~Panel3,存储所有Items:

切换的机理:隐藏其他两个Panel

注意到,Toggle组件有一个On Value Changed(Boolean),可以用来监听是否勾选

  在Tab1中的Toggle添加Panel1,并把SetActive()方法传递给它

并默认将Panel1和Panel2取消勾选 (手动隐藏) (否则刚开始的时候默认三个面板都会显示)

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务4-7:设计装备、消耗品和材料面板,以及之间的切换

通过网格 Grid Layout Group 实现背包内物品的显示

Grid Layout Group: 对子物体进行排序

  Cell Size:每个网格的大小

    子物体的大小是不能通过子物体自己设置的,是通过Grid Layout Group控制的

1. 在Panel1下创建空物体Grid,添加Grid Layout Group组件

2. 在Grid下创建子物体

  UI->Image: Slot

  在Slot下创建子物体Item: UI->Image: inventory-04

  此时,Slot之间没有空隙,并没有像例图中那样显示(可以直接修改Spacing的值)

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

3. 修改:在Grid下创建空物体,将Slot放入该空物体

  一个Slot对应一个空物体,Grid Layout Group控制的大小为空物体的大小

  调整各个GameObject的大小

4. 增加空的Slot,直至填满整个Grid

  将Grid->Slot->SlotItem->Item的Image Source设为空,并将Item取消勾选

5. 在最下方显示物品数量:

  UI->Image: Input Background,下方居中

  创建子物体UI->Text: 字体大小颜色等

  创建子物体两边的修饰 UI->Image: Ornament

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务5-1:关卡选择界面

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

分析:

  关卡分页显示,分页的实现为水平方向的滑动 -- Scroll Rect

  关卡排序显示 -- 使用Grid Layout Group

  下方的按钮对应各个页面 -- Toggle Group

创建背景 UI->Image->bg-01,Anchor&Position stretch

创建Window框架: PanelSelectLevel

创建线框: UI->Image: frame1

任务5-2&5.3:不同类型的关卡按钮&&并通过Grid Layout排序

创建单个关卡:Levelxxx

  背景 -- UI->Image: ButtonRoundBackground

  等级数 -- UI->Text: 黑色、居中、字体、大小等

  通关的星数量 -- UI->Image: StarLeft,StarCenter,StarRight

  在Levelxxx上添加Button组件

关卡类型:可制作为Prefab

  三星完成 LevelCompletedThreeStars:如上所述

  未三星完成 LevelUncompleted:

    增加UI->Image: ButtonRoundForegroundGreen, 把颜色改为黄色

    增加UI->Image: Leave,把被Foreground遮住的底部叶子还原

    将部分星星隐藏显示

  未解锁 LevelLocked:

    增加UI->Image: ButtonRoundForegroundGreen, 把颜色改为深色

    增加UI->Image: Lock

    增加UI->Image: Leave,把被Foreground遮住的底部叶子还原

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

通过Grid Layout进行排序:  

在PanelSelectLevel下创建32个空子物体 Level1~Level32

  将上面创建的各个关卡Levelxxx分别放入Level1~Level8

在Frame下创建一个空物体,称为Grid,添加Grid Layout Group组件

  Start Axis = Vertical; 调整Cell Size

将Level1~Level32放入Grid

需要将Grid进行从左向右的拉伸

  因此将Grid的原点设置在左边(此时修改Width时,大小会以左边为基准进行缩放

  如果原点是在中间,则大小会同时往左和右缩放)

注意,此时关卡按照Grid的排序为上下排序,即为

  1 3 5 7

  2 4 6 8

  因此,需要将Text中显示的关卡数目与Grid的排序进行错位

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务5-4:关卡的滚动列表

&5-5&5.6:控制滑动列表按照页数滑动 && 缓动效果

实现关卡的滚动效果:Scroll Rect

  详见任务1-4

  在Frame下创建UI->Image,调整大小,就是Scroll Rect的大小(把Level1~8包含在内)

    添加Scroll Rect组件,Vertical取消勾选,将Grid赋值给Content

  将Grid拖动到GridScrollPanel下作为子物体

  在GridScrollPanel中添加Mask组件,用于隐藏Grid中多余部分的显示

    取消勾选Show Mask Graphic,用于隐藏GridScrollPanel自身背景的显示

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

按照页数滑动:

现在可以进行滑动了,但是本例的滑动功能比较特别:

  滚动列表分为4页,当滑动完成后会停留在离它最近的一页进行显示

在GridScrollPanel下添加脚本LevelSelectScrollRect.cs

  继承两个接口:using UnityEngine.EventSystems;

    IBeginDragHandle, IEndDragHandle

要想得到滑动的位置 -- 在ScrollRect里可以得到

  private ScrollRect scrollRect = GetComponent<>...

  scrollRect.normalizedPosition;  // The scroll position as a Vector2 btw (0,0) and (1,1)     with (0,0) being the lower left corner. 

    x的值表示水平方向,y表示竖直方向;

    表示当前end drag时所在的位置(以0~1表示)

    注:鼠标松开后的惯性移动不计入测量(以放开鼠标那一刻的位置为准)

  此处因为只需得到水平的滑动,使用scrollRect.horizontalNormalizedPosition即可

需要求得滑动的位置距离哪一页比较近:

  一共有四页,第一页和最后一页用0, 1表示,中间两页用0.333和0.666表示

public void OnEndDrag(PointerEventData eventData) {
    float posX = scrollRect.horizontalNormalizedPosition;
    // 设四个数字,若当前horizontalNormalizedPosition的值离哪个近,就翻到该页
    // 第一页:0;第四页:1
    // 中间两页平均分,第二页0.333,第三页0.666
    float[] indexArray = new float[] { 0f, 0.333f, 0.666f, 1f };
    //判断当前滑动位置离哪一页近
    int index = 0; // 默认离第一页近 (默认就是在第一页)
    int targetIndex = 0;
    float offset = Mathf.Abs(posX - indexArray[index]);
    for (index = 1; index < indexArray.Length; index++) {
        // 寻找最近的一页
        if((Mathf.Abs(posX - indexArray[index])) < offset) {
            offset = posX - indexArray[index];
            targetIndex = index;
        } 
    }
    // targetIndex就是需要定位的页数
    scrollRect.horizontalNormalizedPosition = indexArray[targetIndex];
}      

缓动效果:

当前的效果是直接变到那一页,没有动画效果,太过于生硬

scrollRect.horizontalNormalizedPosition = indexArray[targetIndex];

  -- 改进:需要使用差值运算的方式进行渐变

targetPosX设为全局变量

将上面直接设置Pos的代码改为设置targetPosX:targetPosX = indexArray[targetIndex];

之后在Update()进行差值运算

  scrollRect.horizontalNormalizedPosition = Mathf.Lerp(

    scrollRect.horizontalNormalizedPosition, targetPosX, Time.deltaTime * speed);

此时,实现了缓动效果。

但是,会发现在Update中该差值运算是不停地执行的,而在滑动的过程中,scrollRect的位置是不应该被代码所控制的:

  使用bool startAutoScroll = false; 来判断是否需要自动缓动

  在OnEndDrag()时,将其设为true,在OnBeginDrag()时,将其设为false

  在Update()中,如果为true的时候才会运行差值运算和位置设定

private float targetPosX = 0; // 默认为第一页
private bool startAutoScroll = false;
private float autoScrollSpeed = 5;

public void OnEndDrag(PointerEventData eventData) {
    // ...求得targetIndex,targetIndex就是需要定位的页数
    // scrollRect.horizontalNormalizedPosition = indexArray[targetIndex];
    targetPosX = indexArray[targetIndex];
    startAutoScroll = true;
}

void Update() {
    if (startAutoScroll) {
        // 差值运算和位置设置
        if (scrollRect.horizontalNormalizedPosition.Equals(targetPosX)) {
            startAutoScroll = false;
        }
    }
}

public void OnBeginDrag(PointerEventData eventData) {
    startAutoScroll = false;
}      

任务5-7&5-8:添加单选按钮来控制列表的滑动

添加控制列表滑动的单选按钮:

在Frame下创建空物体SelectLevelToggles,用来存放Toggles

创建子物体UI->Image: Knob,灰色

  创建Knob的子物体,用来显示toggle被选择时的状态 UI->Image: Leave

  在Knob上添加Toggle组件,将其Graphics设置为Leave

    (还记得IsOn为True时Graphics会显示吗)

在SelectLevelToggles中添加Toggle Group组件

  并在所有Knob上的Toggle->Group中赋值SelectLevelToggles

将所有的Knob的IsOn都uncheck,完成按钮的添加

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

通过单选按钮来控制列表的滑动:

Toggle的事件为OnValueChanged(Boolean)

在GridScrollPanel.LevelSelectScrollRect.cs中添加四个方法分别对应四个按键的点击事件

public void MoveToPage1(bool isOn) {

  if (isOn) {

    startAutoScroll = true;

    targetPosX = indexArray[0];

}}

并将这四个方法分别在四个Toggle中注册

此时,可以通过Toggle来控制页面的滑动了

  但是,用拖拽的方式进行页面滑动的时候,不能控制Toggle的开关,该怎么做呢

  -- 通过代码修改Toggle组件的IsOn属性即可

首先,得到所有的Toggles:public Toggle[] toggles = new Toggle[4];

在上一任务中得到targetIndex之后,实现toggles[targetIndex].isOn = true; 即可

public class LevelSelectScrollRect : MonoBehaviour, 
    IBeginDragHandler, IEndDragHandler {

    // 用于修改Toogles的IsOn属性
    public Toggle[] toggles = new Toggle[4]; 

    private ScrollRect scrollRect;
    private float targetPosX = 0; // 默认为第一页
    private bool startAutoScroll = false;
    private float autoScrollSpeed = 5;
    private float[] indexArray;

    void Start() {
        scrollRect = GetComponent<ScrollRect>();
        indexArray = new float[] { 0f, 0.333f, 0.666f, 1f };
    }

    void Update() {
        if (startAutoScroll) {
            scrollRect.horizontalNormalizedPosition = Mathf.Lerp(
                scrollRect.horizontalNormalizedPosition, targetPosX, 
                Time.deltaTime * autoScrollSpeed);
            if (scrollRect.horizontalNormalizedPosition.Equals(targetPosX)) {
                startAutoScroll = false;
            }
        }
    }

    public void OnEndDrag(PointerEventData eventData) {
        float posX = scrollRect.horizontalNormalizedPosition;
        // 设四个数字,若当前horizontalNormalizedPosition的值离哪个近,就翻到该页
        // 第一页:0;第四页:1;第二页0.333,第三页0.666
        int index = 0; // 默认离第一页近 (默认就是在第一页)
        int targetIndex = 0;
        float offset = Mathf.Abs(posX - indexArray[index]);
        for (index = 1; index < indexArray.Length; index++) {
            // 寻找最近的一页
            if((Mathf.Abs(posX - indexArray[index])) < offset) {
                offset = posX - indexArray[index];
                targetIndex = index;
            } 
        }
        // targetIndex就是需要定位的页数
        targetPosX = indexArray[targetIndex];
        startAutoScroll = true;
        // 通过拖拽导致的页面滑动,控制Toggles的IsOn属性
        toggles[targetIndex].isOn = true;
    }

    public void OnBeginDrag(PointerEventData eventData) {
        startAutoScroll = false;
    }

    // 用于通过Toggles来控制页面的滑动
    public void MoveToPage1(bool isOn) {
        if (isOn) {
            startAutoScroll = true;
            targetPosX = indexArray[0];
        }
    }
    public void MoveToPage2(bool isOn) {}
    public void MoveToPage3(bool isOn) {}
    public void MoveToPage4(bool isOn) {}
}
               
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务6-1&6-2:任务列表 -- 背景&&任务项

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

滚动列表

创建背景 UI->Image: bg-01

创建window frame和CloseButton见任务4

在PanelQuest下创建任务对话框:Quest

  背景 UI->Image: quest-bg,Image Type = Sliced,并打开Sprite Editor切图

    左边任务类型 UI->Image: quest-leave

      leave的子物体: UI->Image: quest-dialog

    任务名称 UI->Text: 字体、黑色、Bold、大小等

    右边按钮 UI->Image: ButtonRedA,添加Button组件

      子物体: 按钮文字: UI->Text: Done、白色等

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务6-3:使用Vertical Layout和ScrollRect控制任务列表的滑动

除了Grid Layout Group外,还有Vertical Layout Group和Horizontal Layout Group

这里因为Quests需要竖直排序,所以使用Vertical Layout Group实现

  Vertical Layout Group会将所有子物体完全填充空间

  因此和上面一样,需要将Quest放入空物体后再作为Vertical Layout Group的子物体

在PanelQuest下新建空物体QuestListVerticalLayout

  在QuestListVerticalLayout下创建若干空物体,作为Quest的容器

  Ctrl+D复制出(一共九个)QuestItem

  调整各个物体的大小

实现滚动效果:

新建UI->Image: 添加ScrollRect组件,调节大小

  将QuestListVerticalLayout放入ScrollRect,作为子物体

  并将ScrollRect的Content指定为QuestListVerticalLayout,取消勾选Horizontal

  在ScrollRect中添加Mask,取消勾选show mask graphics

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务7-1&7-2&7-3:游戏设置界面 -- 声音的滑动条

&& 游戏难度按钮

&& 音效和音乐开关

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

Volume:滑动条 (Slider)

Level:单选 (Toggle Group)

Audio/ Music:选择框 (Toggle扩展)

老样子,背景bg-01 +  Window Frame + ButtonClose

音量滑动条:

UI->Text: VOLUME、白色、字体等

UI->Slider:

  Background: Slider Background

  Fill Area->Fill: Slider Background,颜色黄绿色

  Handle Slide Area->Handle: Thumb

  (注:Handle Slide Area的大小和Handle的大小之间的关系要调整好)

选择游戏难度的单选按钮:

UI->Text: DIFFICULTY

UI->Toggle: 

  Background: TickBackground

  Background->Checkmark: Tick

  Label: EASY

创建另外两个按钮MED和HARD

在Difficulty上添加Toggle Group组件,并将三个Toggle的Group设置为Difficulty

音效和音乐开关:

UI->Text: AUDIO

UI->ToggleAudio: 

  Background: SwitchBackground

  Background->Checkmark: SwitchOn,并重命名

  Label: on,黄色,在Hierarchy中放在Checkmark下(子物体)

  在Checkmark旁边添加一个兄弟UI->Image: SwitchOff,位置在右边

  同样,在SwitchOff下创建一个 UI->Text: off,红色,位置在左边

在ToggleAudio中添加ToggleAudioController.cs脚本,用于自定义控制Toggle

首先需要取得SwitchOn和SwitchOff两个gameObject

  public GameObject switchOn; 

  public GameObject switchOff;

监听Toggle的按下:

  public void OnSwitchPressed(bool isOn) {

    switchOn.SetActive(isOn);

    switchOff.SetActive(!isOn);

  }

此时就能进行开关的切换了

但是还需要设置刚开始的初始化状态

  private Toggle toggle = GetComponent<Toggle>();

  在Start()中手动调用OnSwitchPressed(toggle.isOn); 即可

相同的MUSIC按钮,复制即可

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务8-1:游戏登录界面 -- 登录面板、输入框

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

下方两个按钮;中间两个输入框,一个单选按钮

老样子:bg-01 + Window Frame + ButtonClose

创建线框:UI->Image: frame2,调整大小

创建输入框Username:

  UI->Text: Name,字体大小,向右对齐等

    UI->Input Field -- InputField组件用来控制输入,它的属性:

        Image: 输入框背景

        Placeholder: 默认显示值

        Text Component: 输入时会将输入值显示在该组件指向的Text物体中

      子物体 Placeholder: Text组件 -- (当有输入时,该物体的Text会自动被禁用)

      子物体 Text -- 用来存放InputField中输入的内容

同样方法创建输入框Password:

  但是密码是不能显示明文的

  在InputField组件中有一个ContentType属性,ContentType = Password即可

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

创建Remember Me单选框:

  UI->Toggle: 

    Background: TickBackground

    Background->Checkmark: Tick

    Label: Remember Me?

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

创建下方两个按钮:

  登录按钮:

    UI->Image: ButtonRoundBackground,添加Button组件

      UI->Image: Ok

  控制按钮:

    UI->Image: ButtonRoundBackground,添加Button组件

      UI->Image: ButtonRoundForeground(并设为Button的Graphics)

      UI->Image: Leave

      UI->Image: Controller

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear
Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear

任务8-2:结束语

掰掰

Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习 - FudgeBear