
七麦研究院 特邀作者 - Jeff
Jeff
Jeff
5 月 7 日,苹果在开发者后台发布通知,2018 年 7 月起,所有 iOS 应用必须适配 iOS11 系统,并且必须支持 iPhone X 的超级 Retina 显示。
距离 7 月还有一周时间,七麦研究院再次提醒还没有完成适配的开发者需要尽快更新。
另外,今天给大家分享一篇《高效的 iPhone X 适配技术方案》,作者通过改锚点的方式,分别实现在 NGUI 和 UGUI 上 iPhone X 适配技术方案,并结合自身项目经验,阐述了主要的实现细节,希望对广大的游戏开发者有借鉴意义。
适配来源: 按照苹果官方人机界面指南 :
https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/
在 iPhone X 异形屏幕上,苹果提出了 Safe Area 安全区的概念,这个安全区域的意思是,UI 在 Safe Area 能够保证显示不会被裁切掉。
按照苹果的设计规范,要求我们把 UI 控件放在 Safe Area 内,而且不能留黑边。在 Unity 中就需要解决,怎么以更少的工作量把所有界面的控件停靠在 Safe Area 内,黑边的部分用场景或者背景图填充。
当我们横持 iPhoneX 的时候:
iPhone X 整体像素为 2436 x 1125 像素;
整体 SafeArea 区域为 2172 x 1062 像素;
左右插槽(齐刘海和圆角,再加一个边距)各 132 像素;
底部边距(由于 iPhoneX 没有 Home 键,会有一个虚拟的主屏幕的指示条)主屏幕的指示条占用 63 像素高度,顶部没有边界是 0 像素。
一、技术方案
1. 改相机 ViewPort
直接把 UI 相机的视口改为 Rect(132/2436, 0, 2172/2436, 1062/1125),然后把背景图设为另外一个相机。这样做的好处是,完全不用改原来的 Layout。坏处是,多个 UI 的情况下,背景图和主 UI 之间的深度关系要重新设置。
2. 缩放
把主 UI 的 Scale 设为 0.9,背景图的 Scale 设为 1.1,这样就能不留黑边。这个方法的好处是简单,坏处是会引起一些 Tween 已及 Active/InActive 切换之间的问题。
3. 改锚点
分 2 种情况,NGUI 和 UGUI 都有点不同。正好我都有 2 个项目的完整适配经验,所以才写了这个分享。
二、实现细节
首先我们拿到 iPhone X 安全区域,Unity 得开发插件 OC 代码来获取。SafeArea.mm 拷贝到项目的 Plugins/iOS 目录中。
(向下滑动可看更多)
设计通用的适配 component,哪些面板要适配,就直接添加这个脚本:
(向下滑动可看更多)
(向下滑动可看更多)
比如这样,给 Panel 加了 Safe Area Panel 这个组件,勾选 Simulate_X 模拟 iPhone X 运行。
运行时图(红色区域是UI主面板正常是全屏的,这里根据 Safe Area,自动适配后调整锚点展示的左右边距下边距,最底层蓝色区域是场景或者 UI 背景图区域)。
添加一个 812x375 就可以模拟 iPhoneX 的效果
如果是旧项目是使用 NGUI 来开发的,原理一样,也得用到以上 Safa Area.mm 来获取安全区域,不同处在于修改 NGUI 的源码,而 NGUI 版本有好多。不要忘记把 SafeArea.mm 拷贝到项目的 Plugins/iOS 目录中。我提供思路和核心代码,需要你结合自己使用的 NGUI 来修改。
NGUI 中 UI Sprite、UILabel、UIPanel 等等都是继承抽象类 UIRect。
UIRect UI 矩形包含 4 个锚点(每边一个),我们就是要控制锚点在安全区域显示。
在 NGUITools.CS 中增加代码:
(向下滑动可看更多)
锚点的适配最终都会调用 NGUITools.GetSides 这个方法,这个方法实际上是 NGUI为Camera 写的扩展方法。
找到 NGUITools.cs 的 static public Vector3[] GetSides(this Camera cam,float depth,Transform relativeTo)。我们追加一个 bool showInSafeArea, 默认 false。
(向下滑动可看更多)
还需要改动 UIRect 和 UIRectEditor 的相关方法:
1. 在 UIRect.cs 中添加
[HideInInspector][SerializeField]public bool mShowInSafeArea = false;
2. 修改 GetSides 的调用
/// <summary>
/// Convenience function that returns the sides the anchored point is anchored to.
/// </summary>
public Vector3[] GetSides (Transform relativeTo)
{
if (target != null)
{
if (rect != null) return rect.GetSides(relativeTo);
if (target.camera != null) return target.camera.GetSides(relativeTo, rect.mShowInSafeArea);//这里增加了是否在安全区域的参数
}
return null;
}
(向下滑动可看更多)
3. UIRectEditor.CS 扩展下
(向下滑动可看更多)
4. GetSides 的调用加上 mShowInSafeArea。
补充:实际项目中,部分节点是UIAnchor来设置,所以这个脚本也要适配找到UIAnchor的UpDate。
if (pc.clipping == UIDrawCall.Clipping.None)
{
// Panel has no clipping -- just use the screen's dimensions
float ratio = (mRoot != null) ? (float)mRoot.activeHeight / Screen.height * 0.5f : 0.5f;
mRect.xMin = -Screen.width * ratio;
mRect.yMin = -Screen.height * ratio;
mRect.xMax = -mRect.xMin;
mRect.yMax = -mRect.yMin;
}
5.这里都是直接使用 Screen.width 和 Height,要改成安全区域 Safe Area.width 和 Safe Area.height。
if (pc.clipping == UIDrawCall.Clipping.None)
{
// Panel has no clipping -- just use the screen's dimensions
float ratio = (mRoot != null) ? (float)mRoot.activeHeight / NGUITools.SafeArea.height * 0.5f : 0.5f;
mRect.xMin = -NGUITools.SafeArea.width * ratio * NGUITools.Simulate_iPhoneXScale;
mRect.yMin = -NGUITools.SafeArea.height * ratio;
mRect.xMax = -mRect.xMin;
mRect.yMax = -mRect.yMin;
}
这样 NGUI 也就可以了。
添加一个 812x375 就只可以直接预览:
以上,因为我的两个上线项目恰好分别适配了 UGUI 和 NGUI,所以根据经验,总结了高效的 Unity3D 适配 iPhone X 技术方案,希望大家能有收获。
《干货集锦》第九期就到这里啦~ 欢迎留言说出最近困扰哦~
- end -
本文由七麦研究院特邀作者【 Jeff 】原创,首发于公众号侑虎科技(ID:uwatech)转载需联系 Jeff 获取授权,七麦研究院有权向非授权转载追究责任。
查看往期精彩文章
约谈、下架、停更、关停……整改消息扑面而来,这些坑不能再跳了!
世界杯竞猜持续升温,你的手机屏幕是否已被“赌球” App 占据?


