簡介
Vision Pro是蘋果公司的首款頭戴式“空間計算”顯示設備,於2023年6月6日在“WWDC2023”正式發佈,同時推出的還有專爲Vision Pro打造的操作系統平臺visionOS,以及一整套“新的”開發工具,之所以打引號,是因爲用於Vision Pro開發的工具和編程語言並沒有多少改變,而更多的是需要開發者的開發思維變化。
最近公司組織了幾批人員,前往蘋果實驗室實地體驗Vision Pro,並在現場進行適配調試。我有幸參與其中,現在就把整個過程的體驗分享給大家,同時分享一些visionOS開發的基礎。
別具一格的交互
要了解Vision Pro上應用的適配與開發,就要先了解它的人機交互方式。現在市面上大多數的VR設備採用的都是通過手柄進行指向、選擇和點擊的操作,輔以識別簡單的手勢(比如左右滑動等)和頭部活動(點頭、搖頭等)。這樣的交互方式最大的優點就是可以降低成本,手柄的製造工藝已經相當成熟,內置陀螺儀和紅外感應、NFC元件都不是什麼難事,同時減少VR設備的傳感器數目從而降低重量,延長續航。
但是蘋果顯然認爲這種交互方式不夠理想,如果體驗過其他蘋果產品就會發現,蘋果的設計師似乎一直傾向於利用用戶自己的身體來實現目標需求,指紋識別,面部識別,多指手勢以及“嘿,Siri”都是一貫如此。而在Vision Pro上,蘋果認爲用戶的眼睛和手完全就可以勝任手柄的工作,所以他們提出的交互方式是別具一格的“眼球追蹤+手勢識別”。
蘋果通過遍佈Vision Pro眼部周圍的傳感器,實現了精讀極高的眼球追蹤技術:
這樣一來,用戶的眼睛就變成了鼠標的指針,想要選中哪個元素,只要看向它就可以了。就我實際的體驗而言,精度和準確率都非常之高,就連非常小的UI元素都可以準確的選中:
不止如此,蘋果還通過Vision Pro下面的一圈傳感器進行手勢的收集和識別:
蘋果下了這麼大的血本只爲了一個目的:無論用戶的手放在哪裏,都可以實現高精度的手勢識別,面前,腿上,沙發上都可以。在首次開機的學習引導裏,蘋果給出的提示語就能非常好的概括:“you can place your hands wherever you feel comfortable”
除了不限位置,Vision Pro還可以準確的識別單擊、捏住和雙手手勢:
Tap:同時點擊拇指和食指,表示點擊顯示屏上的虛擬元素,相當於點擊iPhone的屏幕。
Double Tap:雙擊手勢。
Pinch and Hold:類似於點擊並按住手勢,執行突出顯示文本等操作。
Pinch and Drag:可用於滾動和移動窗口。您可以水平或垂直滾動,如果用戶加快手勢速度,交互界面也會相應地調整速度。
Zoom:雙手手勢之一,可以把手指捏在一起,通過拉開手勢進行放大,窗口大小也可以通過在角落拖動來調整。
Rotate:另一個雙手手勢之一,它將涉及將手指捏在一起並旋轉雙手以操縱虛擬對象。
雖然乍一看起來通過眼球追蹤和手勢識別來進行日常的操作比較繁瑣,你要先看着想要點擊的地方,再捏一下手指,但實際體驗下來整個過程非常流暢、自然,沒有違和感,與蘋果生態一貫的操作習慣一脈相承,基本不需要額外的學習成本。但是這種便利的代價也很明顯:大量的傳感器增加了設備的成本(3w+)和重量(600-650g),同時即便是連接外接電池,最長也只能實現2小時的續航時間。
現在還無法斷言蘋果這套交互方案和手柄對比誰好誰壞,但是正如以往蘋果率先提出的“觸屏取代實體鍵盤”,“觸摸板手勢”以及“全面屏交互”等方案,經過長時間的市場檢驗,最終還是別廣大廠商採用並效仿,這一次蘋果在Vision Pro上提出的這套全新的“空間交互方案”日後很有可能成爲VR設備採用的主流方案。
移植的適配邏輯
不少研發同學都會有疑問:我的APP沒有單獨對Vision Pro做過適配,那麼它能直接在Vision Pro上運行嗎?可以的話它原始的適配邏輯又是什麼?
首先對於第一個疑問,答案是肯定的,就算沒有經過任何適配,app依然可以在Vision Pro上正常運行,所有的交互都能執行,甚至可以通過盯住屏幕左側用捏住並拖拽實現“左劃返回”手勢。
至於原始適配邏輯,如果有曾經在 iPad,或者M系列芯片 Mac電腦上運行手機App的經驗,就能大致明白他們在Vision Pro上的適配邏輯了,就是在屏幕上創建一個手機屏幕大小的“模擬器”,讓app在上面運行。這裏以我們“京東到家”的app爲例
當然,如果app做過iPad的適配,那麼在Vision Pro上的展示樣式則會優先展示爲iPad的樣式,比如京東主站app:
同時,在App下端會展示兩個控制元素,一個小圓點和一個橫條。眼睛看向小圓點的話,它會變成一個叉號,用於關閉App(退至後臺),需要完全殺死App的話,邏輯則類似於Mac電腦的殺死進程,需要同時按住Vision Pro的返回鍵和錶冠2秒,然後再應用列表中找到 App強制結束
那既然不需要適配也可以正常運行,我們是不是就不需要單獨進行VisionOS的開發了呢?當然不是。未經適配的App雖然能夠正常運行,但是它的展示樣式畢竟是爲了手機端而設計的,在Vision Pro上,屏幕從2D的平面拓展到了3D的空間,而在“空間”中,Vision Pro更着重於凸顯“無界”的概念:
蘋果更傾向於讓App沒有邊界,不侷限於手機屏幕的條條框框中,更加融入到空間之中,同時visionOS也允許UI元素超出App的界面邊界。所以對於Vision Pro的適配,更多的是從平面到空間的思維轉變,如何讓App在“空間”這一畫布上更好地呈現設計者想要表達的意圖纔是重中之重。要進行“空間計算”開發,就要了解基礎的visionOS開發機制,下面我將介紹一些入門的知識。
開發從入門到略懂
首先,在Xcode15中創建app時,除了以前的iOS、macOS等平臺,現在可以選擇visionOS平臺進行開發,此時SwiftUI提供了許多專爲Vision Pro準備的新API,以供空間應用開發。
選擇visionOS平臺後,可以設置場景類型和氛圍樣式:
場景類型
visionOS的app中可以創建三種場景類型:
Window形式
主要用於展示2D內容,iPhone和iPad的App在Vision Pro中展示默認就是採用這種形式,如果app需要展示文本內容、視頻或者彈窗等等,可以創建這種場景來進行展示。Window形式也可以展示3D元素,但是無法在空間中360度的查看3D模型,因爲Window在空間中是以類似於鏡子的形態呈現,繞到後面時只能看到白色半透明的面板。
Volumes形式
蘋果官方描述說這是最適合展示3D模型的場景,當在app中創建了Volumes類型的場景時,visionOS會開闢出一個3D的空間用於放置3D元素,如果我們想要放置商品的3D模型進行全景展示,可以創建這種場景
Spaces形式
在這種場景下,visionOS會將使用者周圍全部設置爲可以放置UI元素的區域,周圍的所有空間都可以作爲開發者的“畫布”,你可以在任意位置放置2D、3D模型。但是需要注意的是這種場景理論上只應創建一個。
氛圍樣式
氛圍樣式是app的呈現形式,分爲.mixed, .progressive,.full三種,我們可以通過一個圖來清晰明瞭的理解它們分別代表的意思:
在工程當中也可以通過代碼來進行設置,以實現在不同氛圍之間切換:
@main
struct MyImmersiveApp: App {
@State private var currentStyle: ImmersionStyle = .full
var body: some Scene {
WindowGroup() {
ContentView()
}
// Display a fully immersive space.
ImmersiveSpace(id: "solarSystem") {
SolarSystemView()
}.immersionStyle(selection: $currentStyle, in: .mixed, .progressive, .full)
}
}
風格適配
既然app是在Vision Pro的空間中展示,那麼最好可以遵循Vision Pro統一的樣式風格,比如:
圓角,毛玻璃半透明的背景
懸停效果
這裏說一下懸停效果,它指的是眼睛停留在某個UI元素上時的效果。如果不進行適配,在Vision Pro上運行app,眼睛看向一個可以點擊的元素時,它會被高亮顯示:
但是蘋果似乎覺得這樣簡單粗暴的懸停效果不夠高雅,所以提供了hoverEffect屬性讓我們可以自定義懸停效果:
這樣設置後,眼睛停留在元素上時,我們可以實現高亮、突出、改變圓角等效果,而且高亮點會隨着眼睛盯的點而改變,非常神奇。
超出邊界外佈局
在visionOS app中,爲了提高場景的沉浸感,蘋果允許把導航欄、tab欄和工具欄等內容無關的元素設置到界面外,並且給他們起了一個獨特的名字:ornament。使用系統自帶的UIHostingOrnament:
當然也可以自定義,將原來的導航欄等元素改造成ornament:
改造前
struct ContentView: View {
@State private var selection: AppScreen = .backyards
var body: some View {
NavigationSplitView {
AppSidebarList(selection: $selection)
} detail: {
AppDetailColumn(screen: selection)
}
}
}
改造後
struct ContentView: View {
@State private var selection: AppScreen = .backyards
var body: some View {
View()
.ornament(visibility: isGoalPanelVisible,
attachmentAnchor: .scene(.bottom),
contentAlignment: .center) {
NavigationSplitView {
AppSidebarList(selection: $selection)
} detail: {
AppDetailColumn(screen: selection)
}
}
}
}
添加3D模型
visionOS使用了蘋果佈局多年的RealityKit,結合SwiftUI,從而使得加載3D和2D模型就像加載一張本地資源圖片一樣方便:
struct SphereView: View {
@State private var scale = false
var body: some View {
RealityView { content in
if let earth = try? await ModelEntity(named: "earth") {
content.add(earth)
}
} update: { content in
if let earth = content.entities.first {
earth.transform.scale = scale ? [1.2, 1.2, 1.2] : [1.0, 1.0, 1.0]
}
}
.gesture(TapGesture().targetedToAnyEntity().onEnded { _ in
scale.toggle()
})
}
}
代碼中RealityView就是專門用來展示模型資源的視圖,就如同UIImageView加載圖片一樣,使用ModelEntity就可以很方便的加載本地的模型資源,並設置碰撞體積CollisionComponent和旋轉縮放等等
需要注意的是蘋果目前僅支持USDZ格式的模型,蘋果給出了幾個非常精美的模型資源以供下載:
https://developer.apple.com/cn/augmented-reality/quick-look/
另外我找到了幾個可以免費下載USDZ格式資源的網站:
https://www.cgtrader.com/zh-cn/3d-models/ext/usdz
https://www.turbosquid.com/zh_cn/Search/3D-Models/usdz
與業務結合的實踐
我們在進行實際業務場景適配的時候,如果是全新的Vision Pro app,則首先要判斷當前平臺是否是visionOS,如果是像我們一樣基於iPad app進行改造,那麼要判斷是否是iPad設備,我們所採用的機型判斷方法爲:
func osType() {
if UIDevice.current.userInterfaceIdiom == .phone {
print("This code is running on iPhone")
} else if UIDevice.current.userInterfaceIdiom == .pad {
print("This code is running on iPad")
} else if UIDevice.current.userInterfaceIdiom == .vision {
print("This code is running on Vision Pro")
}
}
以我們零售app的適配設計爲例,是基於iPad app進行改造,爲了獲得更好的展示效果,需要針對寬屏做UI改造:
iPhone設計稿:
iPad設計稿:
除了上文中提到的懸停效果等改造,資源位寬度,間距和排布等要素也需要進行相應的改變,來適配iPad或者Vision Pro更寬闊的視野。我們的Feeds展示場景,入口求部分氛圍中配置的樓層背景圖拉伸,並根據設計稿進行適配;爲你推薦資源位一行二的展示樣式改爲爲一行四,在用戶使用時能夠獲得更好的視覺體驗。
本篇暫時就先介紹到這裏,後續會有更多Vision Pro適配和空間開發的文章,希望能幫助大家在即將到來的這場“空間計算戰鬥”先拔頭籌。