文章目录
拓展学习: UGUI系列导航帖
UGUI=unity game user interface
创建场景:file-new scene
指定vs版本:edit-preference-external tools
先在Assets文件夹下创建Scripts文件夹,把使用的脚本放入文件夹
包管理器:packages文件夹—右键view in package manager
上边栏component下有许多常用组件可学习
UI渲染层级
数字大的后渲染,在最上面
四种因素:
- camera——depth(多个相机内容显示在一起:clear flags——depth only)
- canvas——sorting layer(可以自定义层级)(不同canvas的层级)
- 物体——order in layer
- 自然顺序——面板的排列顺序(后面的渲染在上面)(如果没有其他因素影响)
图片切割
选择文件夹中的图片文件
sprite editor
sprite mode:
-
simple单张图
九宫格切图
四个角的不会变
-
multiple图集
手动切割
自动切割–上方选项slice–slice
每个切出来的图与单个图一样,可以拉出九宫格
transform组件
每个unity物体必备的组件
显示模式static:normal正常;debug具体参数
单位px
白框:panel 底板
四个白色三角形:anchors锚点
蓝色圆圈:pivet中心点、轴心点(上方的模式切换center、pivet)(0,0)
——anchor position4个锚点的几何中心点(建议使用)
——local position白框的几何中心点(相对于pivet中心点)
获取宽高最安全的方式——白框的宽高(无论锚点怎么变化)
RectTransform rect = transform.GetComponent<RectTransform>();
//宽 rect.rect.width
蓝图模式:(面板上宽高右边的按钮)
物体的白框panel不随着大小、旋转变化
(用处:物体有动画运动,但是响应区域不变化)
**原始编辑模式:**R
操作锚点、中心点,反而是物体跟着动
(面板数值、脚本控制,不能手动直接操作)
Anchor锚点
rect transform——archor presents
子物体相当于父物体
(锚点不是点,实际可以拉出来四个边:锚点的四边和控件的四边相对位置不变)
- 4锚点合起来的情况:中间的9种
- 4锚点分开的情况:旁边的7种 大小与父物体适配缩放
通常选择4个边角
根据锚点(原点)建立坐标系,得到xy值,单位为像素px
当屏幕发生变化,游戏物体距离锚点的距离不变
alt设置位置,shift设置轴心点
图片填满整个屏幕(一般用于背景图片):archor presents,按住alt,选择右下角的方形(图片与父物体保持一致)
pivet中心点
ui物体的(0,0)
以该点计算游戏物体的坐标
0~1之间
Canvas画布
所有的UI必需在canvas下面
-
添加方式1:右键UI-Canvas
-
添加方式2:右键UI-其他控件——检测到没有canvas,自动生成canvas
第一次添加Canvas之后 ,自动生成EventSystem:用于控制事件
可以添加多个canvas,会叠加显示
在画布内添加其他控件:canvas右键-UI-其他控件
render model渲染模式
-
overlay:在所有层之上
-
camera:与具体的摄像机关联(不会与3d物体穿插)
-
world space:画布当作3d物体,可以修改transform参数(可以与3d物体穿插)
pixel perfect:画质提高,关闭抗锯齿
canvas scaler缩放
模式:
- **constant pixel size根据像素大小 **:scale fader》缩放比例 ;reference》1unity单位=多少像素(与图片上的相关参数保持一致,图片又换算回去了。。)
UI适配屏幕方法:
//原始屏幕大小 与目前屏幕大小 比例
float wScale=Screen.width/1920.0f;
float hScale=Screen.height/1080.0f;
GetComponent<CanvasScaler>().scaleFactor=wscale;//根据宽度 调整整体缩放比例
- scale with screen size根据屏幕缩放:最常用的UI适配方法
reference resolution:需要与(调试的)屏幕尺寸一致
screen match mode:
1)match width or height 0完全参考宽度~1完全参考高度,一般使用0.5
2)expand:展开,比标准大
3)shrink:压缩,比标准小
- **constant physical size根据物理大小:**适配屏幕DPI
DPI:一平方inch有多少点
graphic raycaster图片射线响应
管理canvas下的图片射线响应
ignore reversed graphic:是否忽略翻转的图片
blocking objects:什么物体会遮挡射线(none,2d,3d,all)(根据碰撞体collider判断物体类型)
blocking mask:什么会阻挡射线
canvas group组件
改变所有子物体的
alpha:透明度
interactable:可否点击响应
block raycast:接受射线检测
ignore parent group:是否受父级管理
Text文本控件
要使用外部字体——空物体 添加text组件(自己的unity版本问题?)
Text:
显示的内容:Text组件的Text属性
文字模糊的解决1:canvas控件内canvas组件——勾选Pixel Perfect属性
font:字体
使用外部字体:需要先导入
先在Assets文件夹下创建Fonts文件夹,把需要使用的字体放入文件夹
- font style
bold:加粗
italic:斜体
bold and italic:斜体加粗
-
font size字体大小
(字体超出文本框,不会显示)
-
line spacing行间距
**alignment对齐方式:**左中右 上中下
**overflow:**wrap包裹在白框内;overflow溢出
**best fit:**将内容限定在白框内,动态改变字体大小
Color颜色
Material材质
rich text富文本
≈html使用标签
同一个文本内不同格式
加粗:<b>文字</b>
斜体:<i>文字</i>
颜色:<color=green>green<color> (有官方色号表)
字体大小:<size=50>文字<size>
(详细见官方文档)
Image图片控件
先在Assets文件夹下创建Textures文件夹,把需要使用的图片放入文件夹
3D项目里的图片用作UI,需要把图片的texture type改为sprite(2D and UI)
添加方式:右键UI-image
默认是白色
**伸缩图片提前处理:**选择图片——sprite editor面板——调整边框
image控件的image组件:
-
source image:选择显示的图片
-
color:整体渲染的颜色 白色是图片原本的颜色
Color32(byte类型)0255;Color(float类型)01
-
material:材质
-
raycast target:是否检测鼠标点击事件;射线检测
改变图片大小:
按住shift,图片从左上角等比例缩放;按住shift+alt,图片从中心点等比例缩放;按住alt,上下左右对称缩放
set native size改为图片原本的大小
子物体随着父物体缩放:调整子物体的锚点(中间的白色三角)与父物体重合
父子物体之间的位置关系:需要调整好白色锚点+选择合适的archor presents
rect transform组件:
位置(x,y,z)
宽高(单位px)
左右翻转:scale x= -1
image type
-
simple正常显示
-
slice(需要先设置图片边框切割:文件中的图片— sprite editor—border属性/绿线外是边框)
四个角不会被拉伸
fill center:是否显示九宫格中间的部分
-
tiled平铺
-
filled填充
(可以用于技能CD)
fill method:填充方式(radial 360 圆圈
fill origin:开始位置
fill amount:填充了多少
Raw image贴图
UV Rect坐标(用于贴图)
xy:图片从左到右01,从下到上01
宽高:显示原本图片的比例
帧动画:
texture:图片 设置为动画的整套图
raw image控件(raw image ani组件)(脚本)
例子:图集顺序
1234
5678
public RawImage _rawImage;
private float _offsetX;//x轴偏移量
private float _offsetY;//y轴偏移量
void Start()
{
_rawImage = GetComponent<RawImage>();//初始化
_offsetX=1/4.0f;//根据图片确定
_offsetY=1/2.0f;
StartCoroutine(Ani());
}
private IEnumerator Ani()//协程 控制帧动画循环
{
//循环动画
float x=0;
float y=0;
while(true)
{
y+=_offsetY;
while(x<1)
{
x+=_offsetX;
_rawImage.uvRect = new Rect(x,y,_rawImage.uvRect.width,_rawImage.uvRect.height);//新的uv图片 位置、大小
yield return new WaitForSeconds(0.3f)//延迟
}
x=0;
}
}
在UI上展示3D模型:
建立文件夹,创建render texture(RT)
将文件赋值给camera的target texture
将文件赋值给raw image的texture
——camera显示的东西》ui的raw image上显示
(不需要展示3d物体的背景——修改camera的clear flags为solid color)
mask遮罩
只显示遮罩部分
-
mask
会增加层级,性能差,避免使用
-
Rect mask 2d
只能作用于2d
可能出bug
》》可以自己写mask脚本
》》Selectable交互组件的基类
interactable可交互的
transition变化
——color tint颜色变化
target graphic针对某个图片修改颜色
- normal
- highlighted鼠标移动在上面
- pressed鼠标按下
- selected选中之后
- disabled无法交互时
——sprite swap图片转换
——animation动画(不建议使用animation》动画用dotween!!!)
自动生成动画,需要自己k,比较死板,不好修改
Button控件
添加方式:右键UI-button
button内默认有子物体text,显示文字,可以删除
button控件内的button组件:
interactable可交互的 可触发事件
transition变化
——color tint颜色变化
target graphic针对某个图片修改颜色 默认是这个button的image组件
- normal
- highlighted鼠标移动在上面
- pressed鼠标按下
- selected按下之后
添加按钮点击事件脚本
给button挂载buttonmanager脚本
button添加点击事件:
-
代码添加事件:onClick.AddListener
-
手动添加事件:on click ()列表+
(删除事件:选中后按-减号)
指定游戏物体——指定方法
方法可以有参数,在列表里指定参数
off关闭方法;runtime only 只在运行时触发
//例子:颜色改变
private int _index;
void Start()
{
//利用代码 添加点击事件
//GetComponent<button>().onClick.AddListener(ChangeColor);
//传参 lambda表达式 套一层
//GetComponent<button>().onClick.AddListener( ()=>ChangeColor("myname") );
}
public void ChangeColor()
//public void ChangeColor(string name)
{
if(_index==0)
{
GetComponent<Image>().color=Color.blue;
}
else
{
GetComponent<Image>().color=Color.white;
}
_index= _index==0?1:0;
}
Input Field输入框
内含:
-
placeholder文本,显示提示信息(输入文本后自动被禁用)
-
text文本,控制输入
Input Field控件的Input Field组件:
character limit字符限制(0代表没有限制)
content type内容类型:
-
standard
-
interger number数字
-
decimal number十进制数字
-
Alphanumberic大小写字母+数字
-
name强制首字母大写 不能输入数字
-
email address邮件地址
-
password密码输入(输入显示为*号)
-
pin只能输入整数密码(显示为*号)
-
customer可以自定义类型
line type:
- single line一行
- multiple line多行(回车提交)
- multiple line newline多行(回车换行)
keyboard type:输入时弹出的键盘类型(移动端有用)
- number pad弹出数字键盘
caret光标
- 闪烁频率
- 宽度
- 颜色
selection color选中文本的颜色
read only只读(用处:?提交内容后不可修改)
检测事件:
-
on value changed(string)
-
on submit (string)按下回车后
-
on end edit (string)编辑结束后(回车?
Toggle单选按钮
添加方式:右键UI-Toggle
内含:
-
background背景图片
- checkmark对号(打勾)
-
label文字
in on属性:代表是否勾选
toggle transition:none直接不显示;false渐隐渐现
graphic:对号√
onValueChanged.AddListener()需要添加有参数的方法
自制单选按钮:
empty物体——添加toggle组件
empty物体下创建image(背景图片)
将image(背景图片)指定给empty物体的toggle组件的target graphic属性
image(背景图片)下创建image(勾号√)
将image(勾号√)指定给empty物体的toggle组件的graphic属性
**多个按钮中只能单选:**toggle group组件
empty物体——添加toggle group组件
empty物体下创建多个toggle控件
拖拽指定toggle控件的toggle组件的group属性(empty物体)
allow switch off:是否可以都不在选中状态 不勾选的情况下存在默认被勾选的选项
Slider滑动器
添加方式:右键UI-Slider
用途:音量大小,血量,技能cd
内含:
- background
- fill area空物体
- fill(填充的内容)
- handle slide area空物体(删除也没有影响)
- handle(滑块)
onvaluechanged 参数Value
//获取Value值
GetComponent<Slider>().onValueChanged.AddListener((value)=>Debug.Log(value));
进度条
void Start()
{
StartCoroutine(ChangeValue());
}
private IEnumerator ChangeValue()
{
Slider slider=GetComponent<Slider>();
float process=0;
while(process<1)
{
process+=0.1f;
//slider.value=Mathf.SmoothStep(slider.value,process,0.5f)//平滑变化 初始值、目标值、时间
//yield return new WaitForSeconds(0.5f);//协程
//另一种方式
yield return new WaitUntil(()=>
{
slider.value=Mathf.SmoothStep(slider.value,process,0.5f);
return process -slider.value <= 0.01f;//临界值
});
}
}
Slider控件下的Slider组件:
-
max value
-
min value
-
value当前值
-
target graphic:handle(滑动的圆圈 图片)
-
handle rect
-
fill rect(进度条)
-
direction滑动方向
Scrollbar滚动条
一般直接滚动面板(手机)
内含:
- slicing area
- handle
属性:
value滑块位置
size滑块大小
number of steps ≈滑动几次到底
Scroll view
内容:
- Scroll view
- 实际内容
- 横向滚动条Scrollbar
- 纵向滚动条Scrollbar
滚动方向horizontal/vertical
movement type:没有弹性;elastic有弹性(一般使用);clamped有内容限制
elasticity弹性
inertia滚动惯性
viewpot展示的内容区域
Scrollbar的visibility可视:permanent常驻;auto hide自动隐藏;auto hide and expand viewpot(√)
Dropdown下拉菜单
options选项
内含:
-
label文本(选择的选项)
-
arrow箭头
-
templete下拉的部分 模版 选项多的时候滚动查看
(每个选项含有Toggle)
图片:
item image选项中的图片的模版
caption image展示的图片的模版
option下设置图片
Panel面板
通过面板,进行分类:方便控制父子关系
≈空物体+图片
预制体:
设置Prefabs预设体文件夹,放置需要重复使用的物体
修改使用的预制体,右键prefab——unpack断开链接
layout布局
vertical/horizontal layout group
padding内边距(内容与白框的距离)
spacing元素之间的距离
alignment对齐方式
父子大小
-
control child size控制子物体的宽高(子物体不能自己修改)
-
use child scale考虑子物体的缩放
-
child force expand自适应白框
问题:
control child size与child force expand选项需要同时存在
grid layout group网格排列
包含了横向与纵向
可以替代横向/纵向布局
cell size子物体的大小xy
spacing元素之间的距离xy
start corner生成元素开始的地方
start axis生成的方向
constraint限制
- flexsible无限制
- fixed column限制列数
- fixed row限制行数
layout element
用于layout group管理的子物体
-
min最小
-
prefered首选(没有最小优先级高)
-
flexible灵活(每个元素分配比例)
问题:
layout group的control child size与child force expand选项不能同时选择
使用min、layout group的child force expand勾选,会预留min
content size fitters自适应大小组件
1)可以用于layout组件一起,与layout element组件搭配
- min size
- prefered size
2)搭配text文字组件,文字自适应大小
aspect ratio fitter横竖比例组件
mode:
- width control height
- height control width
- fit in parent根据宽高比放入父物体
- envelope parent根据宽高比覆盖(超出)父物体
》》事件系统
UI相关的事件系统:
eventSystem只存在一个
-
1)eventSystem组件
-
2)standalone input控制输入组件
3)canvas上的graphic raycaster组件
射线的区分:
-
graphic》响应有graphic基类的对象(如果不设置的话)
-
2d》响应2d碰撞体
-
3d》响应3d碰撞体
UGUI实现事件的方式:
- 调用接口(推荐!)
- 在unity面板手动添加组件(例event trigger)
- 代码添加组件
EventTrigger组件
1)在unity界面手动添加组件,设置事件
2)使用代码添加组件,设置事件
(需要先初始化事件列表)
void Start()
{
EventTrigger trigger=gameObject.AddComponent<EventTrigger>();//增加组件
trigger.triggers=new List<EventTrigger.Entry>();//初始化事件列表
EventTrigger.Entry entry=new EventTrigger.Entry();//定义绑定类型
entry.eventID=EventTrigger.PointerClick;
entry.callback=new EventTrigger.TriggerEvent();//添加回调函数
entry.callback.AddListener((data)=>ChangeColor());//添加方法
}
接口
clickTime:记录的是运行开始后计时的时间点
拖拽事件
-
IInitializePotentialDragHandler
即将开始拖拽≈鼠标按下(执行一次)
-
IBeginDragHandler
开始拖拽(执行一次)
-
IDragHandler
拖拽过程中(移动?)
-
IEndDragHandler
结束拖拽(执行一次)
必须有IDragHandler,其他拖拽函数才会执行
public void OnDrag(PointEventData eventData)
{
var rect=GetComponent<RectTransform>();//获取当前的Rect transform
Vector3 pos=Vector3.zero; RectTransformUtility.ScreenPointToWorldPointInRectangle(rect,eventData.position,eventData.enterEventCamera,out pos);//屏幕坐标转换为世界坐标(Rect transform,位置,当前的相机,输出)(out参数》自己查)
rect.position=pos;//位置>>输出的坐标
}
-
IDropHandler
放下物体(在IEndDragHandler之后执行)
必须有IDragHandler才会执行
存在层级问题:会执行最上层物体的方法,而不是拖拽物体的方法
解决方法:(让拖拽的物体一直在最上层)
添加canvas组件,勾选override;(尽量少用多个canvas)
添加graphic raycaster,否则无法再拖、
拖动的另一种实现方式:
public void OnDrag(PointEventData eventData)
{
var rect=transform.GetComponent<RectTransform>();
rect.anchoredPosition+=eventData.delta;
}
点击选择事件
-
IPointerEnterHandler
鼠标进入范围
-
IPointerExitHandler
鼠标移出范围
-
IPointerDownHandler
鼠标按下
-
IPointerUpHandler
鼠标抬起
-
IPointerClickHandler
鼠标点击
UGUI的bug:父子物体的点击事件一定情况下可能不执行》解决 子物体有IPointerDownHandler
选中事件
-
ISelectHandler
选中的第一帧
-
IUpdataSelectedHandler
选中时(点击后一直处于选中状态)
-
IDeselectHandler
结束(鼠标点击其他地方才算结束)
物体本身必须有selectable组件或继承selectable的组件
系统按键
(简单实现)
需要先选中物体
-
IScrollHandler
鼠标滚轮
需要停留在物体上
-
ISubmitHandler
提交键(默认为回车、空格)
-
ICancelHandler
取消键(默认为esc)
-
IMoveHandler
方向键(默认asdw、上下左右)
物体本身必须有selectable组件或继承selectable的组件
与standalone input module组件对应
edit——program setting——input对应
》》》《用户登录》案例
输入框
- 提示信息
登录按钮
- 按钮点击事件
获取输入信息:input field控件的input field组件的text属性
(InputField)(text)
//main camera挂载LoginController脚本
//拖拽指定usernameInput和passwordInput控件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//
using UnityEngine.SceneManagement//
public class LoginController:MonoBehavior
{
public InputField usernameInput;//需要引入命名空间UnityEngine.UI;需要在unity拖拽指定
public InputField passwordInput;
public Text messageText;
public void OnLoginButtonClick()
{
string username = usernameInput.text;
string username = usernameInput.text;
if (username=="admin" && password=="admin")//用户名、密码正确
{
//场景跳转
SceneManager.LoadScene("场景名称")//需要引入命名空间
}
else
{
messageText.text="输入错误,请重新输入!";
messageText.enabled=true;//激活
StartCoroutine(HideMessage())//调用协程
}
}
//协程,控制提示信息消失
IEnumerator HideMessage()
{
yield return new WaitForSeconds(1);
messageText.enabled=false;
}
}
//跳转需要设置:file-build setting添加当前场景和需要跳转的场景
- 登录失败,提示信息
初始为禁用状态
- 提示信息自动消失
利用协程
- 信息慢慢隐藏
color的RGBA中A代表透明度,控制透明度,可以让信息慢慢隐藏
》》》《关卡游戏》UI案例
导入unity package file(素材文件)
(3d项目内使用图片,需要全选把所有图片type改为sprite(2d and UI))
用户界面
背景图片:全屏填充 = archor presents,按住alt,选择右下角的上下左右填充
其他图片:set native size;按住shift,图片从左上角等比例缩放;按住shift+alt,图片从中心点等比例缩放;按住alt,上下左右对称缩放
按钮:在图片上添加button组件;修改target graphic,更改按钮目标图片
文本:空物体 添加text组件(不同种类的text控件 可使用的字体不同);调整对齐方式
文字添加阴影:添加shadow组件;调整阴影的颜色;调整xy轴的偏移量
文字添加边框:添加outline组件;调整阴影的颜色;调整xy轴的
血条
需要slider组件,不需要完整的slider控件
取消勾选interactable,因为不需要玩家控制血条进度条(注意调整disabled的颜色,改为正常状态)
不需要handle滑块
血条的构成:
- 背景*(添加slider组件)*
- 底层血条
- 上层血条*(指定为 slider的 file rect)*
调整上层血条的填充模式:image type——filed;fill method——horizontal
指定file过后,上层血条的fill amount(不能修改)== 背景slider的value(后续可以通过代码控制)
技能冷却
技能图标构成:
- 背景图片(添加button组件;添加脚本)
- 技能图片
- 技能图片遮罩(灰色覆盖=技能图片+color灰)
调整技能图片遮罩的填充模式:image type——filed;fill method——radial360(从中心点开始360度转);fill original——top/bottom(从哪里开始);clockwise——false
状态变化:
初始状态:无技能遮罩(fillamount=0)
进入冷却:技能遮罩(fillamount=1)
冷却中:技能遮罩随着时间变化(fillamount=(coldTime - timer) / coldTime)
冷却结束:无技能遮罩(fillamount=0)
**技能触发方式:**1点击——button - on click;2快捷键——Input.getKeyDown(KeyCode.Alpha1)
1)点击触发——
using UnityEngine;
using UnityEngine.UI;//使用Image
public class SkillItem : MonoBehaviour
{
public float coldTime = 2;//技能冷却时间
private float timer = 0;//计时器
public bool isColding = false;//是否正在冷却 默认不在冷却
private Image coldMask;//需要引入命名空间UnityEngine.UI(快捷键:alt+回车)
void Start()
{
coldMask = transform.Find("ColdMask").GetComponent<Image>();//通过名字查找子物体、查找组件
}
void Update()
{
if(isColding)
{
timer += Time.deltaTime;//计时器随着时间增加
coldMask.fillAmount = (coldTime - timer) / coldTime;//剩余冷却时间 百分比 =》冷却遮罩的转动
if (timer>coldTime)//冷却时间结束
{
isColding = false;
timer = 0;//计时器归0
coldMask.fillAmount = 0;//遮罩不显示
}
}
}
public void OnSkillClick()//技能点击事件
{
if (isColding==false)//不在冷却中,可以使用技能;冷却中不能使用
{
isColding = true;//使用技能后,进入冷却
timer = 0;//计时器归0
coldMask.fillAmount = 1;//遮罩完全显示
}
}
}
设置button组件的on click事件:
——(拖拽)选择脚本SkillItem——选择脚本中的事件OnSkillClick
2)按钮触发(与点击触发同时可用)——
变量keyCode可以在unity中修改
using UnityEngine;
using UnityEngine.UI;
public class SkillItem : MonoBehaviour
{
public float coldTime = 2;//技能冷却时间
private float timer = 0;//计时器
public bool isColding = false;//是否正在冷却 默认不在冷却
private Image coldMask;//需要引入命名空间UnityEngine.UI(快捷键:alt+回车)
public KeyCode keyCode = KeyCode.Alpha1;//按键 数字1
void Start()
{
coldMask = transform.Find("ColdMask").GetComponent<Image>();//通过名字查找子物体、查找组件
}
void Update()
{
if(isColding)
{
timer += Time.deltaTime;//计时器随着时间增加
coldMask.fillAmount = (coldTime - timer) / coldTime;//剩余冷却时间 百分比 =》冷却遮罩的转动
if (timer>coldTime)//冷却时间结束
{
isColding = false;
timer = 0;//计时器归0
coldMask.fillAmount = 0;//遮罩不显示
}
}
if(Input.GetKeyDown(keyCode))//检测某个按键按下,按下返回true
{
SkillRelease();
}
}
public void OnSkillClick()//技能点击事件
{
SkillRelease();
}
public void SkillRelease()
{
if (isColding == false)//不在冷却中,可以使用技能;冷却中不能使用
{
isColding = true;//使用技能后,进入冷却
timer = 0;//计时器归0
coldMask.fillAmount = 1;//遮罩完全显示
}
}
}
背包物品 选项卡
单个选项:
- 未选中状态 图片(添加toggle组件)
- 选中状态 图片
设置子物体锚点,与父物体一致大小、一起缩放
未选中状态图片 添加toggle组件:
graphic 设置为 选中状态图片
is on:true——选中状态;false——未选中状态
多个按钮中只能单选:
- 父对象(toggle Group组件)
- 选项1 未选中状态(toggle组件)
- 选中状态
- 选项2 未选中状态(toggle组件)
- 选中状态
- 选项3 未选中状态(toggle组件)
- 选中状态
- 选项1 未选中状态(toggle组件)
复制多个单选项卡
全部选中后右键,创建父对象 create empty parent
设置toggle group:
父对象添加toggle Group组件
子对象设置toggle组件的Group为父对象
(如何通过选项控制 选项卡文字 颜色?利用maskable属性?——自查)
选中不同选项,显示不同物体:
设置子物体的toggle组件 on value change
——选中后显示的物体——gameobject.setactive方法
背包物品 网格布局grid:
- 父物体(grid layout group组件)
- 空物体(方便控制格子位置、大小)
- 格子背景
- 格子内容1
- 格子背景
- 空物体
- 格子背景
- 格子内容2
- 格子背景
- 空物体(方便控制格子位置、大小)
先创建一个格子内容,之后整体放入grid父物体
ctrl+d获得多个格子,自动进行网格布局
设置grid组件的属性:
cell size:格子大小
spacing:格子间距
关卡选择页面
grid网格布局
设置左右的多页:
原点放在最左边
grid组件的start axis设置为vertical竖向增加
滚动页面:
- Scroll物体(Scroll Rect组件)(image)(mask)(scroll脚本)
- grid物体(grid layout group组件)
- 空物体(便于控制物体大小)
- 内容
- 空物体(便于控制物体大小)
- grid物体(grid layout group组件)
Scroll Rect组件的content设置为grid物体
滚动方向选择horizontal左右滚动,不勾选vertical上下滚动
**image组件:**检测到物体才能滚动=》Scroll物体添加image组件
**mask组件:**根据图片范围,遮住区域外面的物体;不勾选show mask graphic,即可不显示图片
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class LevelScroll : MonoBehaviour,IBeginDragHandler, IEndDragHandler//需要引入命名空间EventSystems
{
private ScrollRect scroll;//需要引入命名空间UI
private float[] pagePosition = new float[3] { 0, 0.5f, 1 };//每一个页面的位置,几页就几个位置,n-1平分1
// Start is called before the first frame update
void Start()
{
scroll = GetComponent<ScrollRect>();//获取组件
}
// Update is called once per frame
void Update()
{
}
public void OnBeginDrag(PointerEventData eventData)//开始拖拽
{
}
public void OnEndDrag(PointerEventData eventData)//结束拖拽
{
float currentPosition=scroll.horizontalNormalizedPosition;//xy为0~1 按照比例转换
//scroll.verticalNormalizePosition 只获取垂直方向
//scroll.horizontalNormalizePosition 只获取水平方向
//scroll.normalizePosition 获取两个方向 vector2
int index = 0;//默认离第一个页面最近
float offSet = currentPosition - pagePosition[0];//初始为距离第一个页面的偏移量
for(int i=1;i<3;i++)//从第二个页面开始
{
if(Mathf.Abs(currentPosition - pagePosition[i])< offSet)//距离页面的偏移量,需要取绝对值
{
index = i;
offSet = Mathf.Abs(currentPosition - pagePosition[i]);//相比前一个页面的偏移量小,则置为新的最小偏移量
}
}
scroll.horizontalNormalizedPosition = pagePosition[index];//直接设置为距离最近的页面
}
}
缓慢滑动动画:
Mathf.Lerp插值方法
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class LevelScroll : MonoBehaviour,IBeginDragHandler, IEndDragHandler//需要引入命名空间EventSystems
{
private ScrollRect scroll;//需要引入命名空间UI
private float[] pagePosition = new float[3] { 0, 0.5f, 1 };//每一个页面的位置,几页就几个位置,n-1平分1
private float targetPosition = 0;//目标值
private bool isMoving = false;//是否在滚动
private float speed = 8;
// Start is called before the first frame update
void Start()
{
scroll = GetComponent<ScrollRect>();//获取组件
}
// Update is called once per frame
void Update()
{
if(isMoving)
{
scroll.horizontalNormalizedPosition = Mathf.Lerp(scroll.horizontalNormalizedPosition, targetPosition, Time.deltaTime*speed);//实现缓动动画=》插值运算方法(当前值,目标值,移动距离=时间*速度)
if(Mathf.Abs(scroll.horizontalNormalizedPosition- targetPosition)<0.001f)//差距较小,当作移动到了
{
isMoving = false;//结束移动
scroll.horizontalNormalizedPosition = targetPosition;//直接移动目标位置
}
}
}
public void OnBeginDrag(PointerEventData eventData)//开始拖拽
{
}
public void OnEndDrag(PointerEventData eventData)//结束拖拽
{
float currentPosition=scroll.horizontalNormalizedPosition;//xy为0~1 按照比例转换
int index = 0;//默认离第一个页面最近
float offSet = currentPosition - pagePosition[0];//初始为距离第一个页面的偏移量
for(int i=1;i<3;i++)//从第二个页面开始
{
if(Mathf.Abs(currentPosition - pagePosition[i])< offSet)//距离页面的偏移量,需要取绝对值
{
index = i;
offSet = Mathf.Abs(currentPosition - pagePosition[i]);//相比前一个页面的偏移量小,则置为新的最小偏移量
}
}
targetPosition = pagePosition[index];//设置目标的页面
isMoving = true;
}
页面跳转:
- pageButton父物体(toggle group)
- 按钮 未选中(toggle)
- 按钮选中
- 按钮 未选中(toggle)
- 按钮选中
- 按钮 未选中(toggle)
- 按钮选中
- 按钮 未选中(toggle)
修改scroll脚本:
——点击页面按钮,跳转页面
(scroll脚本)分别添加了每个页面的跳转函数 MoveToPage(bool isOn) (?可以尝试整合写法)
每个按钮toggle组件 设置on value change方法为 scroll物体的对应的MoveToPage方法
public void MoveToPage1(bool isOn)//移动到某个页面
{
if(isOn)//选中
{
isMoving = true;//开始移动
targetPosition = pagePosition[0];//移动到指定页面
}
}
public void MoveToPage2(bool isOn)
{
if (isOn)
{
isMoving = true;
targetPosition = pagePosition[1];
}
}
public void MoveToPage3(bool isOn)
{
if (isOn)
{
isMoving = true;
targetPosition = pagePosition[2];
}
}
——滚动页面,页面按钮改变
(scroll脚本)添加了toggleArray 控制toggle的isOn
按照顺序 把按钮(toggle)设置为toggleArray
public Toggle[] toggleArray;//选项 可以通过unity面板控制
public void OnEndDrag(PointerEventData eventData)//结束拖拽
{
……
toggleArray[index].isOn = true;//选中对应的页面按钮
}
任务列表
上边栏component——布局layout——多种布局
vertical layout 布局:
vertical layout group组件——
spacing间距
child alignment对齐方式
padding整个内容对于各个方向的边距
与grid布局、滚动类似
- Scroll物体(Scroll Rect组件)(image)(mask)
- vertical layout group
- 单一物体
- vertical layout group
设置面板
**声音大小滑动器:**slider
- background背景
- fill area
- fill填充图片
- handle slide area
- handle滑块图片
伸缩图片需要设置好border、sliced
**难易度单选按钮:**toggle group
自定义开关:
- 背景图片(toggle)(myToggle脚本)
- 开启状态
- 关闭状态
在unity面板配置onGameObject、offGameObject为对应物体
将背景图片的myToggle脚本-OnValueChange方法 配置到背景图片的Toggle组件的onValueChange
using UnityEngine;
using UnityEngine.UI;
public class myToggle : MonoBehaviour
{
//unity面板配置 public参数
public GameObject onGameObject;//开启状态
public GameObject offGameObject;//关闭状态
private Toggle toggle;//引入命名空间UI
// Start is called before the first frame update
void Start()
{
toggle = GetComponent<Toggle>();//查找Toggle组件
OnValueChange(toggle.isOn);//根据Toggle组件的isOn属性改变,而改变物体的active状态,控制显示隐藏
}
// Update is called once per frame
void Update()
{
}
public void OnValueChange(bool isOn)
{
//开启关闭物体 active状态相反
onGameObject.SetActive(isOn);//选中为on
offGameObject.SetActive(!isOn);//默认未选中为off
}
}
登录面板:
- input field
- placeholder提示信息
- text输入的内容