This document is about: FUSION 1
SWITCH TO

This page is a work in progress and could be pending updates.

Expo

Level 4
Available in the Industries Circle
Circle
這個Fusion Expo範例的新的版本,不再要求XR互動工具組套件,而且現在共享在VR共享範例頁面中描述的相同的簡單的互動堆疊。
如果您對於在一個Fusion應用程式中整合XR互動工具組上需要協助,請聯絡在Circle Discord上的VR團隊

概述

Fusion Expo範例展示了一個方法,以開發一個在Fusion的最多達100名玩家的社交應用程式。

各個玩家由一個虛擬人偶所代表,並且如果玩家們位於相同的聊天氣泡中,則可以利用Photon Voice SDK與其他玩家交談。

這個範例的一些聚焦點有:

  • 首先,玩家在選擇虛擬人偶畫面來客製化其虛擬人偶,
  • 然後,他們可以加入Expo場景。如果玩家在PC或MAC上啟動範例,它可以選擇桌面模式(使用鍵盤及滑鼠)或VR模式(Meta Quest頭戴式裝置)。
  • 如果玩家們位於相同的靜態聊天氣泡中,玩家可以與彼此交談。在各個靜態聊天氣泡中,可用一個鎖定按鈕以預防新的玩家進入。
  • 同時,如果兩個玩家彼此很接近,將以較慢的速度在玩家周圍建立一個動態聊天氣泡。
  • 某些3D筆可用於建立3D繪畫。可使用錨點來移動各個3D繪畫。
  • 同時,可用一個傳統的白板。可使用錨點來移動各個繪畫。
  • 玩家可以移動到一個新的位置(新的場景載入)。

在程式碼評論中直接提供更多技術細節。

fusion expo

技術資訊

  • 這個範例使用共享模式拓撲,但是核心是與共享及主機端模式拓撲相容,
  • 組建可用於PC、Mac及Meta Quest,
  • 專案已經以Unity 2021.3.13f1、Fusion 1.1.3f 599及Photon voice 2.31來開發,
  • 支援2個虛擬人偶解決方案(自製的簡單虛擬人偶及Ready Player Me 1.9.0虛擬人偶),

在您開始之前

為了運行範例:

  • PhotonEngine儀表板中建立一個Fusion應用程式帳號,並且將它貼上到即時設定(可從Fusion選單中到達)中的App Id Fusion欄位之中。

  • PhotonEngine儀表板中建立一個Voice應用程式帳號,並且將它貼上到即時設定中的App Id Voice欄位之中

  • 然後載入AvatarSelection場景並且按下Play

下載

版本 發佈日期 下載
0.0.19 2023年5月12日 Fusion Expo XR共享0.0.19組建192

下載二進位檔

下方是可用的一個Expo的展示版本:

處理輸入

桌面

鍵盤

  • 移動:WASD或ZQSD以行走
  • 旋轉:QE或AE以旋轉
  • 機器人繁衍:按下「B」以繁衍一個機器人。持續按住超過1秒以在放開時建立50個機器人

滑鼠

  • 移動:按下您的滑鼠左鍵以顯示一個指標。您將在放開時傳送到任何已接受目標
  • 旋轉:持續按下滑鼠右鍵並且移動滑鼠以旋轉視角
  • 移動及旋轉:持續按下滑鼠左鍵及右鍵以向前移動。您仍然可以移動滑鼠以旋轉
  • 拿取及使用(3D筆):將滑鼠放在物件上,並且使用滑鼠左鍵來拿取它。然後您可以使用鍵盤空白鍵來使用它。

Meta Quest

  • 傳送:按下A、B、X、Y,或任何搖桿以顯示一個指標。您將在放開時傳送到任何已接受目標
  • 觸碰(也就是針對聊天氣泡鎖定按鈕):簡單地將您的手放在一個按鈕上以切換它
  • 拿取:首先將您的手放在物件上,並且使用控制器拿取按鈕來拿取它
  • 機器人繁衍:按下左控制器上的選單按鈕以繁衍一個機器人。持續按住超過1秒以在放開時建立50個機器人

資料夾架構

主要資料架/Expo 含有特定於這個範例的所有元素。

資料夾/Expo/Integrations 管理與第三方解決方案的相容性,比如ReadyPlayerMe。

/Photon資料夾含有Fusion及Photon Voice SDK。

/Photon/FusionXRShared資料夾含有來自VR共享範例的裝置及拿取邏輯,建立一個FusionXR共享輕量SDK,其可以與其他專案共享。

/Photon/FusionXRShared/Extensions資料夾含有針對FusionXR共享的延伸模組,針對可重複使用的功能比如已同步射線、運動驗證...

/Plugins資料夾含有Ready Player Me SDK

/StreamingAssets資料夾含有預先組建的ReadyPlayerMe虛擬人偶。如果您不希望使用這些預先組建的虛擬人偶,它可以被自由移除。

/XRI/XR資料夾含有針對虛擬實境的設置檔案。

架構概述

Fusion Expo仰賴於與VR共享頁面中描述的相同的程式碼基礎,特別是在裝置同步方面。

這裡使用的拿取系統是在VR共享——本機裝置拿取頁面中描述的替代性「本機裝置拿取」執行方式。

在這個基礎之外,範例含有一些到FusionXR共享的延伸程式,以處理一些可重複使用的功能,比如已同步射線、運動驗證、觸碰、傳送平順或一個凝視系統。

網路連線及應用程式生命週期

ConnexionManager在共享模式拓撲中啟動一個Fusion遊戲階段,並且針對各個已連線使用者來繁衍一個使用者預製件。如需更多細節,請參見VR共享範例文檔的「連線管理器」章節

SessionEventsManager觀察Fusion及PhotonVoice連線狀態以警示它們感興趣的元件,特別是處理各種音效的SoundManager..

聲音

VoiceConnectionFusionVoiceBridge元件啟動Fusion遊戲階段的聲音Photon Voice連線,Recorder元件捕捉麥克風輸入。

針對Oculus Quest任務組建,需要額外的使用者授權,而且這個請求是由MicrophoneAuthorization指令碼所管理。

使用者預製件含有一個SpeakerVoiceNetworkObject放置在它的頭上,以在接收聲音時投射空間化的聲音。

如需更多關於Photon Voice與Fusion整合的資訊,請參見這個頁面:https://doc.photonengine.com/en-us/voice/current/getting-started/voice-for-fusion

裝置

在一個沉浸式應用程式中,裝置描述了代表一個使用者所必要的所有可移動部件,通常是雙手、一個頭,以及遊玩區域(舉例而言,當一個使用者傳送時,它是可以被移動的個人空間),

當在一個已連線遊戲階段時,每個使用者由一個已連線裝置所代表,其各種部件位置透過網路來同步。

fusion vr shared rigs logic

關於裝置部件的組織及同步的方式,多個架構為可用,且有效。在這裡,一個使用者由一個單一的NetworkObject所代表,附有多個巢狀NetworkTransforms,針對各個裝置部件都有一個。

關於代表本機使用者的網路裝置的具體案例,該裝置必須由硬體輸入來驅動。為了簡化這個流程,已經建立一個獨立的,非連線的裝置,稱為「Hardware rig」。它使用傳統Unity元件來收集硬體輸入(如同TrackedPoseDriver)。

NetworkedRig元件,位於使用者預製件上,針對所有巢狀裝置部件來管理這個追蹤。

FixedUpdateNetwork()期間與其他玩家分享裝置部件位置之外,NetworkRig 元件也處理外插:在Render()期間,移動處理各種裝置部件的NetworkTransforms的圖形代表的內插補點目標,以確保本機使用者總是看見它們的手在最近的位置,就算再網路刷新之間也是如此。

如需更多關於裝置部件同步的細節,請參見VR共享範例文檔的「裝置——細節」章節

裝置資訊

為了能夠輕鬆地找到HardwareRig及配對關於本機使用者的NetworkRig,元件RigInfo針對進一步的使用來註冊HardwareRig及本機NetworkedRig

riginfo content

互動堆疊

這個範例允許玩家來移動、拿取物件,及觸碰表面。

所有這些操控都在本機完成(在硬體裝置上),獨立於網路,然後透過Fusion到網路裝置的輸入來發送到網路。

運動

在虛擬實境中,透過基於射線的傳送來提供運動,在搖桿上附有可用的額外的固定角度轉身。運動由RayBeamerRigLocomotion類別來管理,如同在VR共享範例文檔的「傳送及運動」章節中所說明。

此外,將同步射線,這樣它們可用於向其他使用者指向某個東西。它是透過HardwareHandRay類別來完成,其透過一個[Networked]變數來與其他使用者同步一個RayData架構。

在桌面版本中,使用者可以以鍵盤移動,或以滑鼠左鍵按下地面以傳送到那裡。DesktopControllerMouseTeleport元件管理運動,而MouseCamera元件使用滑鼠右鍵點擊移動來管理相機移動。

針對遠端使用者,遊玩區域移動被平滑化,以逐步移動到目標位置來取代傳送(除非instantPlayareaTeleport選項被設定為真)。這個平滑在TeleportationSmoother類別中完成。它包含一個[OrderAfter(typeof(NetworkRig))]以在自己的FixedUpdateNetwork()中覆寫由NetworkRig FixedUpdateNetwork定義的位置(它只在需要平滑時進行此覆寫)。

運動限制

這個範例應用程式有時候防止使用者前往某些地方(舉例而言,如果已經達到聊天氣泡的最大人數,則不可以進入一個聊天氣泡)。

為了做到這點,每個希望移動玩家的元件都仰賴於泛型運動驗證系統,及與一個特定運動模式有關的限制式。

運動驗證系統

為了確定使用者是否不嘗試前往一個禁止區,每個運動系統首先詢問放置於HardwareRig上的HardwareLocomotionValidation元件,它們是否可以以CanMoveHeadset()方法移動到這個位置。為了回答,HardwareLocomotionValidation首先以其所有的ILocomotionValidator下層,以及放置於在網路上代表本機使用者的NetworkedRig執行個體旁邊的所有NetworkLocomotionValidation元件的ILocomotionValidator下層,來檢查移動是否有效。

locomotion system

此外,如果一個使用者將頭放在一個禁止區,視角將淡出,以防止它們「作弊」。它在InvalidMoveCameraFader類別中處理。

其他限制

此外,運動由其他因素限制,取決於使用的運動系統:

  • RigLocomotion:一個使用者只能在碰撞器上透過RigLocomotion的運動圖層遮罩中的一個圖層進行傳送(比如TeleportTarget圖層)
  • LocomotionValidatedDesktopController運動:控制器檢查在一個移動之後的頭位置是否正確,透過檢查它不在一個碰撞器中,以及檢查在移動後一個正確的可行走的導航網格點將在它之下
  • Bot:它確保機器人將維持在可行走的導航網格點上

可觸碰

為了在手指觸碰上觸發事件,手含有一個Toucher元件,而有些物件有一個Touchable元件。完全在硬體裝置中處理事件,並且沒有自動的連結到網路:您必須在由Touchable.OnTouch調用的元件中處理它。

請注意,桌面控制允許您透過BeamTouchableBeamToucher類別,以滑鼠指標來觸碰Touchable。這些相同的類別可以允許一個VR使用者來指向及按一下一個UI(取決於在BeamToucher類別上選擇的能力)。

UI

可透過滑鼠來使用畫布按鈕及滑桿。

為了能夠以使用者的手指或VR中的指標來觸碰它們,UITouchButton元件確保當使用者觸碰3D按鈕方盒碰撞器時,觸碰時事件被轉傳到UI按鈕。TouchableSlider元件以相同的方式管理滑桿值。

為了在一個畫布中的按鈕及滑桿上自動地新增這些元件,TouchableCanvas元件管理含有它們的預製件的自動具現化。

拿取

在這個範例中,拿取只用來處理筆及繪圖操控。

這裡使用的這個拿取系統是VR共享——本機裝置拿取頁面中描述的替代性的「本機裝置拿取」執行方式。

虛擬人偶

使用者由一個圖形代表所代表,稱為一個虛擬人偶。這個範例支援兩種虛擬人偶,來自Ready Player Me的及一個自訂的較簡單的虛擬人偶。

凝視者

為了提供一個更自然的虛擬人偶代表,一個專用系統處理自動眼睛追蹤:當一個興趣物件出現在一個虛擬人偶之前時,它的眼睛將找到這個目標並且跟隨它。如果一個較近的目標出現,眼睛的聚焦將改變。

如果沒有可用的目標,眼睛將隨著時間隨機地移動。

最後,所有在這個範例中可用的虛擬人偶系統都處理眨眼,也為了讓其顯得更為自然。

為了成為一個潛在的眼睛目標,一個遊戲物件必須有一個GazeTarget元件。在預先組建的預製件中,所有虛擬人偶的眼睛及頭預設有該元件。這些GazeTargetGazeInfo管理器中註冊。

Gazer元件透過詢問GazeInfo潛在(以有效最終視角及目標距離)GazeTarget的一個排序清單(按照距離),來驅動眼睛。

當有很多可用的目標非常靠近的時候,整理過程非常繁重,並且是在背景執行緒中完成。

gaze system

這裡使用的手模型來自Oculus範例框架(由Facebook Technologies, LLC及其關係企業在一個BSD-3授權下發布)。

驅動手移動的輸入動作在本機上收集,並且透過Fusion共享,以在所有客戶端上顯示手移動。

稍微遠端地離散化手移動,以減少改變的頻率。

手顏色匹配使用的虛擬人偶代表的皮膚顏色。

虛擬人偶代表

各個虛擬人偶儲存一個虛擬人偶URL,透過放置在NetworkRig上的UserInfo元件中的一個Fusion [已連線] 變數來共享。

在更改時,這個URL被AvatarRepresentation元件剖析,以確定它是否代表:

簡單虛擬人偶

簡單虛擬人偶系統提供一個簡單且價格低廉的虛擬人偶模型。

嘴部動畫是基於音量偵測,並且沒有準確的唇型同步。

Ready Player Me

Ready Player Me虛擬人偶系統可以顯示https://readyplayer.me提供的任何虛擬人偶。

嘴部動畫提供唇型同步,其基於Oculus唇型同步庫,其在Oculus聲音SDK授權 (https://developer.oculus.com/licenses/audio-3.3/)下發布。

為了最佳化虛擬人偶的下載及載入,針對一個給定的虛擬人偶URL,虛擬人偶物件可以透過幾種方式來載入:

  • 如果這個URL已經針對一個啟用的虛擬人偶來使用,則複製現有的虛擬人偶
  • 如果這個URL與一個預製件相關聯,則繁衍預製件,而非下載及剖析glb檔案
  • 如果這些選項不相關,則下載及剖析glb檔案。請注意,一個URL可以描述在串流資產資料夾中的一個glb檔案,透過針對URL來使用語法%StreamingAssets%/Woman1.glb,以略過下載。如果您這麼做,您應該放置Ready Player Me提供的相關聯的Woman1.json中繼資料檔案在Woman1.glb旁邊(為了下載它,簡單地在Ready Player Me提供的原始URL中以.json替換.glb副檔名)。

LOD

在有大量的使用者(或機器人)的遊戲階段中,虛擬人偶可能給效能帶來很大負擔。

為了避免這個,虛擬人偶代表管理幾個LOD:

  • 常規虛擬人偶(簡單的虛擬人偶或Ready Player Me)
  • 一個簡單的虛擬人偶的低多邊形版本,附有匹配常規虛擬人偶的頭髮/皮膚/衣服顏色
  • 一個告示板總是面對使用者相機。

聊天氣泡

這個範例展示了聊天氣泡。場景包含4個靜態聊天氣泡。當2個使用者彼此靠近時,應用程式也可以建立一個動態聊天氣泡。

靜態聊天氣泡

static chat bubble

預設下,在expo場景中,使用者不會聽到彼此。

但是當他們進入相同的靜態聊天氣泡時,他們將能夠透過Photon Voice的空間化的聲音來一起討論。

zone system

在範例中,一個區系統追蹤NetworkRig靠近一個ZoneZoneUser元件。如果它發生,ZoneUser將進入區,並且觸發各種Zone ZoneUser接聽者。

一個Zone可以有一個與它們相關的PhotonVoice興趣團體,所以如果本機使用者進入/離開一個區,ZoneAudioInterestChanger元件可以更改本機使用者的聲音接聽及錄製群。如果本機使用者應該聽到聲音,它也啟用及停用一個使用者的裝置的聲音來源。

當靜態聊天氣泡中達到最大使用者數量時,將被自動地鎖住,但是可以透過觸碰在每個靜態聊天氣泡中的鎖定按鈕,在這之前鎖住它們。

動態聊天氣泡

代表使用者的預製件含有一個DynamicZoneSource元件。

dynamic zone system

這個元件註冊到一個DynamicZonePool元件,這樣之後它可以檢查另一個現有的DynamicZoneSource是否是近接,如同DynamicZonePool.size中所定義。在這個案例中,DynamicZonepool可以提供一個區,其被繁衍(或被重新使用)以讓兩個使用者來使用。

其他使用者稍後可以加入他們,直到達到區的最大容量

dynamic zone spawn

機器人

為了展示範例支援一個充滿人的Expo的方式,在常規使用者之外,可以建立機器人。

機器人是常規已連線預製件,其聲音已經被停用,而且其由一個導航網格所驅動,而非使用者輸入。

Bot類別也使用運動驗證系統,並且因此感知到聊天氣泡。在此之外,因為它們不會說話,它們被禁止進入任何區,不論該區是否鎖住。

繪畫

3D繪畫

Expo場景含有3D筆,其可以建立3D繪畫:一個線轉譯器的群,附有一個常見的手柄,其可以被拿取和移動。

3D筆持有一個Drawer元件,其繁衍一個持有Draw元件的繪畫預製件。Draw元件確保所有被繪製的點都透過Fusion被同步。它透過一個[Networked]變數來完成。因為它不能持有無限數量的點,因此如果需要,可以將繪畫分開為多個部分,當任何使用者移動它時,第二個Draw跟隨第一個Draw,使它顯示為一個單一繪畫。

2D繪畫

Expo場景中的白板可以使用其周圍的筆來書寫它,而且最終繪畫隨後可以透過一個類似於3D筆繪畫手柄的手柄,在白板上移動。

事實上,它是一種特殊的3D繪畫,其使用一個圖層相機不可見,但是與白板相關的相機可見的圖層。隨後相機在一個在白板上顯示的轉譯材質上轉譯繪畫圖片。

為了效能的考量,這個相機只在筆靠近使用中的白板時啟用,或是在移動使用筆建立的繪畫時啟用。

場景切換

玩家可以透過使用位於場景中的橋,來移動到一個新的世界。各個橋觸發一個特定的場景載入。

expo map

為了這樣做,各個橋有一個NewSceneLoader類別,其負責在玩家與方盒碰撞器碰撞時載入一個新的場景。 請注意,在載入新的場景之前,NewSceneLoader關機Runner,因為它不能在新的場景中被重新使用:各個場景有其自己的Runner

舉例而言,名為ExpoRoomMainWithBridge的主要場景有兩種橋。第一座橋將載入ExpoRoomNorth場景,而另一座橋將觸發ExpoRoomSecondScene載入。 所以現在關於玩家繁衍位置有三個可能性:

  • 當玩家最初加入遊戲時的靠近棕櫚樹的隨機位置,
  • 當玩家從ExpoRoomNorth場景返回時的第一座橋附近的位置,
  • 當玩家從ExpoRoomSecondScene場景返回時的第二座橋附近的位置。

為了確定正確的繁衍位置,在各個場景中需要一個SpawnManager。 它改變RandomizeStartPosition元件的預設行為,以定義當玩家從另一個場景回來時(或在重新連線的情況下)玩家應該出現的位置。

expo bridge

在處理多個場景時,需要記住的另一個點是,如果場景不相同,則不可以使用相同的房間名稱。 換句話說,各個場景的房間名稱必須不同。我們不靜態地設定這個名稱,而是使用Space元件(位於Runner上)以基於包含場景名稱在內的多個參數自動地設定一個房間名稱。

第三方元件

已知問題

  • 如果一個使用者連線的同時,一個繪畫的授權正在中斷連線,新的使用者將不會收到繪畫資料。

更改記錄

  • Fusion Expo 0.0.19

    • 新增新的場景及從一個場景切換到另一個場景的能力
    • 虛擬人偶選擇UI跟隨玩家的頭部位置
    • 玩家可以指定他的暱稱
    • 各種改進及修復問題
  • Fusion Expo 0.0.18

    • 當發生一個網路問題時,修復錯誤訊息顯示
  • Fusion Expo 0.0.17

    • 更新到Fusion SDK 1.1.3 F 組建 599
  • Fusion Expo 0.0.16

    • 使用VR共享技術範例中描述的核心VR執行方式
    • 使用VR共享本機裝置拿取範例中描述的本機拿取執行方式
    • 使用行業元件,與舞台範例共享
    • 移除XR互動工具組依賴性
Back to top