【Unity3D杂谈】记手游适配iPhone灵动岛的经历

一、前言

        还记得苹果在14系列发布了灵动岛,着实吸引了一大波眼球。且不论灵动岛美不美观、实用性如何,至少对于客户端程序员来说,又多了一个需要进行屏幕适配的情况。在灵动岛发布完有较长一段时间了,由于其他事情比较忙,一直没得空去关注和优化这方面的问题,正好有空做优化,适配的事情提上了日程,正好记录一下适配的过程。

        就Unity3d的iPhone适配而言,实际上Unity提供了Screen.safeArea这个API可以获取安全区域的数据,而且是Unity经过换算的像素点位,之前使用它来适配普通刘海屏其实是可以的。但是这里存在着一个主要的问题,Unity收录的iPhone设备的信息有限或者计算方式落后了,只能准确识别出Unity版本对应更新年限之前的iPhone设备,读出的尺寸是错误的,导致此处还需要关心灵动岛的适配(即也许更新到Unity2023甚至更新可能就不用关心这个适配问题了)。

二、iPhone异形屏尺寸介绍

        在灵动岛出来之前,iPhone适配其实主要就是刘海屏的适配。

        这里搜集了两篇关于尺寸描述的文章,具体详情大家可以参考:

        iPhone 14 Screen Sizes (useyourloaf.com)icon-default.png?t=N7T8https://useyourloaf.com/blog/iphone-14-screen-sizes/
图解iPhone iOS灵动岛UI设计尺寸规范 (360doc.com)icon-default.png?t=N7T8http://www.360doc.com/content/12/0121/07/8772388_1067786520.shtml      

        看以下的示意图,灵动岛安全区域(SafeArea)的高度与普通刘海屏相比要高出一截。【Unity3D杂谈】记手游适配iPhone灵动岛的经历_第1张图片

       

【Unity3D杂谈】记手游适配iPhone灵动岛的经历_第2张图片

(图片来自上述文章,侵删)

        具体而言,普通刘海屏的高度为47 points,而灵动岛的安全区高度达到59 points。

三、iOS的points的概念

        在上述的示意图中,我们可以看到所有的尺寸标注都是points。

        熟悉iOS原生开发的童鞋肯定都对这个points了如指掌。

        但是这里的问题在于,Unity的API能给我们提供的数据只有Screen.size之类的像素尺寸,此时我们需要做的事情其实就是需要把points转换到像素值。

        简单的说,这里涉及到一个概念就是苹果的屏幕缩放参数(Native Scale factor)的概念,当设备的屏幕缩放参数是2x的时候,则上述的59points = 59 x 2 = 118px,如果是3x则是59 points = 59 x 3 = 177px。

        这里笔者没有查到Unity有提供任何比较靠谱的API能够获取到这个Native Scale factor。有一种说法是使用DPI除以一个系数。此方法经尝试不可行,主要有两个问题:

        a、有少量设备实测有偏差,即计算结果错误。

        b、通过Unity的Screen.dpi字段获取到的DPI数值,在新款iPhone上也是错误的。这个也很好理解,因为比如Unity2020及更早等旧Unity版本,压根就没有关于新iPhone的信息。

        所以暂时只是枚举了iPhone设备的型号。使用SystemInfo.deviceName字段去匹配。

        截止到2023年底为止,需要适配的异形屏列表如下:

NativeScaleFacotrs {
    ["iPhone8,4"]  = 2, -- iPhone SE
    ["iPhone10,3"] = 3, -- iPhone X
    ["iPhone10,6"] = 3, -- iPhone X
    ["iPhone11,2"] = 3, -- iPhone Xs
    ["iPhone11,4"] = 3, -- iPhone Xs Max
    ["iPhone11,6"] = 3, -- iPhone Xs Max
    ["iPhone11,8"] = 2, -- iPhone XR
    ["iPhone12,1"] = 2, -- iPhone 11
    ["iPhone12,3"] = 3, -- iPhone 11 Pro
    ["iPhone12,5"] = 3, -- iPhone 11 Pro Max
    ["iPhone12,8"] = 2, -- iPhone SE 2
    ["iPhone13,1"] = 3, -- iPhone 12 mini
    ["iPhone13,2"] = 3, -- iPhone 12
    ["iPhone13,3"] = 3, -- iPhone 12 Pro
    ["iPhone13,4"] = 3, -- iPhone 12 Pro Max
    ["iPhone14,4"] = 3, -- iPhone 13 mini
    ["iPhone14,5"] = 3, -- iPhone 13
    ["iPhone14,2"] = 3, -- iPhone 13 Pro
    ["iPhone14,3"] = 3, -- iPhone 13 Pro Max
    ["iPhone14,6"] = 2, -- iPhone SE 3
    ["iPhone14,7"] = 3, -- iPhone 14
    ["iPhone14,8"] = 3, -- iPhone 14 Plus
    ["iPhone15,2"] = 3, -- iPhone 14 Pro
    ["iPhone15,3"] = 3, -- iPhone 14 Pro Max
    ["iPhone15,4"] = 3, -- iPhone 15
    ["iPhone15,5"] = 3, -- iPhone 15 Plus
    ["iPhone16,1"] = 3, -- iPhone 15 Pro
    ["iPhone16,2"] = 3, -- iPhone 15 Pro Max
}

四、关于Unity识别灵动岛的方式

        适配过程中遇到的另一个问题是,如何识别灵动岛设备。这个问题也没有查到任何便捷的方式。在此列举现有的灵动岛设备型号:

DynamicIslandDevices = {
    "iPhone15,2", -- : iPhone 14 Pro
    "iPhone15,3", -- : iPhone 14 Pro Max
    "iPhone15,4", -- : iPhone 15
    "iPhone15,5", -- : iPhone 15 Plus
    "iPhone16,1", -- : iPhone 15 Pro
    "iPhone16,2", -- : iPhone 15 Pro Max
}

        实际上,普通刘海屏完全可以还使用Screen.safeArea去获取尺寸。只需要在判断前面先识别出灵动岛屏幕,用上述的尺寸和缩放系数换算出像素值,再按工程里Canvas的比例去换算对应需要挪动的数值就可以了。

五、后话

        上述方式虽然实现了适配,但是充满了枚举,是不想更新Unity并且希望热更就可以实现的妥协之举。明年再出新的设备又要加枚举。如果有更合适的方式,欢迎留言指教。

        此外,过程中收藏到一个宝藏GitHub仓库,可以方便的查看iPhone设备型号对应的设备,不用每次都去网上到处找了,在此推荐一下:

       pluwen/apple-device-model-list: All Apple devices model name list. 通过内部编号判断 iOS 设备型号。(已更新iPhone15系列) (github.com)icon-default.png?t=N7T8https://github.com/pluwen/apple-device-model-list

你可能感兴趣的:(unity,游戏引擎,游戏,iphone,ios)