Oculus Platform APIをコールバックからTaskへ変換する
はじめに
Oculus Storeからアプリを配布する時はOculus Platform APIが必須になっています。
そのOculus Platform APIは結果をコールバックで返すので処理が冗長になってしまいますが簡単にTask化できたので紹介します。
開発環境
- System.Threading.Tasksを扱える設定およびバージョンのUnity
- Unity2017 + Experimental (.NET 4.6 Equivalent)
- Unity2018 + .NET 4.x Equivalent
- Unity2019以上
- Oculus Integration v1.41.0以上
コールバックの場合
- Unity2017 + Experimental (.NET 4.6 Equivalent)
- Unity2018 + .NET 4.x Equivalent
- Unity2019以上
以下はエンタイトルメントチェックのベストプラクティスのサンプルコードです。Oculus Platform APIはIsUserEntitledToApplication()
のようにOnComplete()
で結果が返ってくるので同様の呼び出しが続くとコールバック地獄になって処理の流れが分かりにくくなります。
using UnityEngine;
using Oculus.Platform;
public class AppEntitlementCheck: MonoBehaviour {
void Awake ()
{
try
{
Core.AsyncInitialize();
Entitlements.IsUserEntitledToApplication().OnComplete(EntitlementCallback); // ここがコールバック
}
catch(UnityException e)
{
Debug.LogError("Platform failed to initialize due to exception.");
Debug.LogException(e);
// Immediately quit the application.
UnityEngine.Application.Quit();
}
}
void EntitlementCallback (Message msg)
{
if (msg.IsError)
{
Debug.LogError("You are NOT entitled to use this app.");
UnityEngine.Application.Quit();
}
else
{
Debug.Log("You are entitled to use this app.");
}
}
}
Taskへ変換する
スクリプティング定義シンボルにOVR_PLATFORM_ASYNC_MESSAGES
を追加します。
するとTaskを返すGen()
メソッドがOculus.Platform.Request
クラスで使えるようになるので以下のように書く事ができます。
private async void Awake()
{
try
{
if (!Core.Initialized())
{
var initialized = await Core.AsyncInitialize().Gen(); // ここをTask化
if (initialized.IsError)
{
Debug.Log($"failed initialize: {initialized.GetError().Message}");
return;
}
}
var entitlements = await Entitlements.IsUserEntitledToApplication().Gen(); // ここをTask化
if (entitlements.IsError)
{
Debug.Log($"failed entitlement: {entitlements.GetError().Message}");
return;
}
var user = await Users.GetLoggedInUser().Gen(); // ここをTask化
if (user.IsError)
{
Debug.Log($"failed get user: {user.GetError().Message}");
return;
}
Debug.Log($"{user.Data.ID}, {user.Data.OculusID}");
}
catch (UnityException e)
{
Debug.LogException(e);
Application.Quit();
}
}
更にUniTaskと組み合わせるとタイムアウトも簡単に扱えます。
var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(10));
try
{
var initialized = await Core.AsyncInitialize().Gen().AsUniTask().AttachExternalCancellation(cts.Token);
}
catch (OperationCanceledException e)
{
if (ex.CancellationToken == cts.Token)
{
Debug.Log("Timeout");
}
}
1つ残念なのはGen()
が返すTask
はTaskCompletionSource
で作られてprivateフィールドにあるのですがTrySetCanceled()
を呼ぶメソッドが用意されていないのでCancellationToken
でキャンセルできない事です。そのため、UniTaskのタイムアウトなどと組み合わせるなどの工夫が必要です。
参考
Author And Source
この問題について(Oculus Platform APIをコールバックからTaskへ変換する), 我々は、より多くの情報をここで見つけました https://qiita.com/shiena/items/a9a0d1667540d052dcd1著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .