Rect Transform(锚点):图片中心的四个点,界面以雪花形式显示
当四个点在一起的时候组成锚点,当四个点分开的时候组成锚框(合则锚点,分则锚框)
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222012057-2100178633.png)
Anchors:
----Min x:控制左两个点,当为0的时候,左两个点在父物体边框的左边缘,当为1时,左两个点在父物体边框的右边缘(取值范围并不是0~1)
----Min y:控制下两个点,当为0的时候,下两个点在父物体边框的下边缘,当为1时,下两个点在父物体边框的上边缘(取值范围并不是0~1)
----Max x:控制右两个点,当为0的时候,右两个点在父物体边框的左边缘,当为1时,右两个点在父物体边框的右边缘(取值范围并不是0~1)
----Max y:控制上两个点,当为0的时候,上两个点在父物体边框的下边缘,当为1时,上两个点在父物体边框的上边缘(取值范围并不是0~1)
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222035892-219277758.png)
当四个点在一起时:
----Pos X, Pos Y, Pos Z(锚点坐标):图片中心点相对于锚点的坐标
----Width, hight:图片的宽高
当四个点分开的时:
----Left:物体的左边框距离左两个锚点组成左锚框的距离;正值表示左锚框在左边框的左边,负值相反
----Top:物体的上边框距离上两个锚点组成上锚框的距离;正值表示上锚框在上边框的上方,负值相反
----Right:物体的右边框距离右两个锚点组成右锚框的距离;正值表示右锚框在右边框的右边,负值相反
----Bottom:物体的下边框距离下两个锚点组成下锚框的距离;正值表示下锚框在下边框的下方,负值相反
锚点作用:子物体自适应父物体拉伸的变化,父物体挤压过度,子物体会消失
Rect Transform的两个可选的编辑模式:Width, hight后的两个按钮。
第一个按钮(虚方框):如果选择后,不能鼠标旋转图片。
第二个按钮(R):如果选择后,当改变中心点的值时,中心点不动,图片移动。
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222057871-1774985471.png)
Pivot(中心点,轴心点):旋转中心
----X:0时,在物体左边框的位置,1时,物体右边框的位置(取值范围并不是0~1)
----Y:0时,在物体下边框的位置,1时,物体上边框的位置(取值范围并不是0~1)
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222250469-263947631.png)
框的显示:快捷键T
代码操作,继承Transform
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UGUI_RectTransform : MonoBehaviour { public Canvas canvas; //1、手动拖拽 private RectTransform rt; // Use this for initialization void Start () { //2、获取方式 rt = GetComponent<RectTransform>(); //3、里氏转换原则 rt = transform as RectTransform; //锚点坐标(物体中心点相对于锚点的坐标) //rt.anchoredPosition = new Vector2(50, 100); //世界坐标 //rt.position = Vector3.zero; //相对于父物体坐标系的坐标, 跟锚点坐标不一样。 //rt.localPosition = new Vector2(50, 100); //设置物体的宽高。只有四个点在一起组成锚点时使用 //rt.sizeDelta = new Vector2(500, 400); //设置锚点 //rt.anchorMax = Vector2.one * 0.5f; //rt.anchorMin = Vector2.one * 0.5f; //当四个点不在一起组成锚框时 //设置的是Left和Bottom,界面的值就是100, 50 //rt.offsetMin = new Vector2(100, 50); //设置的是Right和Top,界面的值是设置值的负值 -100 50 //rt.offsetMax = new Vector2(100, 50); //设置中心点 rt.pivot = Vector2.one; InstanceImage(); } // Update is called once per frame void Update () { //if (Input.GetMouseButton(0)) //{ // rt.anchoredPosition = new Vector2(500, 400); //} //if (Input.GetMouseButton(1)) //{ // rt.position = Vector3.zero; //} //if (Input.GetMouseButton(2)) //{ // rt.localPosition = new Vector2(50,100); //} } void InstanceImage()//加载图片,默认生成在层级面板的根目录下 { GameObject prefab = Resources.Load<GameObject>("prefab"); GameObject obj = Instantiate(prefab, canvas.transform); } }
Canvas(画布):所有的UGUI的组件都需要放在Canvas下才能显示
Render Mode(渲染模式):
----Screen Space – Overlay(屏幕空间-覆盖):这种模式下,所有的UI都会放在最前方,会覆盖掉其他物体显示。
--------Sort Order:当多个Canvas时,如果所有的Canvas都是Screen Space – Overlay这种模式,那么当Sort Order的值越大,该Canvas越后渲染,越显示在屏幕的最前方。
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222339658-992627437.png)
----Screen space – Camera(屏幕空间-相机渲染):该模式下,必须指定一个渲染该Canvas的摄像机,3D物体可以遮挡住UI。Rect Transorm不可修改,随相机深度进行缩放
--------Plane Distance:Canvas画布距离渲染相机的距离
--------该模式下,不同的Canvas渲染的关系:
--------首先判断Sorting Layer:值越靠后越后渲染。
--------如果Sorting Layer值相同,再判断order in layer:值越大越后渲染,越再屏幕的前方。
--------如果order in layer值也相同,再判断plane distance:距离相机越近,越显示在屏幕的前方。
--------优先级:Sorting Layer -> Order in Layer -> Plane Distance
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222353879-972015951.png)
----World Space(世界空间):只有该模式下Canvas的Rect Transorm才能编辑,并且纵深Z值有效了。
Canvas Scaler(画布缩放):
----UI Scale Mode
--------ConstantPixel Size:画布的尺寸像素会随着屏幕的变化而变化(少用)
--------Scale With Screen Size:画布的尺寸像素跟屏幕分辨率无关,需要指定画布的尺寸像素(常用)
------------Reference Resolution:指定画布的尺寸。
--------Constant Physical Size:每个屏幕渲染多少个DPI(很少用)
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222513657-242063657.png)
--------Screen Match Mode:
------------Match With or Heitht:以屏幕宽或者高作为适配
------------Expand:不管屏幕分辨率是多少,画布的内容一定要全部显示出来
------------Shrink:不管屏幕分辨率是多少,一定要使用画布的内容充满整个屏幕
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222525277-811339721.png)
Graphic Raycaster
Ignore Reversed Graphics:是否忽略反面的射线检测
Blocking Objects:指定物体对UI射线检测产生影响(非overlay的情况)
Blocking Mask:指定哪一个层的物体对UI射线检测产生影响;
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222548689-1140526360.png)
Toggle(单选框)
交互、过渡、导航
Is On:是否选中
Toggle Transition(过渡效果):无,淡入淡出
Graphic:选中时显示的图片,默认对勾图片
Group(单选框组):
OnValueChanged:当Is On改变的时候,执行里面存储的所有方法
----1、拖拽形式,方法必须是公共的,可以有参可以无参,注意:有bool型参数的时候注意可变参数和固定参数。
----2、代码注册事件的形式:注意只能把无返回值,有bool型参数的方法注册进去。
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222706746-390109407.png)
Button的OnClick无参,方块代表是固定参数
Toggle的OnValueChanged有参,方块代表是可变参数
代码操作
Toggle -> ToggleEvent -> UnityEvent -> UnityAction
ToggleEvent:参数T0 = bool
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211222719212-1731216709.png)
UnityEvent:Invoke方法也需要有一个bool类型的参数
UnityAction:无返回值的泛型委托,参数未指定
Toggle Group(单选框组):实现一组Toggle的单选效果,只有一个Group内的Toggle才是一个组。
Allow Switch off
勾选:可全部为空
取消:必须选一个
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211223052041-2040598030.png)
Slider组件(滑动条)
Fill Rect:填充的就行,进度的图片
Handle Rect:句柄,索引的图片
Direction:方向
Min/Max Value:最大值,最小值
Whole Numbers:是否整数变化
Value:值,进度值
OnValueChanged:当Value值变化时执行里边所有的方法
----1、拖拽方式,方法必须是公共的,注意固定参数和可变参数。
----2、代码注册事件的方式:方法必须是无返回值,有一个float类型的参数的方法。
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211223105319-1834409825.png)
自制滑动条
同一Canvas下,越靠下的位置越靠前
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211223115751-1114074564.png)
代码操作
slider.normalizedValue:为值的百分比
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UGUI_Slider : MonoBehaviour { private Slider slider; private float value = 0f; // Use this for initialization void Start () { slider = GetComponent<Slider>(); //slider.value为实际的值 Debug.Log("Value: " + slider.value); //slider.normalizedValue为值的百分比 Debug.Log("Value: " + slider.normalizedValue); slider.value = 0f; slider.onValueChanged.AddListener(AddValueChanged); } // Update is called once per frame void Update () { value += Time.deltaTime; slider.value = value; } public void OnValueChanged(float value) { Debug.Log("手动添加的value:" + value); } private void AddValueChanged(float value) { Debug.Log("代码添加的value:" + value); } }
精灵图片批量添加动画:1、全选拖入,2、修改帧数
综合练习-音乐开关
图片挤压问题,图片格式改成水平填充
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211223158518-2035362444.png)
滑动值改为整数
代码操作
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UGUI_SliderMusic : MonoBehaviour { private Slider slider; private AudioSource source; private void Awake() { source = gameObject.AddComponent<AudioSource>(); AudioClip clip = Resources.Load<AudioClip>("OnOff/SingleDog"); source.clip = clip; source.Play(); slider = GetComponent<Slider>(); slider.onValueChanged.AddListener(OnValueChanged); } // Use this for initialization void Start () { slider.value = 0; } // Update is called once per frame void Update () { slider.value = 0; } private void OnValueChanged(float value) { if (value > 0.5f)//打开音乐 { source.volume = 1; } else//关闭音乐 { source.volume = 0; } } }
ScrollBar组件(滚动条)
Value:类型float,范围0~1
Size:句柄的宽度,范围0~1
Number Of Steps:有几个滑动位置,0和1表示无限制,最大值为11,11个位置10段
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211223237426-1861161249.png)
自制滚动条
OnValueChanged:可变参数
OnValueChanged(float):固定参数
把锚点和图片的中心点,设置在左边框,则ScrollBar从0~1,就是图片从0~-1720(1720为图片宽度减画布宽度,负号因为和锚点方向相反)
代码操作
GameObeject.find,类名.方法名,静态
transform.find,对象名.方法名
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UGUI_ScrollBar : MonoBehaviour { private Scrollbar bar; // Use this for initialization void Start () { bar = GetComponent<Scrollbar>(); bar.value = 0.5f;//改变Scrollbar的值 bar.size = 0.4f;//改变句柄大小 bar.onValueChanged.AddListener(OnValueChanged); } // Update is called once per frame void Update () { } public void OnValueChanged(float value) { Debug.Log("值变了:" + value); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UGUI_ScrollBar_Image : MonoBehaviour { private Scrollbar bar;//滚动条 private RectTransform imageX;//图片 private float canvasX = 1920f;//画布 private float offset;//偏移量 private void Awake() { // //GameObeject.Find(); //从子物体里寻找物体,参数是路径,并且支持层级结构 bar = transform.Find("Canvas/Scrollbar").GetComponent<Scrollbar>(); //通过方法找到物体的transform直接转换成Rect Transform imageX = transform.Find("Canvas/Image") as RectTransform; bar.onValueChanged.AddListener(OnValueChanged); } // Use this for initialization void Start () { // - (图片的宽度 - 画布的宽度) offset = canvasX - imageX.sizeDelta.x; //当图片宽度小于画布宽度时,滚动条没有意义,不需要显示 //offset 大于 0 的时候证明图片的宽度小于画布的宽度 if (offset >= 0) { bar.gameObject.SetActive(false); } else { bar.gameObject.SetActive(true); } bar.value = 0; } // Update is called once per frame void Update () { } //当Scroll bar的值改变时,执行的方法 private void OnValueChanged(float value) { //根据value的值去改变图片的位置 float posX = value * offset; imageX.anchoredPosition = new Vector2(posX, imageX.anchoredPosition.y); } }
补充内容-Rect Transform
当锚点分开时,怎么使用anchoredPosition移动图片到中心点的位置
设置位置:
参考锚点的计算公式
anchoredPosition是锚点指向中心点的向量
设置大小:
锚框的计算公式
sizeDelta的值和宽高无关
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211223435299-314868955.png)
代码逻辑
锚线的设置
水平锚线:y相等,x不等
垂直锚线:x相等,y不等
算出参考锚点,偏移参考锚点
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectTransformTest : MonoBehaviour { public RectTransform leftImg; // 设置的是锚点 public RectTransform rightImg; // 设置的是锚框 public RectTransform upImg; // 设置的是水平锚线 public RectTransform downImg; // 设置的是垂直锚线 void Start() { // 设置图片的尺寸为 400,300 // 设置图片的位置为 父物体的中心位置 // ========================== leftImg 设置的是锚点 if (leftImg.anchorMin.x == leftImg.anchorMax.x && leftImg.anchorMin.y == leftImg.anchorMax.y) { // 设置位置 leftImg.anchoredPosition = Vector2.zero; // 设置图片尺寸 leftImg.sizeDelta = new Vector2(400, 300); } // ========================== rightImg 设置的是锚框 if (rightImg.anchorMin.x != rightImg.anchorMax.x && rightImg.anchorMin.y != rightImg.anchorMax.y) { // 设置位置 float anchorReferensePointX = (1 - rightImg.pivot.x) * rightImg.anchorMin.x + rightImg.pivot.x * rightImg.anchorMax.x; float anchorReferensePointY = (1 - rightImg.pivot.y) * rightImg.anchorMin.y + rightImg.pivot.y * rightImg.anchorMax.y; rightImg.anchoredPosition = rightImg.pivot - new Vector2(anchorReferensePointX, anchorReferensePointY); // 设置图片尺寸 //rightImg.offsetMin = new Vector2(100, 100); //rightImg.offsetMax = new Vector2(-100, -100); rightImg.sizeDelta = new Vector2(-200, -200); //Debug.Log("RightImg sizeDelta : " + rightImg.sizeDelta); // sizeDelta = offsetMax - offsetMin; 结果: (-200, -200) } // ========================== upImg 设置的是水平锚线 (上方) if(upImg.anchorMin.y == upImg.anchorMax.y && upImg.anchorMin.x != upImg.anchorMax.x) { // 设置位置 float anchorReferensePointX = (1 - upImg.pivot.x) * upImg.anchorMin.x + upImg.pivot.x * upImg.anchorMax.x; float anchorReferensePointY = (1 - upImg.pivot.y) * upImg.anchorMin.y + upImg.pivot.y * upImg.anchorMax.y; Vector2 anchorPos = upImg.pivot - new Vector2(anchorReferensePointX, anchorReferensePointY); RectTransform parentTrans = upImg.parent as RectTransform; anchorPos.y -= parentTrans.rect.height / 2; upImg.anchoredPosition = anchorPos; // 设置图片尺寸 upImg.offsetMin = new Vector2(100, -400); upImg.offsetMax = new Vector2(-100, -100); //upImg.sizeDelta = new Vector2(-200, 300); } // ========================== downImg 设置的是垂直锚线 (左方) if (downImg.anchorMin.x == downImg.anchorMax.x && downImg.anchorMin.y != downImg.anchorMax.y) { // 设置位置 float anchorReferensePointX = (1 - downImg.pivot.x) * downImg.anchorMin.x + downImg.pivot.x * downImg.anchorMax.x; float anchorReferensePointY = (1 - downImg.pivot.y) * downImg.anchorMin.y + downImg.pivot.y * downImg.anchorMax.y; Vector2 anchorPos = downImg.pivot - new Vector2(anchorReferensePointX, anchorReferensePointY); RectTransform parentTrans = downImg.parent as RectTransform; anchorPos.x += parentTrans.rect.width / 2; downImg.anchoredPosition = anchorPos; // 设置图片尺寸 downImg.offsetMin = new Vector2(100, 100); downImg.offsetMax = new Vector2(500, -100); //downImg.sizeDelta = new Vector2(400, -200); } } void Update() { } }
补充内容-Unity的委托和事件
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; // Unity中使用的委托和事件的命名空间 // C#中使用的委托 // using System; // Action、Action<T>、Action<T, A> .....Action<A, B, C, .....> 没有返回值的 // Func<TResult>、Func<T, TResult>、Func<A, B, .... TResult> 有返回值的 // Predicate<T> 有一个参数,返回值是bool类型 // Comparison<T>(T x, T y) 返回值是int型 public class UnityEventTest : MonoBehaviour { public UnityAction myAction; public UnityEvent myEvent1; // 可以在检视面板中显示 用法同UI public MyEvent2 myEvent2; void Start() { #region Unity中提供的委托 // 没有返回值 没有参数 相当于C#中的 Action UnityAction del1 = delegate () { Debug.Log("delegate"); }; del1 += () => { Debug.Log("Lambda"); }; del1 += Fun1; del1(); UnityAction<int> del2 = delegate (int num) { Debug.Log(num); }; // 有参的匿名委托,Unity委托中参数的个数最多4个 UnityAction<int, int, int, int> del3 = (a, b, c, d) => { Debug.Log(a + b + c + d); }; #endregion #region Unity中的事件 UnityEvent myEvent = new UnityEvent(); // 注册方法 myEvent.AddListener( () => { Debug.Log("这是Unity中的事件"); } ); myEvent.AddListener(Fun1); // 取消注册 myEvent.RemoveListener(Fun1); myEvent.RemoveAllListeners();//无返回值无参数的事件,匿名委托只能用RemoveAllListeners(); // 调用 myEvent.Invoke(); // Unity中有参数的事件 需要自己写一个类去继承 UnityEvent<T> 参数个数:最多4个 // 通过自己的类去创建对象 MyEvent2 myEvent2 = new MyEvent2(); // 注册和取消注册同上 // 调用 myEvent2.Invoke(10); #endregion } void Update() { } public void Fun1() { } } public class MyEvent2 : UnityEvent<int> { } public class MyEvent3 : UnityEvent<int, float, bool, string> { }