Meta Avatar
這個附加元件展示了以Fusion整合Meta虛擬人偶的方法。
主要關注點是:
- 使用Fusion已連網變數來同步虛擬人偶
- 以Fusion Voice整合唇形同步
Meta XR SDK
取代了在其他範例中使用的OpenXR外掛程式,這裡使用Oculus XR外掛程式。
已經透過其有限範圍登錄來新增Meta XR SDKhttps://npm.developer.oculus.com/(請參見Meta文檔以取得更多細節)。
來自Meta登錄的主要的已安裝套件是:
- Meta XR核心SDK
- Meta XR平台SDK:需要存取Oculus使用者ID並且載入Meta虛擬人偶。
Oculus裝備及組建方塊
基於Oculus XR外掛程式而非OpenXR外掛程式,已經建立一個特定的裝備來捕捉頭戴式裝置及手位置。
已經透過Meta組建方塊來建立這個硬體收集裝置:
- 這個步驟產生的預製件在
MetaOVRHandsSynchronization
附加元件的/Prefabs/Rig/BaseBuildingBlocks/[BuildingBlock] BaseRig
預製件中可用。 - 在
/Prefabs/HardwareRig/[BuildingBlock] HardwareRigForMetaAvatar
預製件中,提供了附加元件中實際使用的預製件,以及新增到前一個附加元件的同步元件。
MetaAvatar
遊戲物件將所有讓Meta虛擬人偶正常運作所需的元件都群組在一起。
LipSync
有OVRAvatarLipSyncContext
元件:由Oculus SDK提供它以設定唇形同步功能。BodyTracking
有SampleInputManager
元件:它來自Oculus SDK (Asset/Avatar2/Example/Common/Scripts
)。它是一個來自OvrAvatarInputManager
基礎類別的衍生類別,並且它參照到OVR Hardware Rig
以在一個虛擬人偶實體上設定追蹤輸入。AvatarManager
有OVRAvatarManager
元件:它用於載入Meta虛擬人偶。
運行器
ConnectionManager
位於Runner
遊戲物件上,其處理連線到Photon Fusion伺服器,並且在調用OnPlayerJoined
回調時生成使用者網路預製件。
為了透過網路串流語音,我們需要Fusion Voice Client
。主要錄音器欄位參照到位於Runner
之下的Recorder
遊戲物件。
如需更多關於Photon語音與Fusion的整合的細節,請參照這個頁面:語音 - Fusion整合。
Runner
遊戲物件也負責利用MetaAvatarMicrophoneAuthorization
元件來請求麥克風授權。當授予麥克風權限時,它啟用Recorder
物件。
子物件Recorder
負責連線到麥克風。它含有AudioLipSyncConnector
元件,其從Recorder
接收音訊串流並且轉傳它到OVRAvatarLipSyncContext
使用者生成的網路預製件
當調用OnPlayerJoined
回調時,ConnectionManager
生成使用者網路預製件NetworkRigWithOVRHandsMetaAvatar Variant
。
這個預製件含有:
MetaAvatarSync
:它負責在開始時選擇一個隨機的虛擬人偶,並且透過網路來串流虛擬人偶。NetworkedAvatarEntity
:它衍生自OculusOvrAvatarEntity
。它用於設置虛擬人偶實體,這取決於網路裝備是代表本機使用者或一個遠端使用者。
虛擬人偶同步
概述
MetaAvatarSync
類別處理虛擬人偶同步的協調。
利用它的ConfigureAsLocalAvatar()
方法,當針對本機使用者來生成使用者網路預製件時,關聯的NetworkAvatarEntity
從以下地方來接收資料:
OvrAvatarLipSyncContext
是針對唇形同步SampleInputManager
是針對身體追蹤
利用已連網變數,透過網路來串流資料。
當為了遠端使用者生成使用者網路預製件時,調用MetaAvatarSync
ConfigureAsRemoteAvatar()
,並且關聯的NetworkAvatarEntity
類別利用串流的資料來組建及製作虛擬人偶的動畫。
虛擬人偶模式
MetaAvatarSync
支援兩種模式:
- 使用者虛擬人偶:為了載入使用者的Meta虛擬人偶
- 隨機虛擬人偶:為了載入一個隨機Meta虛擬人偶
所以,當生成本機使用者已連網預製件時,根據這個設置來選擇了虛擬人偶,
C#
public override void Spawned()
{
base.Spawned();
if (Object.HasInputAuthority)
{
LoadLocalAvatar();
}
else
{
if (!avatarConfigured)
{
ConfigureAsRemoteAvatar();
}
}
changeDetector = GetChangeDetector(ChangeDetector.Source.SnapshotFrom);
// Trigger initial change if any
OnUserIdChanged();
ChangeAvatarIndex();
}
async void LoadLocalAvatar()
{
if (avatarMode == AvatarMode.UserAvatar)
{
// Make sure to download the user id
ConfigureAsLocalAvatar();
UserId = await avatarEntity.LoadUserAvatar();
}
else
{
ConfigureAsLocalAvatar();
AvatarIndex = UnityEngine.Random.Range(0, 31);
avatarEntity.LoadZipAvatar(AvatarIndex);
}
}
因為AvatarIndex
是一個已連網變數,在這個值更改時,透過更改偵測器將更新所有玩家。
C#
[Networked]
public int AvatarIndex { get; set; } = -1;
ChangeDetector changeDetector;
C#
public override void Render()
{
base.Render();
foreach (var changedPropertyName in changeDetector.DetectChanges(this))
{
if (changedPropertyName == nameof(UserId)) OnUserIdChanged();
...
}
}
虛擬人偶資料
在硬體裝備上的SampleInputManager
元件追蹤使用者的移動。
如果玩家網路裝備代表本機使用者,則由NetworkedAvatarEntity
參照它。
這個設定由MetaAvatarSync
(ConfigureAsLocalAvatar()
)完成。
在各個LateUpdate()
,MetaAvatarSync
針對本機玩家來捕捉虛擬人偶資料。
C#
private void LateUpdate()
{
// Local avatar has fully updated this frame and can send data to the network
if (Object.HasInputAuthority)
{
CaptureAvatarData();
}
}
CaptureLODAvatar
方法取得虛擬人偶實體串流緩衝,並且複製它到一個稱為AvatarData
的網路變數中。
容量被限制在1200,因為它在中等或高LOD中已足夠串流Meta虛擬人偶(針對一個實際的設置,這個數字應該匹配實際需要的資料數量,以避免浪費記憶體)。
請注意,為了簡化,在這個範例中只串流中等LOD。
也透過網路同步緩衝大小AvatarDataCount
。
C#
[Networked, Capacity(1200)]
public NetworkArray<byte> AvatarData { get; }
[Networked]
public uint AvatarDataCount { get; set; }
所以,當更新虛擬人偶串流緩衝,將告知遠端玩家並且在代表遠端玩家的網路裝備上應用已接收資料。
C#
public override void Render()
{
base.Render();
foreach (var changedPropertyName in changeDetector.DetectChanges(this))
{
...
if (changedPropertyName == nameof(AvatarData)) ApplyAvatarData();
}
}
載入已個人化的Meta虛擬人偶
載入本機使用者虛擬人偶
如同前面所見,為了載入使用者的Meta虛擬人偶,AvatarMode
必須被設定為AvatarMode.UserAvatar
。
所以在Spawned
回調期間,NetworkedAvatarEntity
以LoadUserAvatar()
來請求使用者的帳號虛擬人偶。
C#
/// <summary>
/// Load the user meta avatar based on its user id
/// Note: _deferLoading has to been set to true for this to be working
/// </summary>
public async Task<ulong> LoadUserAvatar()
{
// Initializes the OVR PLatform, then get the user id
await FinOculusUserId();
if(_userId != 0)
{
// Load the actual avatar
StartCoroutine(Retry_HasAvatarRequest());
}
else
{
Debug.LogError("Unable to find UserId.");
}
return _userId;
}
這個方法傳回Meta的帳號使用者ID,其儲存在UserId
[已連網]變數之中,這樣使用者ID將在所有客戶端上同步。
C#
[Networked]
public ulong UserId { get; set; } = 0;
請注意,為了能夠載入使用者虛擬人偶:
Defer Loading
應該在玩家的預製件的NetworkedAvatarEntity
元件上被設定為真:它將防止虛擬人偶在開始時被自動載入。
載入遠端使用者的虛擬人偶
在接收到UserId
時,遠端使用者將觸發與這個ID關聯的虛擬人偶的下載:
C#
public override void Render()
{
base.Render();
foreach (var changedPropertyName in changeDetector.DetectChanges(this))
{
if (changedPropertyName == nameof(UserId)) OnUserIdChanged();
...
}
}
void OnUserIdChanged()
{
if(Object.HasStateAuthority == false && UserId != 0)
{
Debug.Log("Loading remote avatar: "+UserId);
avatarEntity.LoadRemoteUserCdnAvatar(UserId);
}
}
存取Meta虛擬人偶
為了能夠載入Meta虛擬人偶,您必須在Oculus > Oculus Platform
Unity 設定選單中針對您的應用程式來新增App Id
。
這個App Id
可以在您的Meta儀表板上的API > App Id
欄位中找到。
同時,這個應用程式必須有一個已完成的Data use checkup
區段,有所需的User Id
、User profile
及Avatars
存取:
測試使用者的虛擬人偶
為了能夠在開發中看見與本機Meta帳號關聯的虛擬人偶,本機使用者帳號必須是與Oculus平台設定中提供的App Id
關聯的組織的成員。
為了在跨平台設定中(在一個Quest及一個桌面組建之間)看見您的虛擬人偶,您將需要群組您的Quest及Rift應用程式,如同在這個頁面上的Group App IDs Together
章節中所指定:針對Meta虛擬人偶SDK來設置應用程式
唇形同步
麥克風初始化由Photon Voice Recorder
完成。
設置在OVRHardwareRig
上的OvrAvatarLipSyncContext
為期待直接調用,以使用音訊緩衝來供給它。
一個類別掛鉤在記錄器音訊讀取,以轉傳它到OvrAvatarLipSyncContext
,如同下述。
Recorder
類別可以轉傳讀取音訊緩衝到執行IProcessor
介面的類別。
關於更多如何建立一個自訂音訊處理器的詳細資訊,請參照這個頁面:Photon語音 - 問與答。
為了在語音連線中註冊該處理器,在相同的遊戲物件上新增一個VoiceComponent
子類別AudioLipSyncConnector
為Recorder
。
這導致接收PhotonVoiceCreated
及PhotonVoiceRemoved
回調,允許新增一個後處理器到已連線語音。
已連線後處理器是一個AvatarAudioProcessor
,其執行IProcessor<float>
或IProcessor<short>
。
在一個玩家連線期間,MetaAvatarSync
元件搜尋位於Recorder
上的AudioLipSyncConnector
以設定這個處理器的lipSyncContext
欄位。
這樣做的話,每次Recorder
調用AvatarAudioProcessor Process
回調時,在OvrAvatarLipSyncContext
上以已接收的音訊緩衝來調用ProcessAudioSamples
,這確保在虛擬人偶模型上計算唇形同步。
這樣的話,當在MetaAvatarSync
的後期更新的期間以虛擬人偶實體上的RecordStreamData_AutoBuffer
完成捕捉時,將同時串流唇形同步及其他虛擬人偶身體資訊。
相依性
- Meta虛擬人偶2 SDK
- Meta XR核心SDK
- Meta XR平台SDK
- Photon語音SDK
- MetaOVR手同步附加元件
示範
可在Assets\Photon\FusionAddons\MetaAvatar\Demo\Scenes\
資料夾中找到一個示範場景。
下載
這個附加元件的最新版本被包含在附加元件專案之中
已支援拓撲
- 共享模式
更改記錄
- 版本2.0.0:第一個版本