Ngui分辨率适配
必备知识点
1.分辨率适配必然是Orthographic Camera
2.Camera下对应的“Size”(图1)属性大小的理解:当前摄像机高度 = Size * 2 * UnityUnit(Unity编辑器单位长)
3.NGUI象素比例与UnityUnit之间的比值关系为 1:1(这里需要注意所有父节点的缩放都要重置为1)
4.Game视图下分辨率(图2)的意义:
意义1:
Game视图渲染时的光栅格个数(光栅格数越少,画面越模糊)
意义2:
由于上面Size已经决定了摄像机高度,那么还需要根据这个“长宽比值”来决定摄像机的宽度
Eg:
比如Size属性为384,分辨率设置为 2000 X 1000 那么最终 摄像机照射范围就是 “长 -----> 1536UntiyUnit, 宽 -----> 768UnityUnit”
图1
图2(当分辨率比值不变,修改其数值大小时,照射范围一致,只是影响清晰度)
分辨率适配的原理:
1.我们最开始摆放UI的时候都需要有一个最初的分辨率和Camera Size(之后称之为 预设分辨率 & 预设Size)
2.我们假设预设分辨率比为3:2(1152 : 768),而目标分辨率比是未知的,存在以下2种情况 “长宽比小于 预设长宽比”,“长宽比大于 预设长宽比”
- 情况1
【】 由于屏幕高度没有发生变化,所以Camera Size不需要改变
【】 其他UI元素根据其anchor值决定是否 “移动” 或 ”缩放”
- 情况2
【】 由于屏幕高度发生变化,所以要重新计算Camera Size
【】 其他UI元素根据其anchor值决定是否 “移动” 或 “缩放”
以下是分辨率控制器代码(Manager部分)
/*************************************** Editor: Tason Version: v1.0 Last Edit Date: 2018-04-13 Tel: 328791554@qq.com Function Doc: 分辨率适配 主要理解一下裁剪方式 ***************************************/ using UnityEngine; using System.Collections; public class ResolutionController : MonoBehaviour { //设置(时)分辨率 public int m_originalWidth = 1152; public int m_originalHeigh = 768; //设置(时)摄像机Size public static float s_cameraSize; [HideInInspector] public float m_cameraSize; //管理的摄像机们 public Camera[] m_cameras; //偏移值 public static float s_scaleRatio = 1; public static float s_topCenter = 1; public static float s_bottomCenter = 1; public static float s_leftCenter = 1; public static float s_rightCenter = 1; //横屏和竖屏判断 主要涉及裁剪方式 public static bool s_isHorizontalScreen = true; //原始长宽比 public static float s_originalHVRatio; // ----- Awake ----- private void Awake() { //初始化 m_cameraSize = m_originalHeigh / 2; s_cameraSize = m_cameraSize; //设置长宽比 s_originalHVRatio = (float)m_originalWidth / m_originalHeigh; //当前长宽比 float currentHVRatio = (float)Screen.width / Screen.height; float t1 = Screen.height * m_originalWidth; float t2 = Screen.width * m_originalHeigh; float temp; /* 情况2 * ------------------ * | | * |----------------| * | | * |----------------| * | | * ------------------ */ if (currentHVRatio > s_originalHVRatio) { s_isHorizontalScreen = true; //得到纵向高的比值 s_scaleRatio = s_originalHVRatio / currentHVRatio; //得到缩放后的Size大小 temp = m_cameraSize * s_scaleRatio; s_topCenter = temp - m_cameraSize; s_bottomCenter = -s_topCenter; s_leftCenter = 0; s_rightCenter = 0; } /* 情况1 * ------------------ * | | | | * | | | | * | | | | * | | | | * | | | | * ------------------ */ else { s_isHorizontalScreen = false; //这个可划分为 “目标长 / 预设长 = 缩放比例”该比例<1 s_scaleRatio = currentHVRatio / s_originalHVRatio; temp = m_cameraSize; s_topCenter = 0; s_bottomCenter = 0; s_leftCenter = (1 - s_scaleRatio) * m_cameraSize * s_originalHVRatio; s_rightCenter = -s_leftCenter; } //设置摄像机的size foreach (var a in m_cameras) { if (a != null) a.orthographicSize = temp; } } }
代码中需要理解一下的地方就是 “第91行”“s_scaleRatio = currentHVRatio / s_originalHVRatio;”
“当前长 / 当前宽" 除以 “预设长 / 预设宽” 由于 情况1中 当前宽 = 预设宽 所以 上列算式可以划分为 "当前长" 除以 “预设长”
以下是分辨率受控体代码(受控体部分)
/*************************************** Editor: Tason Version: v1.0 Last Edit Date: 2018-XX-XX Tel: 328791554@qq.com Function Doc: 分辨率子对象 配合 ResoulutionController 控制手机适配 ***************************************/ using UnityEngine; using System.Collections; public class ResolutionObject : MonoBehaviour { //情况1 (长宽比减小)是否缩放 public bool m_state1ScaleSwitch = true; //情况2 (长宽比增加)是否缩放 public bool m_state2ScaleSwitch = true; //对齐锚点选择 public bool m_top; public bool m_bottom; public bool m_left; public bool m_right; // ----- Start ----- private void Start() { Vector3 v; if (!ResolutionController.s_isHorizontalScreen && m_state1ScaleSwitch) transform.localScale *= ResolutionController.s_scaleRatio; if (ResolutionController.s_isHorizontalScreen && m_state2ScaleSwitch) transform.localScale *= ResolutionController.s_scaleRatio; if (m_top) { v = transform.position; v.y = ResolutionController.s_cameraSize * (1 - ResolutionController.s_scaleRatio) + transform.position.y * ResolutionController.s_scaleRatio + ResolutionController.s_topCenter; transform.position = v; } if (m_bottom) { v = transform.position; v.y = ResolutionController.s_cameraSize * (ResolutionController.s_scaleRatio - 1) + transform.position.y * ResolutionController.s_scaleRatio + ResolutionController.s_bottomCenter; transform.position = v; } if (m_left) { v = transform.position; v.x = ResolutionController.s_cameraSize * ResolutionController.s_originalHVRatio * (ResolutionController.s_scaleRatio - 1) + transform.position.x * ResolutionController.s_scaleRatio + ResolutionController.s_leftCenter; transform.position = v; } if (m_right) { v = transform.position; v.x = ResolutionController.s_cameraSize * ResolutionController.s_originalHVRatio * (1 - ResolutionController.s_scaleRatio) + transform.position.x * ResolutionController.s_scaleRatio + ResolutionController.s_rightCenter; transform.position = v; } } }
使用方法:
1.挂载Controller 设置对应预设值参数
2.挂载子对象控制器 设置其属性
不同缩放的距离说明(锚点不做说明)
1.情况1、2的缩放要求很多时候不一样 例如下图的妹子在勾选不同情况的缩放时···呈现的状态
如图上的妹子就应该 打开“横向缩放” 关闭"纵向缩放"
Update 1.1
1.以修改了Controller的适配BUG,原来有2个固定常量,现在修改成了变量(上面代码已经修改了但是忘记改版本号了)。
举个例子
使用方式
1.导入NGUI插件,创建背景图,删掉UIRoot对象下的UIRoot组件(即它自己的分辨率适配部分)。
2.将ResolutionController挂载在UIRoot对象下,修改UIRoot的Transform节点缩放为1, 并根据背景图片大小设置 CameraSize 及ResolutionController的分辨率参数。
3.将要修改的摄像机挂载添加到ResolutionController的控制数组中。
4.给需要缩放的物体挂载ResolutionObject 对象并调整参数,一般背景图是挂载对象,也不缩放的
下面我用新版本再举个例子
适配出来以后
----->