unity ugui 与不同屏幕进行像素适配的问题
来源:互联网 发布:大数据前沿技术与应用 编辑:程序博客网 时间:2024/05/21 04:25
unity的ugui其实严格意义上是不需要我们去进行适配的,它确实帮助我们做了很多很多的工作,我们只要简单的拖拉几下就可以搞定适配的问题(这点在比ngui强了不是一点半点,不愧是unity提供的从底层开始的解决方案)。
但是总是会有那么些特殊的蛋痛需求,还是需要让我们来考虑适配的问题的。
假设我们要做一个类似iphone的AssistiveTouch
悬浮窗时,这个东西有个特点,那就是它不能出屏,出屏之后需要再弹回到屏幕范围内,这个时候,你想不处理适配的问题都不行了。。。
如图那个黑边白球:
那么ugui里我们要怎么办呢?
首先我们要考虑2点。
1,我们的ui资源比例是什么?
2,我们要适配的屏幕比例又是什么?
假设我们资源的图是按照960x640(3:2)来绘制的,而我们的屏幕是1920x1080(16:9),我们是不能单纯的用1920x1080屏幕的尺寸来限定运动范围,因为这2种屏幕的比例是不同的,我们在960x640屏幕上 (50,50) 像素的点,跟在1920x1080屏幕上的位置那是2个地方,所以你会蛋痛的发现,你的位置永远的都对不上。。。
但是我们来看看我们知道哪些有用的信息,我们知道2个屏幕的尺寸呀,所以我们可以根据它们之间的差距来转换呀!
思路很简单,就是如果我用 960 / 1920 = ? 宽的比乘以一个1920元素的尺寸或位置,那不就是等于960的尺寸和位置了。
道理很简单,但是谁除谁,也不是能随随便便那么来的,因为我们的屏幕适配是由ugui来处理的,所以我们算比的方式,一定要跟ugui的适配是相一致的,才能保证最后的结果是没有偏差的。
如果ugui是以高为适配的,你算得是宽的比,你觉得这2屏幕能对的上吗?
以上这些重要的信息都是来自于 Canvas Scaler 这个组件上,它负责了ugui中对各种尺寸屏幕的像素适配(这里我用的是Scale with Screen Size模式,自建单独的ui摄像机)
说了这么多,这里就上个我写的浮动球的代码:
using UnityEngine;using System.Collections;using UnityEngine.EventSystems;using UnityEngine.UI;using UnityEngine.Events;public class UIBtnCloud : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler{ /// <summary> /// 按下后超过这个时间则认定为"长按" /// </summary> public float interval = 0.1f; /// <summary> /// 是否只调用一次 /// </summary> public bool invokeOnce = false; // 按下标志 private bool isPointerDown = false; // 记录时间 private float recordTime; //是否已经调用过 private bool hadInvoke = false; // 点击事件 public UnityEvent onClick = new UnityEvent(); // 按住事件 public UnityEvent onPress = new UnityEvent(); private RectTransform m_rectTransform; private float m_scale; private float m_minX, m_minY, m_maxX, m_maxY; void Start() { m_rectTransform = gameObject.GetComponent<RectTransform>(); // 计算分辨率的比例 CanvasScaler cs = XXX.GetInstance().CanvasScaler; m_scale = cs.matchWidthOrHeight == 1 ? (float)Screen.height / cs.referenceResolution.y : (float)Screen.width / cs.referenceResolution.x; // 范围 m_minX = m_rectTransform.sizeDelta.x / 2 * m_scale; m_minY = m_rectTransform.sizeDelta.y / 2 * m_scale; m_maxX = Screen.width - m_minX; m_maxY = Screen.height - m_minY; } void Update() { // 一次机会已用完 if (invokeOnce && hadInvoke) return; // 按下 if (isPointerDown) { // 算按住 if ((Time.time - recordTime) > interval) { hadInvoke = true; onPress.Invoke(); } } } #region 处理点击 // 按下 void IPointerDownHandler.OnPointerDown(PointerEventData eventData) { isPointerDown = true; recordTime = Time.time; } // 抬起 void IPointerUpHandler.OnPointerUp(PointerEventData eventData) { isPointerDown = false; hadInvoke = false; // 算点击 if ((Time.time - recordTime) < interval) { onClick.Invoke(); } } // 离开 void IPointerExitHandler.OnPointerExit(PointerEventData eventData) { isPointerDown = false; hadInvoke = false; } #endregion 处理点击 ------------------------------------- #region 处理拖拽 private void SetRectTransformPos(Vector2 position, Camera camera) { Vector3 globalMousePos; if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_rectTransform, position, camera, out globalMousePos)) { m_rectTransform.position = globalMousePos; } } // 开始拖拽 void IBeginDragHandler.OnBeginDrag(PointerEventData eventData) { } // 拖拽中 void IDragHandler.OnDrag(PointerEventData eventData) { //transform.position = eventData.position; this.SetRectTransformPos(eventData.position, eventData.pressEventCamera); } // 结束拖拽 void IEndDragHandler.OnEndDrag(PointerEventData eventData) { // 位置 float x = m_rectTransform.position.x; float y = m_rectTransform.position.y; // 超出范围处理 if (x < m_minX) { x = m_minX; } else if (x > m_maxX) { x = m_maxX; } if (y < m_minY) { y = m_minY; } else if (y > m_maxY) { y = m_maxY; } Vector2 currentPosition = new Vector2(x, y); // 设置坐标 this.SetRectTransformPos(currentPosition, eventData.pressEventCamera); } #endregion 处理拖拽 -------------------------------------}
以上脚本挂在普通窗的button上就好了,很简单的。
外加没有做差值效果,只是生把出屏的球给拉回来,需要的同学可以自己给加上。
CanvasScaler cs = XXX.GetInstance().CanvasScaler;
获取 CanvasScaler 组件的方法,根据自己的项目去修改就好了,你的位置肯定不会跟我的一样~
这里我的资源都是按着960x640的标准来制作的(其实并不是,只是我瞎j8设的。。。),你要根据你自己的资源去调整参数,剩下的,就全是程序的事了。
PS:
顺便这里安利一下ugui,确实是比ngui好用,不过缺点是好多东西是需要自己手写的,像ngui里,对于这种出屏回弹的功能,其实就有现成的组件的,调参数就好。
这无形中其实增加了使用的门槛,不利于新手入门,尤其是不了解差值动画这个概念的同学,会限制他们制作各种各样精美动画的能力。(不是开玩笑,真有好多人搞不清楚差值动画这个概念。。。)
不过还是那句话,提高自己最重要,你也不能总靠别人不是?
- unity ugui 与不同屏幕进行像素适配的问题
- Unity 点击屏幕与UGUI的区分
- UNITY之UGUI屏幕适配
- Unity-屏幕适配UGUI与3D/2D场景
- DisplayUtil 把dp或sp转成px(像素)的工具类。适配不同屏幕
- Unity UGUI与NGUI的比较,NGUI完胜UGUI
- Unity ugui的鼠标穿透问题
- 【Unity】UGUI的Text各种小问题
- 【Unity】【Canvas】UGUI层次显示的问题
- Unity中NGUI与UGUI的区别
- android不同屏幕大小手机的适配问题
- 适配不同的屏幕
- unity 使用Ngui 屏幕适配问题
- unity 使用Ngui 屏幕适配问题
- Unity使用UGUI进行VR游戏的界面开发
- React Native 之 获取不同屏幕的像素密度
- 屏幕长度与像素长度的转换
- Unity UGUI的适配方法总结
- android多图片缓存
- Android 帧动画(FrameAnimation)的使用
- 监控ip丢包率
- HDU 5835 Danganronpa (贪心)
- 计算文件大小
- unity ugui 与不同屏幕进行像素适配的问题
- 关于使用eventbus引发的NoClassDefFoundError问题解决方案
- Android GridView 分组显示(仿京东商品分类)
- Antlr
- 综合开发_版本控制_git命令大全
- OpenWrt设置mac地址过滤和使用Iptables防火墙禁止mac地址上网
- 检测用户名非法字符
- 2016.8.14中山纪中信息学比赛题解
- C++关键字之explicit