目录
[TOC]
一、基础
1.适配小技巧–1_Pivot的应用
Pivot:
- 名称:轴心点,
- 说明:代表当前物体位置,是一个比例值。
- 使用:在Inspector面板中可以直接修改;或者,更改”Center”为”Pivot”,如下图:
例子:想要中间的黑色Image适配到蓝色Image的左上角。
方法一:不使用Pivot
直接设置锚点,设置锚点的时候按住“Alt”键可以在设置锚点的同时设置物体Position。
设置之后的结果如下图:
黑色Image的Inspector面板显示如下图:
其中PosX和PosY分别为Width和Height的一半。
此法的缺点:在设置此Img的位置时候,代码中需要考虑到Img的宽高。
方法二:使用Pivot
首先将轴心点Pivot移动到左上角,然后同上一样设置锚点。
设置之后的结果如下图:
黑色Image的Inspector面板显示如下图:
此时的PosX和PosY均为0,意思是代表黑色Img位置的轴心点Pivot与锚点之间的相对位置为(0,0)。
此法的优点:不再需要在代码中考虑Img的宽高,降低代码复杂度。
2.获取UI宽高(安全方式)
//获取RectTransform
RectTransform rectTrans = transform.GetComponent<RectTransform>();
//通过RectTransform获取宽高:
rectTrans.rect.width;
rectTrans.rect.height;
3.使用蓝图模式控制UI旋转、缩放时的响应区域
蓝图模式
开启方式:在检视面板中,如下图所示:
作用:开启后,无论是旋转还是缩放UI,UI的响应区域均保持不变。
使用情景:UI存在动画,但即使是在动画播放的过程中依旧需要保持响应区域不变,则可以使用蓝图模式。
4.原始编辑模式(Raw Edit Mode)
原始编辑模式
开启方式:在检视面板中,如下图所示:
作用:作用于Anchors和Pivot,具体应用场景不详。
5.Canvas画布下三个核心组件:Canvas、Canvas Scaler、Graphic Raycaster
(1)Canvas的三种模式
- 1.Screen Space - Overlay:
a.画布独立于场景空间存在,存在于屏幕空间;b.UI永远显示在最上层;c.画布的坐标计算基于屏幕空间,由Unity自动计算,不可在检视面板中手动调整。
Pixel Perfect:开启后,会关闭抗锯齿,抗锯齿会影响到像素,所以在像素要求严格的情况下勾选。
Sort order:排序
- 2.Screen Space - Camera:
a.画布需要与指定相机关联(Render Camera);b.画布的坐标计算基于屏幕空间,由Unity自动计算,不可在检视面板中手动调整。
关联后:
Plane Distance:画布平面到摄像机的距离,此距离即画布深度,会影响到UI是否被游戏物体遮挡(深度剔除)。
- 3.World Space:
同上也需要关联相机,关联后:
a.画布需要与指定相机关联(Render Camera);b.画布的坐标计算基于世界空间,可在检视面板中手动调整。
(2)三种不同UI Scale Mode下的适配
a.Constant Pixel Size模式
Constant Pixel Size模式为恒定像素大小模式,屏幕中UI元素的大小由ScaleFactor(缩放因子)和ReferencePixelsPerUnit(每Unity单位对应的像素个数)共同决定。
在此模式下需要通过脚本来动态调整ScaleFactor:脚本挂载在Canvas中
public class ConstantScaler : MonoBehaviour
{
private const float SCREEN_WIDTH = 1334.0f;
private const float SCREEN_HEIGHT = 750.0f;
private void Start()
{
float wScreen = Screen.width / SCREEN_WIDTH;
float hScreen = Screen.height / SCREEN_HEIGHT;
//假定依据宽来适配:
GetComponent<CanvasScaler>().scaleFactor = wScreen;
}
}
开发过程中,使用1334x750的Screen,如下图:
在真机运行时可能为其他分辨率,例如800x600或1920x1080等。
在编辑模式下,切换Screen为1920x1080后,如下图:
此时可以看见,并未适配成功,原因在于我们必须在运行模式下,执行Start方法中的逻辑才能调整scaleFactor。点击运行后,如下图:
此时的Canvas中的Canvas Scaler组件:
Scale Factor由1变为了1.43928(≈1920/1334),如此一来便达到了适配的效果。
b.Scale With Screen Size模式
适配比较常用的模式,会依据屏幕尺寸进行缩放。
设置分辨率为1334x750,保持和开发过程中的Game视图中的分辨率一致。
Screen Match Mode匹配模式通常选择Match Width Or Height模式,表示屏幕适配是依据屏幕宽或高,就像(1)Constant Pixel Size模式
中所做的那样。然后调整Match来控制宽高适配权重。
该模式下的屏幕适配往往还需配合UI元素锚点的设置,Match常用权重值:0、0.5、0.618、1。
c.Constant Physical Size模式
恒定的物理大小模式,该模式适配是依据的屏幕物理大小,具体应用很少,此处略过。
(3)Graphic Raycaster图形射线组件
该组件负责控制管理该Canvas画布下所有UI元素的射线交互,例如按钮点击。如果移除或禁用该组件,则和射线相关的交互均会失效。
- Ignore Reversed Graphics:是否忽略反转的图形,顾名思义,如果勾选(默认勾选)则当UI元素
的Rotation中的Y大于90度,即产生了翻转,则不再受图形射线组件控制,即不再有射线交互效果。
- Blocking Objects:阻挡对象,表示哪些对象可以阻挡UI射线。
Three D:3D指的是拥有3D碰撞体的物体,也就是说即使是UI元素,只要其拥有3D碰撞体,在此处也算作3D。
- Blocking Mask:阻挡遮罩,设置哪些层级可以阻挡UI射线。
6.Canvas Group的使用
添加CanvasGroup组件可以统一控制自身和子物体的透明度、是否可交互、是否接受UI射线
Ignore Parent Groups:是否忽略父层级的CanvasGroup设置。
7.UI渲染层级
对UI渲染层级影响重要性由大到小如下:
(1)Camera的深度Depth值
当场景中存在多个Canvas以及多个Camera时:
若要将多个Canvas显示在统一屏幕中,则设置Canvas组件的Render Mode为Screen Space - Camera并指定Render Camera
在Scene场景中两个摄像机分别渲染不同的两个Canvas,如下图:
而Game视图中,渲染的图像是由Camera的Depth值决定的,Camera的Depth值会影响Canvas的渲染顺序,Depth值越小越先渲染,后渲染的会覆盖先渲染的。
我们设置Camera的Depth值为0,MainCamera的Depth值依旧保持默认-1。
查看Game视图:
然而此时虽然显示了Camera下的Canvas,然而却没有显示MainCamera下的Canvas,原因在于Camera的Clear Flags设置为Skybox,即在渲染Camera时,会在渲染完不透明对象后渲染一次天空盒,此时渲染的天空盒会覆盖掉早先MainCamera渲染的Canvas图像。详细渲染顺序可见”Analysis-Frame Debugger“,如下图:
深度值为0的Camera在绘制图像时绘制的天空盒覆盖了深度值为-1的MainCamera绘制的Canvas图像。
解决的方式是:设置Camera的Clear Flags为Depth only。
此时Game视图已经可以正常显示两个Canvas中的UI元素图像了。
(2)Canvas组件内的Sorting Layer和Order in Layer
在同一Camera下的Canvas中,要进一步规定UI渲染层级则需要使用Canvas组件。
首先,在Canvas画布中的Canvas组件内添加Sorting Layer:
然后为UI元素添加Canvas组件,并勾选Override Sorting,然后可以设置Sorting Layer和Order in Layer。其中Sorting Layer为排序层级,层级越接近Default则表示越先渲染,后渲染的会覆盖先渲染的;Order in Layer为层间排序,即相同层级下再进行排序,序号越小越先渲染,同样的后渲染的会覆盖先渲染的。
例如,可以将Child的Sorting Layer设置为second,而Parent保持Default不变。
此时,原本被Parent覆盖的小图片Child渲染在Parent之上了:
(3)UI的自然层级
自然层级:在同一Canvas中越靠前的UI元素越先渲染,后渲染同样会覆盖先渲染的。不过自然层级对UI渲染先后顺序的影响会被Sorting Layer和Order in Layer强制改变,所以说UI的自然层级对于UI的渲染先后顺序的影响是最弱的。
8.Image
Image参数介绍:
Source Image:此处需设置图片类型为Sprite(2D and UI)的Texture。
Color:设置颜色,RGBA格式,可以设置参数为0~255byte类型或0~1的float类型。在代码中:byte类型的颜色为Color
,float类型的颜色为Color32
。
Material:可以添加带有特殊shader的材质。
Raycast Target:勾选后才能接收到UI射线,才能响应UI射线交互。
Image Type:图片类型,有四种可选类型:
- Simple:普通的单张图片
- Sliced:经过九宫格切割的图片(常用于切割边框,保证边框的清晰度)
- Tiled:平铺
- Filed:填充(常用于制作技能冷却)
9.RawImage
(1)常规用法–序列帧动画
Boom动画如下:
实现方式一:RawImage+CSharp脚本
创建RawImage,并附上Texture,然后编写脚本:
public class RawImageAnim : MonoBehaviour
{
public float SizeX;
public float SizeY;
[Tooltip("动画持续时间")]
public float AnimDuration;
private RawImage mRawImage;
private WaitForSeconds mDelay;
private float mWidth;
private float mHeight;
private void Start()
{
mRawImage = GetComponent<RawImage>();
mDelay = new WaitForSeconds(AnimDuration / (SizeX * SizeY * 1.0f));
mWidth = 1.0f / SizeX;
mHeight = 1.0f / SizeY;
StartCoroutine(PlayAnim(true));
}
private IEnumerator PlayAnim(bool loop)
{
float u = 0f, v = 1f;
while (true)
{
v -= mHeight;//v坐标可以为负,类似于竖直方向上的平铺循环,具体可以自行测试
while (u < 0.9998f)//此处存在float计算精度问题
{
mRawImage.uvRect = new Rect(u, v, mWidth, mHeight);//此处uv是图片左下角的uv坐标
u += mWidth;
yield return mDelay;
}
u = 0f;//重置
if (loop == false && v <= 0f) break;//循环播放的开关
}
}
}
实现方式二:Shader
Shader "Custom/序列帧动画"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_SizeX("水平方向上图片个数",Float) = 4
_SizeY("竖直方向上图片个数",Float) = 4
_AnimSpeed("动画播放速度",Range(1,100)) = 30
}
SubShader
{
//特效使用和半透明物体一样的渲染设置
Tags { "RenderType"="Transparent" "IngoreProjector"="True" "Queue"="Transparent" }
LOD 100
Pass
{
Tags{ "LightMode"="ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _SizeX;
float _SizeY;
float _AnimSpeed;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float time = floor(_Time.y * _AnimSpeed);
float v = floor(time / _SizeX);
float u = time - v * _SizeX;
float2 uv = i.uv + float2(u , -v-1);//v坐标可以为负,类似于竖直方向上的平铺循环,具体可以自行测试
uv.x /= _SizeX;
uv.y /= _SizeY;
fixed4 col = tex2D(_MainTex, uv);
return col;
}
ENDCG
}
}
}
(2)常规用法–3D模型展示
需要:Render Texture、一个专门用于渲染指定3D物体的Camera、RawImage。
首先,使用Camera渲染指定3D物体;
然后,指定该Camera上的Target Texture为刚新建的Render Texture;
最后,将Render Texture赋值给RawImage即可。
10.Text
(1)基础介绍:
Line Spacing:行间距
Rich Text:富文本
Align By Geometry:几何对齐,勾选之后会紧紧贴合边缘。
Horizontal Overflow:水平方向是否可以超出显示,若选择Wrap(包裹)则不会超出显示。
(2)富文本
勾选Rich Text后可以在Text中编辑富文本。
- 加粗:
<b>内容</b>
- 斜体:
<i>内容</i>
- 字体大小:
<size=50>内容</size>
(注意!:使用富文本设置字体的时候不能勾选Best Fit) - 字体颜色:
<color=#ff0000>内容</color>
(色号表可百度搜索)
例子:
内容<b>内容</b>内容<i>内容</i>内容<b><i>内容</i></b>内容<size=50>内容</size>内容<color=#ff0000>内容</color>内容<b><i><size=55><color=#ff0000>内容</color></size></i></b>
11.图片遮罩:Mask和Rect Mask 2D
-
遮罩的所用:用于限制显示区域,只在设置有遮罩的区域显示图片信息。
-
Mask:一种3D遮罩,也可用于2D物体。
在UI部分不要使用Mask来完成遮罩效果,原因是:Mask使用模板缓冲来限制显示区域,会增加DrawCall同时会打断UI的批处理再一次增加DrawCall。
-
Rect Mask 2D:2D遮罩,在CPU阶段决定显示区域,所以不会增加DrawCall,但是不会进行UI批处理。
-
总结:Rect Mask 2D内的ui节点不可以和外面的ui节点合并批次, 多个Rect Mask 2D之间也不可以合并批次,但是多个Mask之间内的ui节点是可以合并批次的!并且多个Mask首尾dc如果满足条件也是可以分别合并的!
补充一个Rect Mask 2D使用的Bug:
更多遮罩相关资料:
Unity手游开发札记——使用Shader进行UGUI的优化