Site icon 8bit.media

【Unity官方Blog】處理AR中的比例問題

Spread the love

Unite Austin 2017中,Unity的開發人員Jimmy Alamparambil和Tim Mowrer做了一場演講《在Unity中使用ARKit和ARCore》。這次演講中,我們已經為大家介紹了《在ARCore和ARKit中實現多人遊戲》,除此之外,演講重點提到了內容縮放及其必要性。並且解釋了為何應該使用“攝像機技巧”來實現縮放,而不是自己動手去縮放內容。關於內容的縮放方式,我們展示了兩種方式,一是使用單個攝像機,另一種是使用兩個或更多的攝像機。本文中將提供實現的具體細節。
https://blogs.unity3d.com/2017/11/16/dealing-with-scale-in-ar/
《在Unity中使用ARKit和ARCore》視頻演講

https://v.qq.com/x/page/o0501q3n89t.html 

基本原理

假設你想製作一個名為“暴怒公雞”的桌面遊戲,一隻受輻射變異的巨型公雞蹂躪城市。你可以先從Asset Store資源商店下載一個城市環境模型。城市的大小在100米x100米以上。然後將公雞資源導入到城市場景中。一隻0.3米高的公雞可沒有什麼威脅感,所以你將它在三個軸向上的大小都放大100倍,使公雞長到30米高,厲害了!

將一個類似這樣的第三人稱視角遊戲轉換成AR的難度有多大?當移植到任何新平台時,總會碰到一些常見問題。例如用戶界面改變和不同的輸入方式。對於AR來說,還有一個你可能預料不到的問題:比例。

將《暴怒公雞》遊戲轉換到ARKit/ARCore,首先需要將特定的AR資源包導入到遊戲中。對場景稍作改動,就可以查看場景在AR中的樣子了。當啟動遊戲,你可能只會看到一些佔據了整個屏幕的巨大像素。四處移動,屏幕上只會充斥著這些大型像素。完全沒有城市和公雞的影子。問題在哪?

比例

Unity編輯器中的距離單位時米。一個100米大小的城市區域將佔據100個單位。ARKit和ARCore的原生單位也是米。聽起來似乎兩者完美匹配。對於某些AR體驗來說,你可能希望資源能和真實世界完美匹配。例如:一個跟你等高的人體模特,展示最新的流行服飾,而你可以繞著它走動。對於桌面體驗,你通常會希望資源可以縮小到桌子的可玩區域大小。對於這個例子來說,我們的《暴怒公雞》城市,放入AR之後需要100米的物理空間,就像真實的城市一樣。大多數的桌子基本上只有半米大小,所以我們要怎樣將城市放到桌子上是一個問題。

作為一個經驗豐富的Unity開發者,縮放城市、公雞和特效匹配桌子的首選解決方案,可能是將所有東西放到一個變換之下,然後縮放變換對象。視覺上城市和公雞會縮小,但特效不能正確的縮小。你的公雞可能還是以原來的速度移動。此外重力也沒有按比例縮放,導致所有東西都以瘋狂的速度下落。你可以花費大量時間手工調整這些區域,以使它們一一匹配,但如果要確保城市能在不同尺寸的桌子上都能正確縮放,那這就是個近乎不可能的任務了。

幸運的是最新的通用AR腳本接口解決了這個問題,不再需要手工單獨調整遊戲中的比例。我們提供了兩套方案,滿足不同需求:一個是設計為對整個場景應用一個通用比例,另一個則允許使用不同的比例組合。

通用比例

將來自設備的所有位置信息乘以一個比例常量是最簡單的做法。這包括設備自身的位置以及它生產的數據,例如平面或特徵點。旋轉信息無需進行縮放。

ARCore和ARKit產生的信息以米為單位,且都是相對於跟踪開始的位置。也就是說,(0, 0, 0)指的時應用啟動時所在的位置。所有生成的數據,例如平面,也同樣是以此位置為參照點。我們將此稱為“設備空間”。

Unity使用的也是米,但我們常常需要將那些好幾米高的物體縮小到真實世界中的幾厘米大小。我們將這個場景所在的原始空間稱為“內容空間”。

將位置信息乘以一個比例因子,可以完成設備空間到內容空間的轉換。而縮放內容,則可以反過來進行內容空間到設備空間的轉換。後者要困難的多,因為Unity中的許多系統會改變它們的行為,或較難高效的進行縮放。

例如物理交互會因縮放而改變。縮小物理物體會產生不穩定、抖動或其它不期望看到的行為改變。其它的系統,例如地形和導航網格,一旦創建,就無法被縮放或移動。因此對它們來說,不可能進行縮放。粒子系統沒有一個總體縮放因子,因此開發者需要調整好幾個獨立的設置,以保持原先的效果外觀。相較而言,對攝像機進行縮放要簡單的多了。

在Unite的演示程序,我們將Unity攝像機放在了一個名為“AR Root”的遊戲對象之下。所有設備生成的遊戲對象,例如平面,都被實例化為攝像機遊戲對象的兄弟節點。我們隨後可以將比例和位置偏移量應用到AR Root遊戲對象,從而移動和縮放攝像機與平面。運行時的層級可能會看起來像下面這樣:

AR Root
ARCamera
Plane1
Plane2

AR Root遊戲對象應當包含一個ARController組件,用於管理AR SDK的生命週期。要設置比例,只需簡單的設置ARController.scale。

示例

假定我們的比例因子是10。當應用啟動時,設備報告的當前位置時(0,0,0),所以,我們的ARCamera也會在(0,0,0)。我們在現實世界中後退一米,ARCamera的localPosition就會是(0,0,-1)。但是,由於AR Root遊戲對象的縮放比是(10,10,10),所以攝像機的世界位置將會是(0,0,-10)。這意味著原先的內容將會離攝像機10倍遠,它看起來縮小了10倍。但是,它實際上並沒有縮小,因此物理交互不會發生變化,導航網格也會按原來設計的方式運作等等。

命中測試

ARKit和ARCore都提供了針對特徵點和平面的命中測試API。但是它們對縮放無感(即命中測試總是在設備空間內進行)。我們可以先從內容空間轉換到設備空間,進行命中測試,然後將結果再轉換回內容空間。不過對我們的需求來說,只需簡單的在平面遊戲對像上添加一個網格碰撞器,並對它進行射線投射即可。

我們使用的平面預製件包含一個plane基本體以及一個網格碰撞器,它們被設置為一個單位的縮放能產生一個1×1米大小的平面。由於AR Root遊戲對象擁有一個縮放因子,因此也會對平面進行縮放。這意味著我們可以正常進行物理射線投射,而無需考慮比例。例如,假定我們希望在用戶輕觸屏幕時放置一個對像到一個平面上。我們可以使用下面這樣的代碼:

參見PlaceOnPlane.cs,了解完整示例。注意其中沒有針對比例的特殊處理,因為攝像機和平面都已經處於內容空間中。

匹配比例

上文解釋瞭如何應用某個特定的比例因子,但如果你想將某個特定資源或關卡幾何模型匹配到一個表面,而這個表面的大小只有在平面明確後才會知道,這時又該如何?假想你有一個複雜的場景,可能包含了整個城市區域,而你想將它放到一個桌面,剛好匹配桌子的大小。你該選擇什麼比例因子呢?很簡單!正確的比例因子是:

scale = levelSize / surfaceSize

levelSize是內容的大小(以米為單位)。比如,這可能是它邊界框其中一條邊線的長度。surfaceSize是平面的大小(以真實世界中的米為單位)。這可能是維度中較小邊的長度,即:

Mathf.Min(plane.width, plane.height)

參見MatchingScalePicker.cs,了解完整示例。

關卡幾何體的定位和定向

前面提到過某些資源在運行時無法移動或旋轉。例如Unity中的地形和導航網格就有這個限制。我們知道如何在運行時縮放它們,但如何對它們進行定位和定向呢?如果你想將關卡幾何體放置在一個桌面,代表桌子的平面可能會在任意位置和方向。既然我們無法移動內容,我們可以相應的更改AR Root遊戲對象的位置和方向。

例如:如果關卡幾何體的中心位於p1,而我希望將它放置在p2,那我們應該移動AR Root遊戲對象,以使p1=p2。即,不將關卡幾何體移動到p2,而是將AR Root遊戲對象朝相反方向移動相同距離。由於平面和攝像機之間沒有發生相對位移,因此這樣看起來似乎只有關卡幾何體發生了移動。

對於方向,我們可以採取同樣的做法。因為我們無法旋轉關卡幾何體來匹配平面的方向,所以我們反向旋轉AR Root遊戲對象。另一種思考方式是,如果我們在空間中旋轉關卡幾何體,實際上是將AR Root圍繞關卡幾何體做反方向的旋轉。

ARController組件有一些輔助方法,可以完成這些位置和方向的更改:

public Vector3 ARController.pointOfInterest
“point of interest”是內容空間中,我們希望AR Root遊戲對象圍繞其運動的中心位置。一般就是關卡幾何體的中心點。

public Quaternion ARController.rotation
位於pointOfInterest處的內容看起來應該有的旋轉狀態。實際上AR Root遊戲對象向反方向旋轉同樣數值。

public void AlignWithPointOfInterest(Vector3 position)
移動AR Root遊戲對象,以使point of interest看起來已經“到位”。這可能會是針對某個平面做射線投射後的返回結果。

參見DemoGUI.cs組件,了解代碼示例。

混合比例

第二個選擇的大致描述如下,相關ARKit插件的代碼和項目可參見文末的下載資源列表。目前它還不是ARInterface示例項目的一部分,但過些時候就會加入。

對於雙攝像機解決方案,我們使用一個攝像機來跟踪現實世界坐標系統中的遊戲對象,例如你正打算在其之上顯示內容的桌子的大小和位置。我們將之稱為“TrackingDataCamera”,並使它隨ARKit設備移動和旋轉。它還會渲染所有由ARKit生成的遊戲對象,比如調試平面和特徵點。

第二個攝像機,我們將它稱為“ContentCamera”,它有一個父級變換。對該變換實施定位和旋轉,可使由此攝像機渲染的內容場景以正確的大小出現在正確位置。這是如何辦到的?首先是“內容錨點”,這是一個真實世界坐標的點,即縮放後場景的出現位置。我們計算該點與TrackingDataCamera之間的偏移。將這個偏移乘以你所希望的場景比例的倒數(例如,如果你希望城市場景縮小到原尺寸的1/100,我們就把偏移量乘以100)。然後將ContentCamera的父變換相對於錨點位置平移這個乘積的量。這個ContentCamera的攝像機變換仍然與TrackedDataCamera的定位與旋轉保持一致,因此它的方向與設備相同。參見下面粗略的草圖,理解父變換的移動方式。

如何使用它?在UnityARContentScalingScene中,將SkyscraperRoot遊戲對象替換為包含你內容的場景對象。當你啟動場景,它將會尋找一個表面,而當你輕觸表示那個表面的調試平面時,它將使用點擊的位置作為前面提到的ContentAnchor(內容錨點)。你的內容將會顯示在那個位置。如果你知道你的內容所需的比例,在Content Scale Manager組件的Content Scale參數中找到ContentCameraParent遊戲對象,並將所需的值賦予它。GUI上的+和-按鈕可以幫你確定內容的正確比例。

雙攝像機(或多攝像機)方案在多種情況下十分有用:

資源下載

ARKit下載
Bitbucket:https://bitbucket.org/Unity-Technologies/unity-arkit-plugin
Asset Store:https://www.assetstore.unity3d.com/en/#!/content/92515

ARKit插件的代碼和項目
https://bitbucket.org/Unity-Tech … /alt-scaled-content

ARInterface示例代碼
https://github.com/Unity-Technologies/experimental-ARInterface

TANKS! Networking示例
https://www. assetstore.unity3d.com 

小結

正如你所見,我們可以在開發時和應用到現實世界中時採用不同的縮放比,以此創建出更真實更美觀的AR體驗。我們已經討論了一些方法,讓創作者無需太多工作量即可實現這一目標。我們也為你提供了兩個現成的解決方案,你可以在自己的應用中使用。請試用我們的解決方案並在Unity官方社區分享你的使用心得!!

Exit mobile version