投稿日
Extreal 1.1.0をリリースしました!
開発基盤センターの伊藤です。
弱虫ペダルを見ていたらロードバイクを始めたくなりロードバイクを購入しました!最近太り気味なのでこれで痩せられそうです。
さて、3/28にExtreal 1.1.0をリリースしました。今回は1.1.0のリリース内容の中から注目機能を2つ紹介します。全てのリリース内容についてはReleaseページをご覧ください。
コンテンツ切り替え
バーチャル空間やアバター等の3Dモデルといったアセットをアプリケーションから外部化し、アプリケーションの実行時にアセットをダウンロードできるようにしたいケースがあります。1つのアプリケーションで様々なイベント向けのバーチャル空間を作るようなケースです。このようなケースではUnity標準のAddressablesという機能を使います。
開発当初はAddressablesを使ってサンプルアプリケーションHolidayにコンテンツ切り替えを実装しました。アバターやシーン等の3Dモデル、メッセージ、チャットとマルチプレイへの接続情報などのアプリケーション設定を切り替え可能にしました。この実装を通じてアプリケーションで共通する処理が見えてきたので、1.1.0ではAddressablesを使いやすくするラッパー機能の追加を決定しました。
Asset Workflow using Addressables
いくつか使用例を紹介します。ラッパー機能はAssetProviderクラスが提供します。
var assetProvider = new AssetProvider();
ダウンロード後にアセットをロードしてからステージ遷移させるなど、ダウンロード後の処理を指定できます。
// ダウンロード後の処理
Func<UniTask> navigate = async () =>
{
MessageConfig = await LoadAsync<MessageConfig>();
stageNavigator.ReplaceAsync(nextStage).Forget();
};
// ダウンロード後の処理を指定してダウンロード
assetProvider.DownloadAsync("AssetName", nextFunc: navigate).Forget();
ダウンロード状況表示など、ダウンロード状況に応じて処理を実行できるようにイベント通知を提供しています。
// ダウンロードを開始する直前
assetHelper.OnDownloading
.Subscribe(_ => loadingScreenView.SwitchVisibility(true))
.AddTo(sceneDisposables);
// ダウンロードした直後(途中経過も含む)
// ダウンロード状況としてトータルバイト数、ダウンロード済みバイト数、パーセントなどを受け取れます。
assetHelper.OnDownloaded
.Subscribe(loadingScreenView.SetDownloadStatus)
.AddTo(sceneDisposables);
C#ではリソース解放処理を行うIDisposableインタフェースが設けられています。一方、Addressablesでロードしたアセットのリソース解放にはAddressablesのReleaseメソッドを呼び出す必要があり、リソース解放処理の呼び出し方が異なります。ラッパー機能ではAddressablesでロードしたアセットのリソース解放処理をIDisposableインタフェースで提供しています。アプリケーション全体でリソース解放処理の仕組みを統一したい場合など、地味ですがとても重要な機能だと考えています。
// ロード結果としてIDisposableを実装したAssetDisposableが返る
// usingを使ってDisposeを呼び出すことが可能
using var assetDisposable = await assetProvider.LoadAssetAsync<GameObject>("AssetName");
// ロードしたアセットはResultから取得
var prefab = assetDisposable.Result;
このラッパー機能を使うことでUnity標準のAddressablesが使いやすくなるだけでなく、標準では提供されていないアセットの暗号化/復号を行うことも可能です。詳細についてはドキュメントをご覧ください。
ネットワーク切断時の再接続
マルチプレイやボイスチャットなど、いくつかの機能はネットワーク接続を前提としています。移動時などネットワーク接続が一次的に切断する場合に備えて、1.1.0ではネットワーク接続を前提とする機能に切断時の再接続機能を追加しました。
再接続機能のベースとなるリトライ処理は汎用的な機能として提供しており、例えばアプリケーションのAPI呼び出しに再接続処理を追加する場合にも使用できます。
リトライ処理の使用例です。リトライ処理は任意のメソッドに対して適用できます。詳細についてはドキュメントをご覧ください。
// 戻り値なしの同期処理:RunAction(value)メソッド
using var retryHandler = RetryHandler<Unit>.Of(() => RunAction(value), e => e is AccessViolationException, new CountingRetryStrategy());
await retryHandler.HandleAsync();
// 戻り値なしの非同期処理:RunActionAsync(value)メソッド
using var retryHandler = RetryHandler<Unit>.Of(() => RunActionAsync(value), e => e is AccessViolationException, new CountingRetryStrategy());
await retryHandler.HandleAsync();
// 戻り値ありの同期処理:RunFunc(value)メソッド
using var retryHandler = RetryHandler<Unit>.Of(() => RunFunc(value), e => e is AccessViolationException, new CountingRetryStrategy());
var result = await retryHandler.HandleAsync();
// 戻り値ありの非同期処理:RunFuncAsync(value)メソッド
using var retryHandler = RetryHandler<Unit>.Of(() => RunFuncAsync(value), e => e is AccessViolationException, new CountingRetryStrategy());
var result = await retryHandler.HandleAsync();
SLOC
最後にExtrealのSLOCについて紹介したいと思います。1.1.0でSLOCは次の通り変化しました。このSLOCはコメント行や空行を除いたステートメントのみの行数です。
1.1.0ではAssetWorkflowやCommonが新たに加わり、既存機能も少しずつ増加しています。体制は1.0.0から2名でずっと開発してきたので、急激に増加/減少するような動きはなく安定して増加しています。通常リリースを繰り返すたびにチーム力が高まり生産性が上がるはずですがあまり上がってないですね。社内で利用事例がないAddressablesの調査(特にカスタマイズ方法)と既存機能への影響調査が慣れてないため時間がかかっていたように思います。
まとめ
今回は1.1.0のコンテンツ切り替えとネットワーク切断時の再接続機能について紹介しました。今回紹介した以外にもDisposeパターンを適用しやすくする機能、ログ出力やチャット機能の改善など、いくつか変更を実施しています。ぜひReleaseページから変更内容をご確認ください。
今後も、人々が集まってコミュニケーションできるバーチャル空間の開発に有効な機能追加・変更を実施していきます。 新しく追加した機能をぜひご活用ください。