Unity入门之U2D——UGUI
UI的成像平面(首先需要设置Canvas的Render Mode为Screen Space-Camera):可以在Canvas->Plane Distance中设置它距离摄像机多远
摄像机的近裁剪平面和远裁剪平面:3D空间的物体,超出此范围会被“裁剪”(不渲染),为了提高渲染效率
Scaler组件:
当我们新建四个按钮:

如果左右拉伸屏幕,会看到按钮的相对位置会随屏幕分辨率变化而变化,甚至超出屏幕范围

选择Canvas Scaler的UI Scale Mode的Scale With Screen Size以及Screen Match Mode的Expand,就可实现随屏幕大小缩放

注:UI Scale Mode各选项的意义——
· Constant:UI不随屏幕大小而改变
· Scale With Screen Size:UI随屏幕大小缩放
· Expand:匹配宽度
· Shrinke:匹配高度
RecTransform组件:
用于二维物体缩放,继承自Transform类
Pivot:选中的单个物体的正中心
Center:多个物体围成的包围盒的中心
Anchor:锚点,它的改变会使得物体的Position也发生变化,即以该锚点为原点,向右向下为正坐标值
Image控件:
Image Type:Filed模式:可用于制作各类进度条。ClockWise勾选表示顺时针填充,不勾选是逆时针。
Sliced模式:用于制作九宫格——一种可以指定外部区域不缩放,内部区域缩放的图片类型
Tiled模式:重叠模式
Preserve Aspect:使图片缩放不超过其Rect(图片不失真)
练习:编程控制技能CD(技能冷却时间)的刷新,比如技能CD为2秒,则从 Unity脚本启动后直接进入CD状态,2秒后取消CD
新建Image,在Source Image里将技能图拖拽进去,在其下面新建一个子Image,并在Rect Transform处设置锚点,选择stretch右下角加Alt键

拖拽一个白底图给子Image,并调节其透明度

选择Fill Method为Radical 360, 不勾选Clockwise,那么Fill Amount从1到0的过程就是顺时针冷却完毕技能的过程




给父Image新建一个SkillCD脚本,进行编程
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class SkillCD : MonoBehaviour
{public Image cdImage;public float totalCdSec;//cd总时间public bool isCooldown;//是否开始cdprivate float curCdSec;//当前cd时间进度// Start is called before the first frame updatevoid Start(){isCooldown = false;curCdSec = 0;}// Update is called once per framevoid Update(){if (isCooldown){curCdSec += Time.deltaTime;cdImage.fillAmount = Mathf.Max(1 - curCdSec / totalCdSec,0);if (curCdSec > totalCdSec){isCooldown = false;curCdSec = 0;}}}
}
RawImage控件:
与Image控件的区别:
Image用于显示Sprite类型的图片
RawImage显示Texture类型的贴图、网络下载的图片
新建一个RawImage,添加一个脚本,实现网络下载图片并显示功能
用到WWW和协程下载图片以及显示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class DownloadImage : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){StartCoroutine(Download());}IEnumerator Download(){WWW www = new WWW("https://gss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/zhidao/wh%3D600%2C800/sign=ecfa515c8e0a19d8cb568c0303caaeb3/64380cd7912397dd810190e95782b2b7d1a287e6.jpg");yield return www;//等待协程下载图片完毕,程序才会继续往下执行GetComponent<RawImage>().texture = www.texture;}// Update is called once per framevoid Update(){}
}
注:若显示的图片是一个红色问号,最大的原因是图片链接不正确,在网上选择图片后,不要直接复制地址,要先右键->检查->Network->F5刷新,选择Img

选中自己想要的图片对应的链接才是可在代码里下载的链接

可交互的组合控件(Button、Slider、InputField)
可交互控件——继承自Selectable类
不可交互控件——继承自MaskableGraphic
Button控件:
聚合了Image和Button组件
Slider控件:
聚合了Slider组件。由多个部分构成:
Background:背景部分
Fill:进度条填充部分
Handle:句柄部分
Transition TargetGraphic:用于指定交互效果控制哪个对象的图形效果
Navigation :指定可交互控件之间的前后顺序(上下键切换)
InputField控件:
可输入文字
UI层级
子节点覆盖父节点
下节点覆盖上节点
调整层级,RectTransform:
SetAsFirstSibling
SetAsLastSibling
SetSiblingIndex
GetsiblingIndex
如:
子节点Button1覆盖Button2

同层级的Button1和Button2,在下面的Button2覆盖Button1

事件监听
给Button1新建一个Button1脚本,并添加OnClick方法

在Unity的Button控件中,拖拽Button1以及选择Button1的OnClick()方法到On Click()窗口下

运行,点击Button1按钮可以看到控制台打印出Button1

新建一个Slider控件,设置其Max Value为10

给Slider控件添加一个Slider脚本,添加事件代码

同理拖拽


聊天框制作
Image组件做背景,然后添加∶
· Text显示文本,调到能显示全部文本
· ScrollRect用于关联文本滚动(水平、垂直)
· Mask用于文本遮盖
· Scrollbar :关联给ScrollRect.VerticalScrollbar
拖拽事件︰
using UnityEngine.EventSystems
Implements IBeginDragHandler, IEndDragHandler
关联脚本到Image组件
步骤:
新建一个Panel,将其缩小并移动到左下角

在其子层级新建一个GameObject,并重命名为InputArea

压缩其大小并移到底部

在InputArea下新建一个InputField并移动到最左边,新建一个Button改文本为发送并移到最右边

在Plane下新建一个ScrollView并调节到合适位置

勾掉Horizontal表示不能左右滚动,只能上下滚动

在InputField下新建一个Text

调节到合适位置

为了实现输入文字点发送按钮后能够发送,给Button添加脚本编写代码

保存以后在unity里拖拽到对应位置

onClick()也拖拽和选择


运行代码,发现输入文字并点发送后,滚动条自己滚到最底端,而ScrollView的Content上移到顶端,导致发送的文字不在显示范围里

要往上拖滚动条才能看到

解决方法是给Content组件添加Vertical layout Group(让content的高度随文本高度适配)

同时再增加一个ContentSizeFitter组件并选择Vertical Fit的Preferred Size

运行后,可以看到Content的大小根据文字而适配

但是发现,每次发送完后定位的是发送前的最后一行

输入111111111,发送后

并没有跳到最底层的1111显示,而是依然定位在发送前的位置,直到往下拖动滚动条才能看到

因此定位部分需要使用协程来修改:

自动布局
· LayoutElement提供最小、最合适、最大大小信息。
· lmage实现了ILayoutElement接口,但如果用户额外增加了组件LayoutElement,则Image上实现的ILayoutElement接口失效。
· IgnoreLayout:有些组件必须放在LayoutGroup下,但是又不想受其控制,就勾选。
· LayoutGroup:该组件所在对象的Width和Height控制子节点的大小和位置(但自身不受控制)
· Child Force Expand:强制拉伸子节点,使其在水平或垂直方向铺满当前节点
· Control Child Size: 让子节点大小受LayoutElement组件控制
· Paddingn:控制最边缘子节点的边缘离LayoutGroup 的内边距(要与ChildAlignment配合使用)
· LayoutControl:
· Content Size Fitter:控制节点的大小,使其匹配LayoutElement组件的大小(Text、lmage等非组合控件都拥有LayoutElement组件)
· LayoutGroup控件下不能摆放此控件,因为这两个都能控制大小,会冲突但是LayoutGroup控件可以和此控件放在同一对象上,一个控制分组元素的布局,一个控制分组元素集合的总大小
思考:如果给拥有LayoutEement组件的对象再单独添加LayoutEement组件并指定Min Size、Preferred Size会怎样?
GridLayoutGroup
模拟背包:新建一个Panel,调节大小,在其下新建Image并命名为Item,调节大小后复制八份

给Panel新添一个Grid Layout Group

调节各项数值


要给背包添加一个标题,在Panel下新建一个Text,但是发现无法自由移动,因为它默认并入了其他Item的布局

因此对Text新建一个Layout Element并勾选Ignore layout



给UI元素添加事件处理功能
方法一:实现相应的事件接口:参考UnityEngine.EventSystems命名空间
例:之前的SendText代码,可以通过实现IPointerClickHandler接口来触发事件,而不用去界面组件上拖拽

方法二:添加Event Trigger组件,并指定事件处理器
方法三:程序动态添加
可以通过视图->对象浏览器查看接口

实现通过拖拽窗口的标题来移动窗口位置


代码脚本挂载在Drag Zone下
程序思路是:首先通过鼠标点击事件获取当前点击处的位置,通过鼠标拖拽事件获取拖拽后的位置,拖拽后的位置减去拖拽前的位置即为Panel的偏移量,在鼠标点击事件中通过this.transform.parent(即Panel).localPosition可获得拖拽前Panel的位置(以界面的左上角点为锚点),该位置加上偏移量即为拖拽后Panel的位置

注:RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector2 localPoint):
将屏幕空间点变换到矩形变换的局部空间中位于矩形平面上的位置
实现通过拖拽窗口角点来调整大小

实现Mylighting——能通过拖拽滑杆来调节面板颜色
新建Panel,并设其透明度为255

新建三个Slider并重命名为红绿蓝

将其Fill Area的fill的color颜色改为对应的红绿蓝色


给Panel新建脚本

在各个Slider里的On Value Changed中拖拽和选择


渲染纹理
新建一个RawImage并strech

新建一个Render Texture并命名为Render Texture

拖拽到RawImage的Texture里

将模型导入并拖拽到Hierarchy

新建平行光

选择Global并将模型移到场景外

(未完)
拖拽物品到背包,若未拖拽到指定位置则恢复初始位置
思路:

新建一个Image对象并命名为DragImage,拖拽图片

给DragImage添加一个脚本,编写代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class DragImage : MonoBehaviour,IPointerClickHandler
{// Start is called before the first frame updateprivate void OnEnable(){//在Dragimage的位置创建一个相同的图片,起名为iconGameObject icon = new GameObject("icon");//新建icon对象GameObject canvas=GameObject.Find("Canvas");icon.transform.position = this.transform.position;//icon跟随DragImage的位置icon.transform.SetParent(canvas.transform, true);//设置icon为Canvas的子节点,true表示保持icon在上一步中设置好的场景中的位置不变Image img = icon.AddComponent<Image>();//给icon新增Image组件并赋给变量imgimg.sprite = this.GetComponent<Image>().sprite;//icon的图片与DragImage的同步}public void OnPointerClick(PointerEventData eventData){print("你点击了Dragimage");}}
写到这一步的时候,保存并运行测试,发现不论怎么点击DragImage始终不会打印“你点击了DragImage”,因为生成的icon位于DragImage的同层级下方,点击的时候默认点击的icon

所以要给icon添加一个Canvas Group组件并还要勾掉Blocks Raycasts,像下面这样

在代码中加入下面这行
icon.AddComponent<CanvasGroup>().blocksRaycasts = false;//防止icon阻挡鼠标点击其背后的DragImage
完整代码为
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class DragImage : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler
{private Vector3 m_offset;//以图片中心为终点,以鼠标位置为起点的向量private GameObject m_icon;private RectTransform m_canvas;private void OnEnable(){m_canvas = GameObject.Find("Canvas").transform as RectTransform;//在Dragimage的位置创建一个相同的图片,起名为m_iconm_icon = new GameObject("icon");//新建m_icon对象m_icon.transform.position = this.transform.position;//m_icon跟随DragImage的位置m_icon.transform.SetParent(m_canvas.transform, true);//设置m_icon为Canvas的子节点,true表示保持m_icon在上一步中设置好的场景中的位置不变Image img = m_icon.AddComponent<Image>();//给m_icon新增Image组件并赋给变量imgimg.sprite = this.GetComponent<Image>().sprite;//m_icon的图片与DragImage的同步m_icon.AddComponent<CanvasGroup>().blocksRaycasts = false;//防止m_icon阻挡鼠标点击其背后的DragImage}public void OnBeginDrag(PointerEventData eventData){Vector3 imgPos;RectTransformUtility.ScreenPointToWorldPointInRectangle(m_canvas, this.transform.position, eventData.pressEventCamera, out imgPos);Vector3 cursorPos;RectTransformUtility.ScreenPointToWorldPointInRectangle(m_canvas, eventData.position, eventData.pressEventCamera, out cursorPos);m_offset = imgPos - cursorPos;}public void OnDrag(PointerEventData eventData){Vector3 cursorPos;RectTransformUtility.ScreenPointToWorldPointInRectangle(m_canvas, eventData.position, eventData.pressEventCamera, out cursorPos);Vector3 imgPos;imgPos = cursorPos + m_offset;m_icon.transform.position = imgPos;}public void OnEndDrag(PointerEventData eventData){m_icon.transform.position = this.transform.position;//this表示DragImage,一直没有动}
}
下面来实现拖拽到指定位置放下:
新建一个Image为DropSlot,将表示篮筐的透明图片拖拽到里面,给DropSlot添加代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class MyDropImage : MonoBehaviour, IDropHandler
{// Start is called before the first frame updatepublic void OnDrop(PointerEventData eventData){this.GetComponent<Image>().sprite = eventData.pointerDrag.GetComponent<Image>().sprite;this.GetComponent<Image>().color = eventData.pointerDrag.GetComponent<Image>().color;}
}
(未完待续…)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
