20190728のUnityに関する記事は9件です。

UnityのAndroid実機ビルドでつまづいた話その2

前回までのあらすじ

UnityのAndroid実機ビルドでつまづいた話その1で一時的に動いたものの
また動かなくなった
前回うまくいったのはandroidの設定だと思っていたけど
どうやら違ったらしい

結論から言うとPC変えたらいけた

動作環境

Windows 10(前回と違いノートパソコン)
adb ver.1.0.39
Unity 2018.3~2018.4LTS
※2019はGradleが原因でビルドできなかった
Galaxy note 9 Android 9.0

Buildする前に

JDKとSDKのパスを確認
NDKは無くても問題ない

キャプチャ.PNG
Gradleをinternalに変更

Build And Runを実行

キャプチャ.PNG
Use Highest Installをクリック
※何故かUpdate Android SDKをクリックしても意味がない
このことについて詳細をご存知の方はコメントにて知らせていただけると助かります

Buildできなかった原因

十中八九AndroidStudioのバージョン上げたせい
それのせいでplatform-toolsのadbのバージョンが上がって
組み合わせの問題かadbのせいかはわからないけど
エラー吐いたんだと思われる
メインPCではADBを上手く構築できなかった
メインPCでビルドできたらまた記事書きます

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure Kinect SDK (v1.1.0) を使ってみた (導入 ~ Unity で使う)

はじめに

TMCN さん主催の Azure Kinect DK触ってみる会 に参加して Azure Kinect DK の実機に触ることができました。

会では実際に SDK を使って何か自作のコードを動かすことを目標にしていましたが、一応何か動かすことまではできたので、忘れないうちに記事にまとめました。当面さわる機会もなさそうですし・・・

実施環境

下記環境で試しました

  • Windows 10 (1903)
  • Visual Studio 2019 (16.2.0)
  • Unity 2019.1.11f1
  • Azure Kinect SDK v1.1.0

今回は Camera のみで Body Tracking は試していません。

準備

Azure Kinect SDK のバイナリをダウンロード、インストールします。

次に SDK のソースコードを GitHub から取得します。

次項でソースコードから SDK のビルドを行います。だったら SDK のバイナリをインストールする必要ないのでは?と思ってしまうところですが、インストーラーには非オープンソースの必須 .dll が含まれているため、インストールはしておく必要があります。もちろんインストーラーで入れれば各種ツール類が入りますので、これらでまず動作確認をするべきでしょう。

SDK をビルドする

いきなり Unity でやる、というのであれば本項は飛ばせますが、 Windows Forms / WPF 版のサンプルを試しておきたいところなので、まず SDK のビルドをお勧めします。

C SDK をビルドする

C# プロジェクト (src\csharp\K4a.sln) のビルドをする際、 C ネイティブ側のビルド済バイナリを要求されます。おそらくインストーラーのバイナリを適切に配置しても解消すると思いますが、適切な配置がよくわからなかったのでソースからビルドします。

C SDK は CMake でのビルドになっています。が、 Windows の場合は Visual Studio の CMake サポート機能を使う事で別途 CMake をインストールしなくても Visual Studio のみでビルドする事が可能です。

(Visual Studio Installer の "個別コンポーネント - コンパイラ、ビルドツール、およびランタイム" の中)
image.png

  1. Visual Studio 2019 を起動し、 "ローカルフォルダーを開く" を選択する
    image.png
  2. "Azure Kinect Sensor SDK" をチェックアウトしたフォルダーを選択します
  3. 少し待ちます
  4. 構成の種類が選べるようになったら "Win-x64-Release-Ninja" を選択します
    image.png
  5. ビルドします
  6. インストールした Azure Kinect SDK から "depthengine_1_0.dll" (C:\Program Files\Azure Kinect SDK v1.1.0\sdk\windows-desktop\amd64\release\bin\depthengine_1_0.dll) を "build\Win-x64-Release-Ninja\bin" にコピーします

"Win-x64-Release-Ninja" は C# Wrapper で参照している構成なのでここではビルド対象にしていますが、他の構成は必要に応じて適宜ビルドしてください。

C# Wrapper をビルドする

前項 "C++ SDK をビルドする" が完了していれば "src\csharp\K4a.sln" を開いてビルドすることができます。エラーは出ないはずです。

C# プロジェクトはコンパイル時にネイティブの DLL を参照することは原則ないので C++ ビルドがなくてもある程度はビルド通ります。が、それ以外の追加作業含めてビルドを通すようにするには C++ ビルドは必須です。

Unity で使う

Unity では SDK に含まれている C# Wrapper をそのまま Unity で使う事ができます。

今回、下記のような配置にしてみました。

  • Assets/K4A/Scripts ← SDK "src\csharp" 下の *.cs を丸ごとコピー
  • Assets/K4A/Plugins/x86_64 ← k4a.dll と depthengine_1_0.dll をコピー

image.png

コードを書きます。

using UnityEngine;
using KinectSensor = Microsoft.Azure.Kinect.Sensor;

public class KinectCapture : MonoBehaviour
{
    private KinectSensor.Device _device = null;

    private void Awake()
    {
        _device = KinectSensor.Device.Open();
        _device.StartCameras(new KinectSensor.DeviceConfiguration
        {
            ColorFormat = KinectSensor.ImageFormat.ColorBGRA32,
            ColorResolution = KinectSensor.ColorResolution.r720p,
            DepthMode = KinectSensor.DepthMode.NFOV_2x2Binned,
            SynchronizedImagesOnly = true,
        });
    }
}

実行をしてみると Device は取得できるのですが、 Device.StartCameras で失敗します。

これ、原因は "depthengine_1_0.dll がロードできない" ことでした。 depthengine_1_0.dll は k4a.dll からロードするので Unity のネイティブプラグインの DLL パスのルールではなく Windows のルールに従います。つまり Unity のルールに従った k4a.dll と同じ位置に配置してもロードされないわけです (ので depthengine_1_0.dll を置く意味はありませんでした) 。

面倒だったので、インストールした SDK のバイナリのフォルダ ("C:\Program Files\Azure Kinect SDK v1.1.0\sdk\windows-desktop\amd64\release\bin") にパスを通す事で解決しました。

あとは C# サンプルを参考にコードを書けば Unity 上でも動作させることができました。 API の数自体は少ないし、わかりやすいのでとりあえず動かすだけならそんなに難しくはなかったのですが、適切に動かすにはいろいろコツが必要なようです (というお話を伺った) 。

実装的にはカメラの Color と Depth をそれぞれ RenderTexture の ARGB32 と R16 に書き出し、 Shader 側でごにょごにょしてます。

Depth は Vertex Shader で値を見て Z 方向に動かすようにしているのですが、そもそも Kinect から取得する際の扱いが適切ではなかったようでうまく反映できませんでした (ペットボトルの形状は取れているようではあったのですが) 。この辺はもう少し時間があれば対処できたと思います。

おわりに

会で触れる時間は限られていましたが、事前準備を多少しておいたおかげで何もできずに終了、ということにはならずに済みました。

Unity でやってみた感想としては、一応 C# Wrapper を使えば基本的に Azure Kinect の機能を問題なく使えそうですが、 C# Wrapper が機能的には非常に低レベルな "C API ほぼそのまま" な定義なのにも関わらず、実装自体がよくわからない冗長な実装をしているように見えてあんまりよろしくない感じがしました。

ホロラボさんが独自に C# Wrapper を開発されているようですが、こちらの方がシンプルで無駄のない実装になっているようですので C# で開発をされる場合はこちらをベースにした方がよさそうです。

個人的には Unity で扱う場合、例えばカメラの映像をテクスチャに反映するといったところで実質ネイティブブラグイン不可避なので、最初から C# Wrapper は使わずに Kinect に対する処理はネイティブで書くようにしそうです。あるいはインプロセス実行にこだわらず、 Kinect 自体は別プロセスで実行するのも考えられそうです。

なんにせよ実機がないと何もできないので早いところ日本で普通に入手できるようになってほしいところです・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】コンポーネントのアタッチ時にデフォルト値を自動で設定する

環境

  • Unity 2019.1.12f1 (Unity 5系 のような古いバージョンでも大丈夫です)

デフォルト値の設定について

コンポーネントのデフォルト値を設定する際、私はインスペクタを開いて手動で設定していました。この操作、割と面倒ですしヒューマンエラーを起こします。
イラスト57.png

手間を減らせないかと探したところ、Reset() という関数が MonoBehaviour クラスには存在しているようです。

Reset() について

リファレンス
(古いバージョン (Unity 5.0) のリファレンスにも存在しています。)

Reset はインスペクターのコンテキストメニューにある Reset ボタンやコンポーネントを初めて追加するときに呼び出されます。 この関数はエディターモードのみで呼び出されます。Reset はインスペクターでデフォルト値を設定するときにもっともよく使用されます。

Reset()は、コンポーネントをアタッチするときに呼ばれる関数です。この関数内でデフォルト値を設定する処理を書けば、アタッチ時にデフォルト値が自動で設定されるわけです。

使い方

アタッチするコンポーネントに Reset() を定義します。関数内でデフォルト値を設定します。

HogeComponent.cs
using UnityEngine;
using UnityEngine.UI;

public class HogeComponent : MonoBehaviour
{
    [SerializeField] private Image image;
    [SerializeField] private Text text;

    void Reset()
    {
        if(!text){ text = GetComponentInChildren<Text>(); }
        text.text = "Hoge";
        if(!image){ image = GetComponentInChildren<Image>(); }
        image.color = Color.red;
    }
}

後はこのコンポーネントをアタッチするだけです。

s2.gif

上のように、アタッチした瞬間に参照をつけることが出来ました。
また、参照先のコンポーネントのパラメータの変更もできます。

なお、コンポーネントのアタッチ後に、そのコンポーネントの Reset() を定義しても、アタッチ済みのコンポーネントのデフォルト値は設定されません。
アタッチ済みのコンポーネントのデフォルト値を設定する場合は、右クリックメニューからResetを選択することで、Reset()が実行されます。

s3.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ROS を使って Unity の仮想車両をマイコンシミュレータで制御する

概要

ROS を使って Unity の仮想車両をマイコンシミュレータ上のプログラムで制御してみました.

自動運転制御系の開発で,車両制御をビジュアライズする手法としてはよくある感じなんですが,今回,TOPPERS の オープンソースを組み合わせて構築することに成功しましたのでご紹介します.

今回作成した構成は下図の通りで,青色のものが TOPPERS オープンソースです.残りは,ROS と Unity なので,いずれもフリーで利用可能です.

image.png

来週,京都で開かれるオープンソースカンファレンスの TOPPERS ブースにてデモ/説明しますので,ご興味のある方は是非お立ち寄りください.
★ここで作成した成果は,ETロボコンにも応用可能ですし,
★自分のノルマでもありますので,年内には一般公開します.
★乞うご期待ください!

以下,デモでお見せする内容をまとめます.

Unityの登場物

まず,Unity上の登場物は以下の通りです.

車両

今回作成した車両は下図のとおりで,見栄えはまだパッとしませんが,「走る」,「曲がる」,「止まる」は制御可能にしています.

image.png

ちなみに,この車両は以前,下記でご紹介したものを発展させたものです.

https://qiita.com/kanetugu2018/items/a6411ee86b2ed404031b

障害物センサ

車両の先頭部分には障害物センサを付けました.青色のキューブです(浮いてますが・・).
前方20m先の障害物を検出します.

image.png

ライントレースセンサ

将来的にETロボコンでも使えるようにライントレースセンサを付けました.
下図の通り,車両の下にカメラをつけてテクスチャの色を数値変換してセンシングしています.

image.png

仮想マイコン

車両にマイコンをアタッチしている感をわかりやすくするために,マイコンのテキスチャ付けました(単なる遊び心です^^;).

image.png

走行コース

シンプルに四角状の道路を作りました.

image.png

障害物

道路上にド~ンと壁を置きました.

image.png

あと,移動する邪魔者も置いてます.方向キーで自由自在に移動できます.

image.png

マイコンシミュレータの登場物

マイコンシミュレータ

マイコンシミュレータは,最近売り出し中の TOPPERS/athrill を使っています.TOPPERS の RTOS を動作させやすいです.athrillの紹介は下記記事を参照ください.

https://qiita.com/kanetugu2018/items/1f2ef93c9e1fa7a29f97

TOPPERS/RTOS

車両制御アプリケーションをマイコン上で動作させるためのリアルタイムOSとしては,TOPPERS/ASP を利用しています.

https://www.toppers.jp/asp-kernel.html

TOPPERS/mROS

マイコン上で ROS を利用するためのありがたいミドルウェアとしては,TOPPERS/mROS を利用しています.

※mROSについて詳しく知りたい方は,本家サイトを参照ください.
https://qiita.com/takasehideki/items/7d783ecd605dcee29ee0
https://qiita.com/m_ksg/items/0060a8738e6a34a0f237

センサ/アクチュエータ

センサ/アクチュエータ処理は,基本的には ROS トピックの出版/購読で実現しています.
トピック情報としては下図のような感じです.

image.png

vehicle_controller ノードが,車両制御指示用のトピックを出版しています.
vehicle_sensor ノードは,車両のセンサ情報を購読しています.

rosbridge_websocket が中間にいますが,Unity と マイコンシミュレータの間に rosbridge が存在しているためです.

車両制御

車両制御としては,まだあまり高度なことはやっていません.
シミュレーション実行時に直進開始させ,障害物検出したら一時停止させるくらいの制御です.
※将来的には MATLAB/Simulink で作成したコードを使ってみたいと考えています.

デモ

論より証拠,デモをお見せします.

mROS_unity_CAR2.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MirrorとLiteNetLib4Mirrorを使って、UnityでのNetwork Discoveryを行うメモ

はじめに

LiteNetLib4Mirrorとは、LiteNetLibという.NET用のUDPライブラリを、Unity用ネットワークライブラリMirrorのLow level networking transportとして使えるようにするものです。特に、Mirrorには無いNetwork DiscoveryuPnPをサポートしてくれるのが嬉しいので、その辺の話を中心にメモします。なお、原稿執筆時のLiteNetLib4Mirrorのバージョンは1.2.5です。

LiteNetLib4Mirrorの入手

こちらからUnityPackageをダウンロードして、自分のプロジェクトにインポートしてください。ただし、これにはサンプルシーンが含まれないので、初心者はこちらのレポジトリをクローンして試してみるのが良いと思います。使うUnityのバージョンはUnity 2018.3.6f1以降が推奨です(IL2CPPでのIPv6サポートの問題のため)。私は執筆時点でUnity2018.3.8f1を使ってます。

サンプルシーンから学ぶ

公式ドキュメントが少ないので、サンプルシーンを勉強してみましょう。

レポジトリをクローンしてプロジェクトを開くとAssetフォルダに"Scene"というシーンのファイルがあるので開いてください。Mirrorに付属のPongデモと同じようなシーンが開きます。

image.png

ただし、NetworkManagerゲームオブジェクトにアタッチされてるコンポーネントに、以下のような違いがあります。

LiteNetLib4MirrorTransport

MirrorのPongデモではTelepathy Transportがアタッチされてますが、こちらではLiteNetLib4MirrorTransportがアタッチされています。このコンポーネントはLiteNetLib4Mirrorを使う上で必須であり、必ずNetwork Managerと同じゲームオブジェクトにアタッチされている必要があります。

image.png

コンポーネントのパラメータについては、以下の参考資料が役に立つかもしれません。

127.0.0.1とlocalhostと0.0.0.0の違い
UPnPでNAT越え ~オンラインゲーム開発における課題~

LiteNetLib4MirrorDiscovery

Network Discoveryを行うためのコンポーネントです。On Discovery Responseを設定しておくことで、Hostが見つかった後の処理を行えます。

image.png

NetworkDiscoveryHUD

これがあると、シーンに"Start Discovery"というボタンが表示され、これをClient側で押すとHostを探し始めてくれます。

image.png

Network Manager

このコンポーネント自体はMirrorのPongデモにもありますが、Network Infoの"Transport"がLiteNetLib4MirrorTransportになっているのに注意してください。

image.png

ためしてみる

とりあえず、プロジェクトをビルドして試してください。ビルドしたアプリを二つ起動させて、一方をClient、一方をHostにしてみましょう。Host側で"LAN Host"、Client側で"Start Discovery"を押せば接続されてPongが始まります。
image.png

Network Discoveryの方法

サンプルシーンのNetworkDiscoveryHUD.csが参考になります。この中のOnGUIメソッドの中に、Discoveryを始めるか止めるかの処理があります。コード中の_noDiscoveringは、初期状態ではtrueです。

NetworkDiscoveryHUD.cs
//OnGUI内
if (!NetworkClient.isConnected && !NetworkServer.active){
    if (_noDiscovering){
        if (GUILayout.Button("Start Discovery")){
            StartCoroutine(StartDiscovery());
        }
    }
    else{
        GUILayout.Label("Discovering..");
        GUILayout.Label($"LocalPort: {LiteNetLib4MirrorTransport.Singleton.port}");
        if (GUILayout.Button("Stop Discovery")){
            _noDiscovering = true;
        }
    }
}
else{
    _noDiscovering = true;
}

"Start Discovery"ボタンを押すと、StartDiscoveryメソッドがコルーチンとして実行されます。

StartDiscoveryメソッドでは、LiteNetLib4MirrorDiscoveryコンポーネントのInitializeFinder()で初期化し、Singleton.onDiscoveryResponse.AddListenerでOnClientDiscoveryResponseをイベントハンドラとして登録した後に、LiteNetLib4MirrorDiscovery.SendDiscoveryRequestでリクエストを送信し続けます。

NetworkDiscoveryHUD.cs
private IEnumerator StartDiscovery()
{
    _noDiscovering = false;

    LiteNetLib4MirrorDiscovery.InitializeFinder();
    LiteNetLib4MirrorDiscovery.Singleton.onDiscoveryResponse.AddListener(OnClientDiscoveryResponse);
    while (!_noDiscovering)
    {
        LiteNetLib4MirrorDiscovery.SendDiscoveryRequest("NetworkManagerHUD");
        yield return new WaitForSeconds(discoveryInterval);
    }

    LiteNetLib4MirrorDiscovery.Singleton.onDiscoveryResponse.RemoveListener(OnClientDiscoveryResponse);
    LiteNetLib4MirrorDiscovery.StopDiscovery();
}

サンプルでは、LiteNetLib4MirrorDiscovery.SendDiscoveryRequestの引数として"NetworkManagerHUD"を与えてるのですが、他の文字列を与えても動作に影響しないです。理由は調査中です

(追記: shienaさんのコメントにあるとおり、与えた引数はホスト側のLiteNetLib4MirrorDiscoveryのProcessDiscoveryRequestに渡されるようです。ProcessDiscoveryRequestの中では渡された文字列を使わないので何を与えていても影響ないですが、LiteNetLib4MirrorDiscoveryを継承したクラスを作る場合、この文字列を使って処理を行うこともできます。)

いずれにせよDiscoveryが上手くいくと、登録したOnClientDiscoveryResponseにホストのIP Addressが渡されるので、Mirrorの通常の方法でクライアントを起動できます。

NetworkDiscoveryHUD.cs
private void OnClientDiscoveryResponse(IPEndPoint endpoint, string text)
{
    string ip = endpoint.Address.ToString();
    NetworkManager.singleton.networkAddress = ip;
    NetworkManager.singleton.maxConnections = 2;
    LiteNetLib4MirrorTransport.Singleton.clientAddress = ip;
    LiteNetLib4MirrorTransport.Singleton.port = (ushort)endpoint.Port;
    LiteNetLib4MirrorTransport.Singleton.maxConnections = 2;
    NetworkManager.singleton.StartClient();
    _noDiscovering = true;
}

おわりに

多分、もっと色々なことができるんだと思いますが、サンプルから理解できたのはこれくらいです。公式サンプルが追加されたら、こちらにも情報追加します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今更だけど Android Instant Apps を試してみた (unity)

前提

Android Instant Appsってなんだろう?

  • アプリのサブセットをインストールせずに「今すぐ試す」ものです。
    • ストアに「今すぐ試す」ボタンが付きます。
    • 有料アプリの無料体験版にできます。
    • 「Install版がストアにない状態」=「Instant版だけ」では使えません。
  • アプリ中にインストールボタンを付けられるので、インストールの導線になります。
  • 「アプリを起動するリンク」を作ることもできます。
    • Webアプリのような感じで使えます。
    • ただし、端末側で許可設定が必要です。

※あくまでも私の理解です。

準備

  • 基本的には、上記のGoogleの記事に従います。
  • play-instant-unity-plugin をプロジェクトに導入します。
  • android studio に Google Play Instant Development SDK を導入します。

できること

  • ビルド自体は、公式記事通りに進めれば、容易にできます。
    • サイズ制限がある以外に違いはありませんし、テストする分にはサイズ制限もありません。
    • PlayerSettings以外は、何も変えずともビルドできます。
  • InstantとInstallを切り替えてビルドできます。
    • PLAY_INSTANTというシンボルを使って、条件コンパイルできます。
  • InstantAppを(実/仮想)デバイスに送って起動できます。
  • コンソールへアップロード可能なInstant版APKが作れます。
  • 容量制限がありますが、InstantからInstallへデータを引き継げます。(CookieApi)
  • アプリサイズ制限をオーバーしていても、テストトラックで試すことはできます。

できないこと

  • InstantとInstallでPlayerSettingsを切り替えてくれません。
    • Instantでは、いくつかのPlayerSettingsが強制されます。
    • プロジェクトやブランチを別にするなどの工夫が必要です。
  • エディタ環境では、InstantからInstallへのデータ引き継ぎができません。
    • try {CookieApiで保存/取得} catch {PlayerPrefsで保存/取得}として、エディタ上でシミュレートしました。
  • Android App Bundleをサポートしていません。
    • もちろん、InstantとInstallの混成aabを作ることもできません。
    • これのせいで、サイズ制限を超えられませんでした。

留意点

  • サイズを減らすために、複数のPlayerSettingsに対して更新が提示されます。
    • いくつかは強制のようで、更新しないとビルドできません。
      • 更新しなくてもビルドできるものもありました。
    • 推奨通りに更新されたものを元に戻したい場合は、PlayerSettingsで個別に直すことになります。
    • ビルドタイプをInstallに切り替えても、元に戻りません。
      • InstallとInstantで設定を別にしたい場合は、プロジェクトやブランチを別にすることになるでしょう。
  • Install版は、Instant版より大きなビルド番号でなければなりません。
    • ツール側で混成aabがサポートされれば、同じビルド番号でも良いものと思われます。
  • InstantからInstallへのデータ引き継ぎ(CookieApi)には、容量制限があります。
    • 保存可能なサイズはCookieApi.GetInstantAppCookieMaxSizeBytes ()で取得可能です。
  • テスト機のGoogle設定で、「バックアップ」⇒「アプリのデータ」の「自動復元」を切っておきましょう。
    • インストール直後にデータが復活するので、データの引き継ぎが阻害されます。

結論

  • aabの生成がサポートされるまでは厳しいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PlayFabのUnitySDKのコールバック地獄の対応

PlayFabのUnitySDKは古いUnityにも対応するため、async/awaitではなくコールバックで結果を受け取ります。
C#SDKはasync/awaitなのですが、こちらはAndroid実機などでHttpClientを使おうとしてアプリがクラッシュします。
手っ取り早く解決するために、PlayFabClientAPIを解析して内部でUniTaskCompletionSourceを使ってUniTaskを返すWrapperメソッドの集まりを作りました。

// こんな感じでメソッド名を洗い出す
var validMethods = new List<(string methodName, string requestType, string resultType)>();
using (var stream = File.OpenText("PlayFabClientAPI.cs")))
{
    while (!stream.EndOfStream)
    {
        var row = stream.ReadLine();
        // public static void ***(***Request...)を探す
        if (row.Contains("public static void") && row.Contains("request") && row.Contains("resultCallback"))
        {
            var temp = row.Split(new[] { "void ", "(" }, StringSplitOptions.RemoveEmptyEntries);
            var methodName = temp[1];
            temp = temp[2].Split("request", StringSplitOptions.RemoveEmptyEntries);
            var requestType = temp[0];
            temp = temp[1].Split(new[] { " Action<", ">" }, StringSplitOptions.RemoveEmptyEntries);
            var resultType = temp[1];
            validMethods.Add((methodName, requestType, resultType));
        }
    }
}
// こんな感じでラッピングしたメソッドを書き出す
foreach (var (methodName, requestType, resultType) in validMethods)
{
    if (methodName.Contains("<"))
    {
        var temp = methodName.Split(new[] { "<", ">" }, StringSplitOptions.RemoveEmptyEntries);
        stringBuilder.AppendLine($"\t\tpublic static UniTask<{resultType}> {temp[0]}Async<{temp[1]}>({requestType} request, object customData = null, Dictionary<string, string> extraHeaders = null)");
    }
    else
    {
        stringBuilder.AppendLine($"\t\tpublic static UniTask<{resultType}> {methodName}Async({requestType} request, object customData = null, Dictionary<string, string> extraHeaders = null)");
    }
    stringBuilder.AppendLine("\t\t{");
    stringBuilder.AppendLine($"\t\t\treturn ToUniTask<{requestType}, {resultType}>({methodName}, request, customData, extraHeaders);");
    stringBuilder.AppendLine("\t\t}");
}

完成品

https://gist.github.com/yKimisaki/5a3d331a0c1db909d8e10c9ce079b25d

これで

var result = await PlayFabClientAPIAsync.LoginWithCustomIDAsync(new LoginWithCustomIDRequest()
{
    CustomId = "0",
    CreateAccount = true,
});

のような感じで結果を受け取ることができます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Oclus Questで「アップデート中」が出た場合の対処法

はじめに

Questのアプリ起動した時にこの画面が出たら・・・
IMG_4575.JPG

※お持ちのQuestは正常です! とりあえず待ちましょう!!

過去にOclus公式にてバージョンについての記事がありました
Oclus公式曰く、正常なこと
(Questは、Wifi接続で自動アップデートされるらしい)です。

待つ時の注意点

①Oclus本体の電源はONに。

②アップデート中は常時Wifi接続をする。

③OclusQuestを被らない。

(額センサーが触れているときはアップデートを一時中断してるみたい)

④念の為、Oclus公式ページにてアップデート情報を確認する。


以上のことに注意し、約4、5時間待ちましょう!!

私はこの方法でアップデートが終わってました(^ ^)

おわりに

私はQuestからVRデビューしたので、
「え、Questおかしくなったの?」と思いつつ、
Twitterでサーチしまくりましたが正誤判断できず...(T ^ T)カナシイ

同じ体験をされた方の力になれればと思い、本記事を書きました。
それでは、良いQuestライフを!!

参考にさせていただいたURL

Oculus Quest のソフトが「ダウンロード待ち」状態のままでインストールできない現象の解決策
Oclusサポートページ「クエストダウンロードキューの問題」
Oculusコミュニティフォーラム

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Oculus Questで「アップデート中」が出た場合の対処法

はじめに

Questのアプリ起動した時にこの画面が出たら・・・
IMG_4575.JPG

※お持ちのQuestは正常です! とりあえず待ちましょう!!

過去にOclus公式にてバージョンについての記事がありました
Oclus公式曰く、正常なこと
(Questは、Wifi接続で自動アップデートされるらしい)です。

待つ時の注意点

①Oculus本体の電源はONに。

②アップデート中は常時Wifi接続をする。

③OculusQuestを被らない。

(額センサーが触れているときはアップデートを一時中断してるみたい)

④念の為、Oclus公式ページにてアップデート情報を確認する。


以上のことに注意し、約4、5時間待ちましょう!!

私はこの方法でアップデートが終わってました(^ ^)

おわりに

私はQuestからVRデビューしたので、
「え、Questおかしくなったの?」と思いつつ、
Twitterでサーチしまくりましたが正誤判断できず...(T ^ T)カナシイ

同じ体験をされた方の力になれればと思い、本記事を書きました。
それでは、良いQuestライフを!!

参考にさせていただいたURL

Oculus Quest のソフトが「ダウンロード待ち」状態のままでインストールできない現象の解決策
Oculusサポートページ「クエストダウンロードキューの問題」
Oculusコミュニティフォーラム

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む