赞
踩
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;//是否开始cd private float curCdSec;//当前cd时间进度 // Start is called before the first frame update void Start() { isCooldown = false; curCdSec = 0; } // Update is called once per frame void 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 update void 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 frame void 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 update private void OnEnable() { //在Dragimage的位置创建一个相同的图片,起名为icon GameObject 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组件并赋给变量img img.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_icon m_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组件并赋给变量img img.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 update public void OnDrop(PointerEventData eventData) { this.GetComponent<Image>().sprite = eventData.pointerDrag.GetComponent<Image>().sprite; this.GetComponent<Image>().color = eventData.pointerDrag.GetComponent<Image>().color; } }
(未完待续…)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。