2024年05月21日

Agora SDKを使用したVision Pro Unity クイックスタート

Agora SDKを使用したVision Pro Unity クイックスタート

※この投稿は、Agoraの日本代理店であるブイキューブが、Agoraブログを翻訳した記事です。

 

新しいApple Vision Proヘッドセットは、パーソナルコンピューティングとエンターテイメントを再定義します。 
AppleネイティブのSwiftUIフレームワークまたはUnityエンジンを使用してイマーシブアプリケーションを開発できるため、可能性は無限大です。

FaceTimeのSharePlay機能を組み込むことで、同じアプリケーション内でAppleデバイス間でシームレスなビデオ チャットが可能になります。
しかし、他のプラットフォームのユーザーはどうなるでしょうか?
ここでAgora RTC SDKが活躍し、Vision Proヘッドセットでクロスプラットフォームのビデオチャットを可能にするソリューションを提供します。
この記事では、Vision Proヘッドセット用のUnityアプリケーションにクロスプラットフォームビデオチャットを実装するプロセスについて詳しく説明します。

前提条件

  • シリコン CPU (M1 以降) を搭載した Mac コンピューター
  • Xcode
  • Apple 開発者メンバーシップ
  • Unity 2022.3 LTS
  • Unity 開発者ライセンス — Pro/Plus/Enterprise
  • Agora 開発者アカウント
  • visionOS プラグインを含む Agora Video SDK

Part1:プロジェクトのセットアップ

3D URPテンプレートを使用してUnityプロジェクトを作成します。vision-pro-unity-quick-start-with-agora-sdk-1プロジェクトの準備ができたら、visionOSビルド設定に切り替えます。実際のVision Proデバイスにデプロイする前にシミュレーターでテストするため、ターゲットSDKとしてシミュレーターSDKを選択します。

vision-pro-unity-quick-start-with-agora-sdk-2

パッケージ マネージャーを開き、次のパッケージを名前で追加します。
  • com.unity.xr.visionos
  • com.unity.polyspatial
  • com.unity.polyspatial.visionos
  • com.unity.polyspatial.xr

Agora Video SDKをダウンロードします。この記事の執筆時点では、 プレビューバージョンにのみアクセスできます。
正式バージョンがリリースされたら、適切なダウンロード場所を記載してこの記事を更新します。
Unityエディターで、[アセット] > [パッケージのインポート] > [カスタム パッケージ] に移動してパッケージをインポートし、ダウンロードしたUnityパッケージを選択します。
vision-pro-unity-quick-start-with-agora-sdk-3

カメラとマイクにアクセスするので、使用説明を記入します。さらに、SDKは安全でないポインターを容易にするため、「安全でない」コードを許可します

vision-pro-unity-quick-start-with-agora-sdk-4

XRプラグイン管理に ApplevisionOSが選択されていることを確認してください。 World Sensingの使用法についても説明を入力してください。ハンドトラッキングを使用する場合は、必要に応じて、他の使用方法の説明を入力します。

vision-pro-unity-quick-start-with-agora-sdk-5

最後に、標準的な方法として、アプリの会社名を入力することもできます。

Part2: シーンを作成する

このデモプロジェクトは、GitHubにあります 。次のセクションでは、デモを作成する詳細な手順について説明します。

Mixed Realityエクスペリエンスを作成するには、UnityのPolySpatialパッケージが必要です。機能が有効になっていることを確認してください。

vision-pro-unity-quick-start-with-agora-sdk-6

ボリューム カメラが自動的に作成されない場合は  、[階層] ウィンドウで [+] ボタンをクリックし、[XR] > [セットアップ] > [ボリューム カメラ] を選択して追加できます。
このカメラは、必要なメイン カメラを置き換えるものではありません。

vision-pro-unity-quick-start-with-agora-sdk-7

次に、[XR] > [AR セッション] を選択して、ARセッションオブジェクトをシーンに追加します。
次に、「ボリューム」をクリックし、 「グローバル・ボリューム」を選択します。

オプション: Cubeという名前の3Dオブジェクトキューブを作成し、次の変換プロパティを与えます。この最小限のデモには他のUIがないため、このキューブは、VisionProデバイス上で正常に実行されているUnityアプリケーションの参照として見られます。

vision-pro-unity-quick-start-with-agora-sdk-8

オプション: 立方体の外観をより興味深いものにするには、次のようなスクリプトを使用して立方体を回転させ続けます。

public class SelfRotate : MonoBehaviour
{
  void Update()
  {
    // Rotate the object around its local Y axis at 10 degree per second
    transform.Rotate(10 * Vector3.up * Time.deltaTime);
  }
}

チェックポイント1

完成したシーンは次のようになります。

vision-pro-unity-quick-start-with-agora-sdk-9

Part3: AgoraVPManagerの設計

AgoraVPManagerは、SDK API-Examplesにある設計パターンに従っています 。

vision-pro-unity-quick-start-with-agora-sdk-10
AgoraVPManagerクラスは、RTCEngineのインスタンスを使用して、ビデオチャットセッションを実行するAPIを呼び出します。 ViewObjectsディクショナリは、ビューオブジェクトへの参照を保持します。
Agoraエンジンセッションのライフサイクルは、MonoBehaviorライフサイクル メソッド Start、Update、OnDestroy で それぞれ処理されます。

最上位クラスは、内部クラスUserEventHandlerを使用してコールバックイベントを処理します。

AgoraVPManagerスクリプトはSerializedFieldsを使用して 、開発者がアプリケーション認証に必要な資格情報 (アプリIDなど)、ユーザートークン、およびチャネル名を入力できるようにします。

public class SelfRotate : MonoBehaviour
#region EDITOR INPUTS
[Header(“_____________Basic Configuration_____________”)]
[FormerlySerializedAs(“APP_ID”)]
[SerializeField]
protected string _appID = “”;
[FormerlySerializedAs(“TOKEN”)]
[SerializeField]
protected string _token = “”;
[FormerlySerializedAs(“CHANNEL_NAME”)]
[SerializeField]
protected string _channelName = “”;
[SerializeField]
internal GameObject ViewContainerPrefab;
[SerializeField]
GameObject TargetObject; // to be looked at
#endregion

エディターの入力

次のスクリーンショットは、UnityエディターでのAgoraManagerのコンポーネントのインスペクタービューを示しています。
vision-pro-unity-quick-start-with-agora-sdk-11
AppIDとトークン
Unityエディターで、Agora開発者アカウントから作成したAppIDを入力します。実稼働コードでは認証にトークンを使用する必要があります。ただし、プロトタイプでは、トークンが不要なAppIDを使用する方が便利です。

チャンネル名
アプリケーションが同じAppIDとチャネル名を使用している限り、2 人のユーザーは異なるプラットフォーム上で相互に通信できます。たとえば、Vision Pro Unityユーザーは、デスクトップ Webブラウザ上のユーザーと会話できます。テストには「visionpro」を使用します。

コンテナプレハブの表示
これは、ビデオストリームをレンダリングするオブジェクトです。 Unity 3Dオブジェクト テンプレートの立方体を単純に使用します。キューブを作成してファイルパネルにドラッグするだけです。プレハブ名として MyCube という名前を付けます。 MyCube を [エディター] フィールドにドラッグします。

対象物
ビューオブジェクトをこの変換に直面させます。ボリュームカメラを参考にしてください。

開始
UI入力管理をさらに複雑にすることなく、アプリケーションはStart()時にビデオ チャット セッションを自動的に開始します。必要な3つの手順を次の順序で実行します。

  • InitEngine();
  • SetBasicConfiguration();
  • JoinChannel();

エンジンの初期化
InitEngine メソッドは、Agora RTCエンジンインスタンスを作成し、ユーザーハンドラーとエンジンをプロファイルで初期化します。

現在、RTC機能を適切に動作させるには、CHANNEL_PROFILE_LIVE_BROADCASTING および AUDIO_SCENARIO_GAME_STREAMING プロファイル オプションを使用する必要があります。

protected virtual void InitEngine()
{
  RtcEngine = Agora.Rtc.RtcEngine.CreateAgoraRtcEngine();
  UserEventHandler handler = new UserEventHandler(this);
  RtcEngineContext context = new RtcEngineContext(_appID, 0,
    CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING,
    AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING,
    AREA_CODE.AREA_CODE_GLOB);
  RtcEngine.Initialize(context);
  RtcEngine.InitEventHandler(handler);
}

基本構成の設定

ライブストリーミングRTCモードを使用するため、このセットアップでは各クライアントをブロードキャスターとして設定します。また、visionOSでオーディオストリームが正しく動作するようにする特別な調整も有効にします。

protected virtual void SetBasicConfiguration()
{
 RtcEngine.EnableAudio();
 RtcEngine.EnableVideo();
 VideoEncoderConfiguration config = new VideoEncoderConfiguration();
 config.dimensions = new VideoDimensions(640, 360);
 config.frameRate = 15;
 config.bitrate = 0;
 RtcEngine.SetVideoEncoderConfiguration(config);
 RtcEngine.SetChannelProfile(CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING);
 RtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);// For now this private API is needed to make voice chat working
 if (Application.platform == RuntimePlatform.VisionOS)
 {
   RtcEngine.SetParameters(“che.audio.restartWhenInterrupted”, true);
 }
}

チャンネルに参加する

チャネルへの参加には、顧客のユーザーID (uid) とメディア オプションを省略した最も単純なバリエーションを使用します。

RtcEngine.JoinChannel(_token, _channelName);

完全な関数シグネチャ:

int JoinChannel(string token, string channelId, uint uid,
ChannelMediaOptions options);

チャネルメディア オプションを使用すると、ビデオまたはオーディオストリームを公開せずにチャネルを設定できます。

 

破棄

セッションの終了時に、RTCエンジンの破destroy()メソッドを呼び出してリソースを適切にクリーンアップすることが重要です。

private void OnDestroy()
{
 if (RtcEngine == null) return;
 RtcEngine.InitEventHandler(null);
 RtcEngine.LeaveChannel();
 RtcEngine.Dispose();
}

アップデート

この設計では、ビデオディスプレイビューが指定された位置を向いています。カメラ (TargetObject に設定) は参照オブジェクトとして使用されます。

private void Update()
{
 foreach(var ob in ViewObjects.Values) {
   ob.transform.LookAt(TargetObject.transform);
 }
}

ユーザーイベントハンドラ

内部クラスUserEventHandlerには、AgoraRTCエンジンイベントに応答する一連のハンドラーメソッドが含まれています。イベントの完全なリストは、IRtcEngineEventHandlerインターフェイスで設定されます。ここでは、最も重要な4つのイベントのみに焦点を当てます。

 ・エラー時
 ・チャンネルに参加時
 ・ユーザー参加時
 ・オンユーザーオフライン

エラーが何を処理すべきかを理解するのは簡単です。残りの3つについてのみ説明します。

 

チャンネルに参加時

ローカルユーザーがチャネルに正常に参加すると、RtcConnectionへの参照がコールバックで提供されます。 
RtcConnection には、UIDとチャネル名が含まれています。以前は、デフォルト値0を使用してチャネルに参加しました。バックエンドシステムは、ユーザーを識別するための一意の UIDを生成します。指定されたUIDを使用して参加した場合、このコールバックには応答用に同じUIDが含まれます。この実装では、ユーティリティ関数を使用して、ユーザーのビデオストリームをレンダリングするビューを作成します。ローカルユーザーの場合、ストリームをレンダリングするために実際のUIDの代わりに常に0を使用する必要があります。

public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
{
 Vector3 pos = new Vector3(-2.5f, 0, 3.28f);
 CreateUserView(0, connection.channelId, pos);
}

ユーザー参加時

OnJoinChannelSuccessと同様に、OnUserJoinedはリモートユーザーのチャネル参加イベントを示します。レンダリングされたビュー変換の間にギャップを設けて、ユーザーを1人ずつ水平方向に追加します。

public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed)
{
 var count = _app.transform.childCount;
 Vector3 pos = new Vector3(count * 1.5f, 0, 3.28f);
 CreateUserView(uid, connection.channelId, pos);
}

オンユーザーオフライン

リモートユーザーがオフラインになると、そのビューがディスプレイからリモートに移動され、参照レコードがクリーンアップされます。

public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
{
 if (_app.ViewObjects.ContainsKey(uid)) _app.ViewObjects.Remove(uid);
 AgoraViewUtils.DestroyVideoView(uid);
}

ビューの作成

CreateUserView関数は、ユーティリティ関数AgoraViewUtils.MakeVideoView() を呼び出して、レンダリングビュー オブジェクトを取得し、変換階層の下に配置します。
これは完全に UI/UX デザイン次第です。
したがって、CreateUserViewはオーバーライドされる仮想関数として宣言されます。
ここで説明するより重要なことは、AgoraViewUtils.MakeVideoView()で表示するテクスチャ データを収集するためにSDKが提供するVideoSurfaceクラスを使用することです。 AgoraViewUtilsには、RawImage、Plane、または MeshRenderを備えたプレハブなど、いくつかのレンダリング ターゲットオプションが用意されています。 
レンダリングにはUnity 3Dテンプレートの立方体を使用します。この関数は最終的に MakeCustomMeshを呼び出します。

private static VideoSurface MakeCustomMesh(string goName, GameObject prefab)
{
 var go = GameObject.Instantiate(prefab);
 // configure videoSurface
 var videoSurface = go.AddComponent();
 go.transform.Rotate(-90.0f, 0.0f, 0.0f);
 return videoSurface;
}

チェックポイント2

これで、VisionProデバイスへの単純なRTCアプリの実装が完了しました。
アプリケーションはUnityエディターで実行できます。参照立方体の左側に自分自身のWeb カメラのキャプチャが表示されるはずです。

vision-pro-unity-quick-start-with-agora-sdk-12

Part4: テスト

ビジョンプロシミュレータ
Part1でシミュレータにターゲットSDKを設定したことを思い出してください。 UnityプロジェクトをビルドしてXcodeプロジェクトを取得します。次に、Xcodeプロジェクトをビルドします。

プレビューSDKの注意事項
Xcodeが重複シンボルの長いリストエラーを表示する場合、シミュレータのビルドに追加のターゲットが含まれていることが原因です。 XcodeプロジェクトからARM64フレームワークを削除します。

vision-pro-unity-quick-start-with-agora-sdk-13

シミュレーターテスト
VisionProシミュレーターでアプリケーションを構築して再生します。 Webブラウザを開いて、  Agora WebDemoページに移動します。テスト用のAppIDとチャネル名を入力します。

vision-pro-unity-quick-start-with-agora-sdk-14

Vision Proアプリがシミュレーターで正常に実行されると、次のスクリーンショットのようなものが表示されるはずです。シミュレータ設定には Vision Proのカメラキャプチャがないため、ローカルユーザーのディスプレイ用に設定された空の長方形のボックスが左側に表示されます。

vision-pro-unity-quick-start-with-agora-sdk-15

デバイステスト
ターゲットSDKをデバイスSDKに切り替えて、Unityプロジェクトを再度ビルドします。

vision-pro-unity-quick-start-with-agora-sdk-16

Xcode で、アプリケーションをビルドして Vision Proデバイスにデプロイします。

vision-pro-unity-quick-start-with-agora-sdk-17

RTCビデオ チャットにはローカル ユーザー (ペルソナ) とリモートユーザーの両方が表示されるはずです。

vision-pro-unity-quick-start-with-agora-sdk-18

vision-pro-unity-quick-start-with-agora-sdk-19

結論

結論として、UnityとVision Proのペルソナ表現を使用した没入型ビデオ チャットアプリケーションの可能性は、本当に刺激的です。それが提供するリアルな体験は、ユーザーのエンゲージメントを高めるだけでなく、有意義で楽しいコラボレーションのためのプラットフォームも提供します。これらのテクノロジーを採用するアプリケーションが増えるにつれ、革新的で魅力的なエクスペリエンスがすべての人に提供される未来が期待できます。

>Agoraの詳細をみる

リソース

ブイキューブ

執筆者ブイキューブ

Agoraの日本総代理店として、配信/通話SDKの提供だけでなく、導入支援から行い幅広いコミュニケーションサービスに携わっている。

関連記事

先頭へ戻る