20200319のUnityに関する記事は13件です。

アプリづくりを通して、感染症を考えてみた

コロナです。

最近、コロナウイルスがはやっていて、僕のアカウント名が危機にさらされています
そんな時に、けど「数値だけ見たら」インフルエンザや花粉が大ごとだなーとか考えていました

今来ている「東京」では、花粉症が結構多いと聞きました。
そこで、

花粉の情報を調べられるアプリを考えてみよう!?

・コロナウイルスほどじゃないですが、「空気」に関するお勉強を兼ねて、花粉を調べられるアプリを作ったら、今の時期いいのでは!?

・過去の業務実績にある「緯度と経度のプログラムデモ」として説明がしやすいと考えて

対象とした人

・花粉症に悩まされている人
・これから花粉の強い地域へ行く人

対象となる方のイメージイラスト

kafun_kusyami.png

*ゲームじゃない

本アプリの想定シナリオ

出かけるときの一シナリオを図形にしてみたのでご参照ください

Untitled Diagram (1).png

ここで大事な体験

・花粉情報っておまけだから、聞かないことが多い
・人は文字だけだと、苦痛なのでスルーする層がいる
 →画像やゲームに近い表現にすることで認識してもらおうという試み

技術構成

フロントツール Unity
天気情報取得元 https://lab.life-socket.jp/life_socket
モデリング Vroidで髪型を調整したり

実際に作ってみた

ビデオ(クリックすると、youtubeに飛びます)

ビデオが開けなかった場合に表示されるテキスト

アプリの操作内容

 1.地名をクリック
 2.クリックした地名に移動して、花粉情報を取得する
 3.取得した花粉情報を取得する
 4.花粉の強さは0~4で返ってくる
 5.かえってきた花粉の強さに応じて、アプリ内の空に花粉を発生させた

システムイメージ図

Untitled Diagram.png

*キャラクターが巨大化しているのは当時「無観客」が話題になっていたので、観客が多かったら巨大化するキャラクターを作ってみようと個人の趣味で実装していた演出です。

位置情報の設定方法(今回はコード内)

    // 都道府県ごとの地域情報
    LocationData[] locations = new LocationData[] {
        // 東京
        new LocationData( 35.6895f, 139.6917f),
        // 北海道
        new LocationData( 43.062f, 141.3543f),
        // 名古屋
        new LocationData(35.1814f, 136.9063f),
        // 神奈川
        new LocationData(35.4475f, 139.6423f),
        // 和歌山
        new LocationData( 34.2259f, 135.1675f),
        // 栃木
        new LocationData(36.5657f, 139.8835)

    };

今日改めて撮影を

今日お世話になっている会社で「花粉症」の話が出ているのでデプロイしたアプリを起動して、見てみました

ビデオ(クリックすると、youtubeに飛びます)

ビデオが開けなかった場合に表示されるテキスト

関東の花粉が紫色の濃い紫を表しているのを確認できました。

感想と宣伝

・位置情報+時間で変わる情報について、意外と覚えていて実装もすんなりできた

・ご興味のあるかたは交流してください

・業務機密があるため、サンプルの動画やデモ+NDA後に技術的な部分だけをお話をさせていただくようになります

こんなことに応用できます

・よく行く場所で花粉対策が必要な時期なのか
・旅行に行きたい場所の確認
・花粉症に弱いので家に出る前に知っておきたい

googlemapだと、以下の数値と差し替えて対応できます

東京駅の例

url

https://www.google.com/maps/place/%E6%9D%B1%E4%BA%AC%E9%A7%85/@35.6812362,139.7671248,17z/data=!3m1!4b1!4m5!3m4!1s0x60188bfbd89f700b:0x277c49ba34ed38!8m2!3d35.6812362!4d139.7671248

埋め込み方として以下の情報で場所を指定するようになっています

35.681をlat
139.767をlon

「〇〇に使えないかな」一部カスタマイズ等のご相談や雑談も待っています

イラストの参考元

https://www.irasutoya.com/2015/03/blog-post_94.html

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

OculusQuestでどこでもドアを実現してみる

はじめに

XR Interaction Toolkitと、Pocket Portal VRというアセットを使用して、OculusQuestでどこでもドアを実現してみました。

Pocket Portal VR
Pocket Portal VRのアセットのページです。Pocket Portal VRは、作者がサポートできない状態とのことで、オープンソース化されています。

XR Interaction Toolkitは、Unity上でPackage Manegerからインストールできます。
また、XR Interaction ToolkitのサンプルシーンはXR-Interaction-Toolkit-Examplesから入手できます。

開発環境

Unity 2019.3.2f1
XR Interaction Toolkit 0.9.3
Oculus XR Plugin 1.2.0
Pocket Portal VR 2.3

修正したところ

Portal.csのRenderMonoを以下のように書き換えました。

Portal.cs
    private void RenderMono(Camera camera) {
        Transform trackingSpace = xrRig.cameraGameObject.transform;
        var leftEye = trackingSpace.localPosition + new Vector3(-camera.stereoSeparation / 2f, 0f, 0f);
        var RightEye = trackingSpace.localPosition + new Vector3(camera.stereoSeparation / 2f, 0f, 0f);


        if (camera.stereoTargetEye == StereoTargetEyeMask.Both || camera.stereoTargetEye == StereoTargetEyeMask.Left)
        {
            Vector3 leftPosition = xrRig.transform.TransformPoint(leftEye);
            Quaternion leftRot = xrRig.transform.rotation * trackingSpace.localRotation;
            RenderPlane(renderCam, leftTexture, leftPosition, leftRot, camera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left));
            meshRenderer.material.SetTexture("_LeftTex", leftTexture);
        }

        if (camera.stereoTargetEye == StereoTargetEyeMask.Both || camera.stereoTargetEye == StereoTargetEyeMask.Right)
        {
            Vector3 rightPosition = xrRig.transform.TransformPoint(RightEye);
            Quaternion rightRot = xrRig.transform.rotation * trackingSpace.localRotation;
            RenderPlane(renderCam, rightTexture, rightPosition, rightRot, camera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right));
            meshRenderer.material.SetTexture("_RightTex", rightTexture);
        }
    }

上記コード中で使用しているxrRigは、XR Interaction ToolkitのXRRigをstart時に取得しておきます。

xrRig = GameObject.FindObjectOfType<XRRig>();

左右カメラ視差をつくるためのオフセット設定は、どこでもドア(ポータル)をUnity NativeのVRで実現してみるを参考にさせていただきました。

Oculus Integrationとの組み合わせについて

Oculus Integrationとの組み合わせで動作させる場合、サンプルシーンRiftOVRDemoを試してみたところ、特にコードを修正しなくでもビルドはできるのですが、OculusQuestで動かしたときに両目でポータルの見える位置がずれてしまい立体視できない状態でした。コード修正で立体視できる状態にできないか試してみたのですがうまくいきませんでした・・対応方法をご存じの方がいましたら教えていただけると嬉しいです。
(2020/3/22追記)
シェーダーで左右のテクスチャ切り替えを変にトグルさせている処理が有効になっており、Portal.cs中で設定している箇所を以下のように無効に設定することで対処できました。

//#if USES_OPEN_VR
//        Shader.SetGlobalInt("OpenVRRender", 1);
//#else
        Shader.SetGlobalInt("OpenVRRender", 0);
//#endif

その他、Portal.csのRenderOpenVRを以下のように書き換えました。

Portal.cs
    private void RenderOpenVR(Camera camera) {
#if USES_OPEN_VR
        Transform trackingSpace = rig.centerEyeAnchor.transform;
        var leftEye = trackingSpace.localPosition + new Vector3(-camera.stereoSeparation / 2f, 0f, 0f);
        var RightEye = trackingSpace.localPosition + new Vector3(camera.stereoSeparation / 2f, 0f, 0f);

        if (camera.stereoTargetEye == StereoTargetEyeMask.Both || camera.stereoTargetEye == StereoTargetEyeMask.Left)
        {
            Vector3 leftPosition = rig.transform.TransformPoint(leftEye);
            Quaternion leftRot = rig.transform.rotation * trackingSpace.localRotation;
            RenderPlane(renderCam, leftTexture, leftPosition, leftRot, camera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left));
            meshRenderer.material.SetTexture("_LeftTex", leftTexture);
        }

        if (camera.stereoTargetEye == StereoTargetEyeMask.Both || camera.stereoTargetEye == StereoTargetEyeMask.Right)
        {
            Vector3 rightPosition = rig.transform.TransformPoint(RightEye);
            Quaternion rightRot = rig.transform.rotation * trackingSpace.localRotation;
            RenderPlane(renderCam, rightTexture, rightPosition, rightRot, camera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right));
            meshRenderer.material.SetTexture("_RightTex", rightTexture);
        }
#endif
    }

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

UnityでiOS向けにビルドしたアプリにおいて、音声をバックグラウンド再生する備忘録(20200319)

目的

UnityでiOS向けにビルドしたアプリにおいて
アプリがバックグラウンドになっても音声を再生しつづけたい

ステップ

  • Unityスクリプト内 OnApplicationPause でバックグラウンド時に音声を再生する関数を実行
  • iOS用にunityからビルドし、 書き出されたxcode pjファイルを開く
  • Signing & capabilitiesでbackground modesを追加。Audio,Airplay~にチェックを入れる

  • UnityAppController.mmのstartUnity関数内ににaudioSessionを定義している箇所があるので、下記記述を追加する

[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

この記事を書いた理由

下記記事の内容を参考にしたが、
スレッドが長い上に古い情報が混ざっていて解決に時間がかかったため。
https://forum.unity.com/threads/how-do-i-get-the-audio-running-in-background-ios.319602/

備考 swiftで書くとき

extension AppDelegate {
    //background play(audio)
    func prepareBackgrounPlay(){
        let audioSession = AVAudioSession.sharedInstance()

        //background audio play
        do {
            try audioSession.setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default, options: [.mixWithOthers, .allowAirPlay])
            print("Playback OK")
            try audioSession.setActive(true)
            print("Session is Active")
        } catch {
            print(error)
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

1人でアプリを作る

はじめに

こんにちは。
今回から、『Unity』を使ってスクロールゲームを作っていきます。
企画から完成までの過程を日記感覚で記録していきます!

制作環境

macOS Mojave バージョン 10.14.6
Unity 2019.2.19f1

企画

「近未来の世界で、主人公は機械で...」という、妄想を膨らませながら、
イメージを紙にサラサラと書いていきます。
ステージ構成や、プレイしてもらう時間、ターゲットなどをじっくり考えました。

実際に書いたものが下記画像になります。(きたない...)
gameRough.jpgflow.jpg
まあ、見づらくても、自分が分かっていればいいと思います。
ただ、他の人に見せるなら綺麗にまとめた方がいいかもしれません...。
今回は、一人で作るので、このまま進めます。

イメージイラスト

世界観や、設定が決まったので、イメージイラストを書きます。
手が動くままに書きました。
イメージイラストを書いてから、世界観や設定を決めていってもいいかもしれません。
characterRough.jpg

まとめ

今回は、企画をかんがえました。
内容を、事細かに説明していないので短くなっちゃいました...。

次回は、ゲームの流れがわかる、簡易的なモックアップを作ります。

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

1人でアプリを作る【その1】

はじめに

こんにちは。
今回から、『Unity』を使ってスクロールゲームを作っていきます。
企画から完成までの過程を日記感覚で記録していきます!

制作環境

macOS Mojave バージョン 10.14.6
Unity 2019.2.19f1

企画

「近未来の世界で、主人公は機械で...」という、妄想を膨らませながら、
イメージを紙にサラサラと書いていきます。
ステージ構成や、プレイしてもらう時間、ターゲットなどをじっくり考えました。

実際に書いたものが下記画像になります。(きたない...)
gameRough.jpgflow.jpg
まあ、見づらくても、自分が分かっていればいいと思います。
ただ、他の人に見せるなら綺麗にまとめた方がいいかもしれません...。
今回は、一人で作るので、このまま進めます。

イメージイラスト

世界観や、設定が決まったので、イメージイラストを書きます。
手が動くままに書きました。
イメージイラストを書いてから、世界観や設定を決めていってもいいかもしれません。
characterRough.jpg

まとめ

今回は、企画をかんがえました。
内容を、事細かに説明していないので短くなっちゃいました...。

次回は、ゲームの流れがわかる、簡易的なモックアップを作ります。

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

【Unity】画像の外部読込時に、端に謎の線が出る際の対処法(スクリプト)

画像の外部読込時に、画像の端に謎の線が残る現象が起きました。
どうやら画像の逆端の部分が見えてしまっているようです。
インスペクターで設定を変更すればいいのですが、外部読込の場合スクリプトで設定を変更する必要があります。

スクリプトでTextureWrapModeをClampに設定する
filename.TextureWrapMode
image.sprite.texture.wrapMode = TextureWrapMode.Clamp;

下記記事を参考にしました。

参考記事:
Unityで画像の端に謎の線が出るときの対処法

下記の方法でも線が消える場合があるようです。
(→僕の場合はうっすーい線が残りました)

filename.UseSpriteMesh
image.useSpriteMesh = true;

参考記事:
【Unity】SpriteAtlasでパックしたスプライトをUIに使用したときに出るゴミの対処

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

【Unity】画像の外部読込時に、端に謎の線が出る際の対処法

画像の外部読込時に、画像の端に謎の線が残る現象が起きました。
どうやら画像の逆端の部分が見えてしまっているようです。
インスペクターで設定を変更すればいいのですが、外部読込の場合スクリプトで設定を変更する必要があります。

スクリプトでTextureWrapModeをClampに設定する
filename.TextureWrapMode
image.sprite.texture.wrapMode = TextureWrapMode.Clamp;

下記記事を参考にしました。

参考記事:
Unityで画像の端に謎の線が出るときの対処法

下記の方法でも線が消える場合があるようです。
(→僕の場合はうっすーい線が残りました)

filename.UseSpriteMesh
image.useSpriteMesh = true;

参考記事:
【Unity】SpriteAtlasでパックしたスプライトをUIに使用したときに出るゴミの対処

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

UnityちゃんとTHETAでMixedRealityな記念撮影を

はじめに

リコーのYuuki_Sです。
弊社ではRICOH THETAという全周囲360度撮れるカメラを出しています。
RICOH THETA VやTHETA Z1は、OSにAndroidを採用しており、Androidアプリを作る感覚でTHETAをカスタマイズすることもでき、そのカスタマイズ機能を「プラグイン」と呼んでいます。(詳細は本記事の末尾を参照)。


さて、THETAの様な全天球カメラは360度撮影できるのでVRとの相性が良いです。
撮影した全天球画像をHMDに入れれば、そのまま撮影した瞬間の空間にダイブするが如く見ることが出来ます。

ところで、VRというと3D CGのキャラクターを利用したコンテンツが多くあります。
共にVRと相性の良い全天球画像と3D CG、一見すると組み合わせ易そうですが、実はそうではありません。
全天球画像に3D CGのキャラクターを合成しようとすると、これが中々難しいです。

難しい理由は、画像に奥行き情報が存在していないため。
全天球画像はHMDで見ていると一見奥行きもあるように感じますが、あくまで画像は2次元情報でそれを球体に展開しているだけです。(世界地図と地球儀の関係)

残念ながら現状のTHETAには奥行きを検出する手段はありません。
ですが、プラグインやAPIを介することで他のデバイスの力を借りる事ができます。
今回は、奥行きを取得できるデバイスとしてHololensを利用し、好きな場所にキャラクターを配置しMixedRealityな記念撮影ができるアプリを作ってみました。

まずは、動作の様子と撮影結果をご覧ください。

撮影結果

Post from RICOH THETA. - Spherical Image - RICOH THETA

システム構成と仕組み

system_image.png
今回の欲しい空間の3D情報取得は、Hololensの基本機能であるSpatialMappingを利用します。
SpatialMappingは、Hololensのセンサで空間の奥行き取得し、下図の様に3Dのメッシュデータとして保存、利用するものです。

これにより、現実空間に整合してキャラクターを配置したり、位置関係による隠面消去(オクルージョン)表現が可能になります。
spatialmapping_example.jpg
UnityのHololensマニュアルより引用

そして、空間にCGキャラクターを配置した後、現実空間のTHETAに撮影トリガを飛ばし、
撮影画像を受信すると同時にHololens側でもTHETAの位置から見たCGキャラクターを含む仮想全天球画像を取得、それらを合成することで、CGキャラクターとの記念撮影が実現できます。
THETA.png

Hololens側の実装

開発はUnityを利用します。
細かな環境構築に関しては割愛しますが、SpatialMappingや入力まわりはMRTK(Microsoft Mixed Reality Toolkit)をインポートして使っています。

目的であるCGキャラクターとの記念撮影を実現するためには、
現実のTHETAと同じ位置関係でCGキャラクターが写った仮想の全天球画像を得る必要があります。

そのために、今回はTHETAの位置をHololens側のUIで指定する方法を用いました。
具体的には、Hololens側に仮想THETAを表示し、その位置を現実のTHETAに重ねるという力技です。
(ちなみに仮想THETAモデルは20分ぐらいかけてBlenderで作りました。)
THETA位置合わせ.png

これで、現実世界のTHETAの位置をHololensのSpatialMapping上で把握することが出来ましたので、
あとは撮影ボタンを押したらTHETAの位置から仮想全天球画像を取得する仕組みを作ります。

Unityでは、任意の位置からキューブマップという全方位が写った立方体テクスチャを得ることが出来ます。
これをTHETAの画像と同じequirectangularに変換すれば仮想全天球画像が得られます。
このアイディアを実装しようと調査した所、まさにそのものを公開されている方が居たので利用させて頂きました。
@mechamogeraさんのUnityでカメラのequirectangular画像を作成してみる

THETAとの通信

今回、THETAとの通信内容は、撮影トリガと撮影画像の受信のみです。
なので、THETAのAndroidプラグインではなくTHETA Web APIを利用しました。
THETA Web APIは他の機器からTHETAをリモート制御する時に利用でき、撮影に加え、THETA内のAPIサーバーにアクセスして撮影画像も受け取れます。
APIのやり取りに利用するJSONですが、UnityではJsonUtilityという便利な仕組みがあるので今回はそれを利用します。

撮影トリガとその後の画像取得は下記の通りです。一定の時間がかかるのでコルーチンによる非同期処理を行っています。

...
 IEnumerator StartThetaTask()
    {
        //撮影開始トリガ
        url = "http://192.168.1.1:80/osc/commands/execute";
        takepicObject.name = "camera.takePicture";
        settedJson = JsonUtility.ToJson(takepicObject);
        byte[] postData_takePic = System.Text.Encoding.UTF8.GetBytes(settedJson);
        var request_takePic = new UnityWebRequest(url, "POST");
        request_takePic.uploadHandler = (UploadHandler)new UploadHandlerRaw(postData_takePic);
        request_takePic.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request_takePic.SetRequestHeader("Content-Type", "application/json");
        yield return request_takePic.Send();

        //結果反映まで待つ
        yield return new WaitForSeconds(3);

        //確認
        url = "http://192.168.1.1:80/osc/checkForUpdates";
        checkUpdateObject.stateFingerprint = "FIG_0003";
        settedJson = JsonUtility.ToJson(checkUpdateObject);
        byte[] postData_checkUpdata = System.Text.Encoding.UTF8.GetBytes(settedJson);
        var request_chckUpdate = new UnityWebRequest(url, "POST");
        request_chckUpdate.uploadHandler = (UploadHandler)new UploadHandlerRaw(postData_checkUpdata);
        request_chckUpdate.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request_chckUpdate.SetRequestHeader("Content-Type", "application/json");
        yield return request_chckUpdate.Send();

        //撮影画像の取得
        url = "http://192.168.1.1:80/osc/state";
        var request_state = new UnityWebRequest(url, "POST");
        request_state.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request_state.SetRequestHeader("Content-Type", "application/json");
        yield return request_state.Send();
        //gettedObject = JsonUtility.FromJson<gettedState>(request_state.downloadHandler.text);
        int appear_http = request_state.downloadHandler.text.LastIndexOf("_latestFileUrl");
        int appear_JPG = request_state.downloadHandler.text.LastIndexOf(".JPG");
        DataURL = request_state.downloadHandler.text.Substring(appear_http + 17, appear_JPG - 13 - appear_http);

        url = DataURL;
        var request_download = new UnityWebRequest(url, "GET");
        request_download.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request_download.SetRequestHeader("Content-Type", "application/json");
        yield return request_download.Send();
        Debug.Log(request_download.responseCode);
        Debug.Log(request_download.error);
        string directorypath = "";

        //画像の保存
#if WINDOWS_UWP
        //HoloLens上での動作の場合、LocalAppData/AppName/LocalStateフォルダを参照する
        directorypath = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
#else
        // Unity上での動作の場合、Assets/StreamingAssetsフォルダを参照する
        directorypath = UnityEngine.Application.streamingAssetsPath;
#endif
        File.WriteAllBytes(directorypath + "/" + datetimeStr + "_RealEquirePIC" + ".JPG", request_download.downloadHandler.data);

        THETAPicTexture.LoadImage(request_download.downloadHandler.data);
        TargetMaterial_THETA.SetTexture("_MainTex", THETAPicTexture);
        TargetMaterial.SetTexture("_MainTex", THETAPicTexture);
    }

実際の動作

実際の撮影は以下の④ステップでおこないます。
それぞれの動作はボタンを押すことで操作できるUIにしました。
①現実のTHETAの位置を決め、その位置に仮想THETAを重なるように設置します。
設置.png

②キャラクターを配置します。
今回はせっかくUnityを使用しているのでUnityちゃん(© Unity Technologies Japan/UCL)を利用しました。
視線の先が先程の仮想THETAに自動で向く様にスクリプトを追加しています。
設置2.png

③撮影ボタンを押して撮影します。
すぐに撮影されるとHololensを操作している姿勢のまま撮れてしまうので、3秒セルフタイマーにしました。
設置3.png

④少し待つとTHETAから撮影画像が送られてきます。
その画像とアプリ内で取得した仮想全天球画像を重ねた画像がプレビュー表示され、同時にそれぞれが保存されます。
設置4.png

上記の4ステップで目的の記念撮影が出来ました!
SpatialMappingの奥行き情報によって、Unityちゃんの椅子に隠れた部分はちゃんと非表示になっているのが分かると思います。
完成.PNG

まとめ

今回は、CGのキャラクターと記念撮影できる全天球合成画像生成アプリを作ってみました。
現時点では、オクルージョンを中心とした配置の整合性のみ考慮していますが、せっかくTHETAの全天球画像を受け取っているので、それを利用して光源推定(Image-based lighting)をおこなうと、MixedRealityらしい溶け込んだCG表現になると思います。

また、今回はHololensを利用しましたが、Kinectに代表されるデプスセンサと組み合わせても(範囲は限定されますが)同様のことが出来ると思います。

RICOH THETAプラグインパートナープログラムについて

THETAプラグインをご存じない方はこちらをご覧ください。
パートナープログラムへの登録方法はこちらにもまとめてあります。
QiitaのRICOH THETAプラグイン開発者コミュニティ TOPページ「About」に便利な記事リンク集もあります。
興味を持たれた方はTwitterのフォローとTHETAプラグイン開発コミュニティ(Slack)への参加もよろしくおねがいします。

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

adbコマンドを使ったモンキーテストのやり方

モンキーテストとは

モンキーテストとは、機器やソフトウェア、システムのテスト手法の一つで、対象箇所や操作手順などを事前に定めず、実施者がその場の思いつきで操作してみる方式。開発者の意図などを一切考慮しないことを「猿に使わせてみたらどうなるか」に例えた名称である。
http://e-words.jp/w/モンキーテスト.html より引用

すなわち「猿のように画面も見ずに連打」すればいいわけです。
が、人力はちょっとツライですね。もちろんアプリ自体にそういうモードを用意してあげることもできますが、結構骨が折れます。

そんな貴方に朗報です、Androidにはこれを自動でやってくれる仕組みが既にあるんです!

コマンド

adb shell monkey -v -p パッケージ名 --throttle イベント間隔(ms) --pct-touch 100 回数

これで、指定したパッケージアプリが自動で起動し(先に起動しておいても良い)、指定したイベント間隔で指定回数ランダムで画面を連打してくれます。
(パッケージ名はUnityのProjectSetting→Player→OtherSettings→PackageNameで指定したものです)
image.png

このイベント間隔と回数をかけ合わせれば、終わる時間が分かるので、寝る前から次の日の朝まで、仮に10時間モンキーテストさせたい。

という場合は

10時間=600分=36000秒

なので、イベント間隔が100ms(=0.1秒)であれば、360000 を回数に指定すれば良いことになります。

<例>

adb shell monkey -v -p jp.com.MyApp --throttle 100 --pct-touch 100 3600000

注意

なお途中で辞めたくなってCtrl+Cで止めても、adbのshell上ではプロセスが動いてしまっているので、モンキーテストは止まりません。

止めるにはプロセスを指定してkillする必要があるため

adb shell kill $(pgrep monkey)

とやる必要があります。

また、例えばアプリに終了ボタンなんかがある場合はモンキーテストにより押されてしまい、終了してしまう可能性があります。
なので、そのあたりは先に無効化するなどの考慮が必要です。
(※間違っても課金が発生するような処理をそのままにしないように!)

準備

adbとは Android Debug Bridge からくる略称のツールで、Android実機とPCを接続しデバッグの補助をしてくれるものです。
これは AndroidSDK に含まれています。

コマンドプロンプトから adb とコマンドを打って、何かズラズラとadbのヘルプテキストが表示される場合は問題ありませんが、

>adb
'adb' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

こんな感じになってしまう方はadb.exeへのパスが通っていませんので、先にパスを通す必要があります。

自分でAndroidSDKを用意した方は AndroidSDKをインストールしたフォルダ\android-sdk\platform-tools なんですが、
Unityをインストールする際にAndroidSDKのインストールにチェック入れてついでにセットアップした場合は
[UnityHubで設定したUnityのインストール先]\Hub\Editor\[Unityのバージョン]\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools
と、少々奥深くに置いてあるはずです。

UnityHubで設定したUnityのインストール先

これをパスに設定、もしくはフルパスでadbコマンドを実行するようにしてください。

まとめ

このadbコマンドによるモンキーテストにより

  • 上記の意図しない操作による不具合を発見する

に加え、人間ではなかなか現実的でない

  • 24時間ゲームを起動し(遊び)続けても大丈夫か

というような、耐久テストも兼ねることができます。 (エイジングテストともいうかな?)
手元のアプリも公開する前にちょっと24時間ぐらい走らせてみたらどうでしょうか。
思わぬ進行不能バグ。 思わぬメモリリークが見つかるかもしれませんよ。

ではでは。

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

adbコマンドを使って実機で楽々モンキーテスト

モンキーテストとは

モンキーテストとは、機器やソフトウェア、システムのテスト手法の一つで、対象箇所や操作手順などを事前に定めず、実施者がその場の思いつきで操作してみる方式。開発者の意図などを一切考慮しないことを「猿に使わせてみたらどうなるか」に例えた名称である。
http://e-words.jp/w/モンキーテスト.html より引用

すなわち「猿のように画面も見ずに連打」すればいいわけです。
が、人力はちょっとツライですね。もちろんアプリ自体にそういうモードを用意してあげることもできますが、結構骨が折れます。

そんな貴方に朗報です、Androidにはこれを自動でやってくれる仕組みが既にあるんです!

コマンド

adb shell monkey -v -p パッケージ名 --throttle イベント間隔(ms) --pct-touch 100 回数

これで、指定したパッケージアプリが自動で起動し(先に起動しておいても良い)、指定したイベント間隔で指定回数ランダムで画面を連打してくれます。
(パッケージ名はUnityのProjectSetting→Player→OtherSettings→PackageNameで指定したものです)
image.png

このイベント間隔と回数をかけ合わせれば、終わる時間が分かるので、寝る前から次の日の朝まで、仮に10時間モンキーテストさせたい。

という場合は

10時間=600分=36000秒

なので、イベント間隔が100ms(=0.1秒)であれば、360000 を回数に指定すれば良いことになります。

<例>

adb shell monkey -v -p jp.com.MyApp --throttle 100 --pct-touch 100 3600000

注意

なお途中で辞めたくなってCtrl+Cで止めても、adbのshell上ではプロセスが動いてしまっているので、モンキーテストは止まりません。

止めるにはプロセスを指定してkillする必要があるため

adb shell kill $(pgrep monkey)

とやる必要があります。

また、例えばアプリに終了ボタンなんかがある場合はモンキーテストにより押されてしまい、終了してしまう可能性があります。
なので、そのあたりは先に無効化するなどの考慮が必要です。
(※間違っても課金が発生するような処理をそのままにしないように!)

準備

adbとは Android Debug Bridge からくる略称のツールで、Android実機とPCを接続しデバッグの補助をしてくれるものです。
これは AndroidSDK に含まれています。

コマンドプロンプトから adb とコマンドを打って、何かズラズラとadbのヘルプテキストが表示される場合は問題ありませんが、

>adb
'adb' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

こんな感じになってしまう方はadb.exeへのパスが通っていませんので、先にパスを通す必要があります。

自分でAndroidSDKを用意した方は AndroidSDKをインストールしたフォルダ\android-sdk\platform-tools なんですが、
Unityをインストールする際にAndroidSDKのインストールにチェック入れてついでにセットアップした場合は
[UnityHubで設定したUnityのインストール先]\Hub\Editor\[Unityのバージョン]\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools
と、少々奥深くに置いてあるはずです。

UnityHubで設定したUnityのインストール先

これをパスに設定、もしくはフルパスでadbコマンドを実行するようにしてください。

まとめ

このadbコマンドによるモンキーテストにより

  • 上記の意図しない操作による不具合を発見する

に加え、人間ではなかなか現実的でない

  • 24時間ゲームを起動し(遊び)続けても大丈夫か

というような、耐久テストも兼ねることができます。 (エイジングテストともいうかな?)
手元のアプリも公開する前にちょっと24時間ぐらい走らせてみたらどうでしょうか。
思わぬ進行不能バグ。 思わぬメモリリークが見つかるかもしれませんよ。

ではでは。

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

【Unity】Riderで1行<summary>を挿入するためのキーマクロとショートカットを割り当てる

はじめに

RiderでXML Documentを書く時、クラスやメソッド定義の上の行で///と入力すると下記のようなテンプレートを挿入してくれると思います。

/// <summary>
/// ここにテキストを書く
/// </summary>
public void Hoge() 
{
    // TODO: Implement
}

この機能は大変便利なのですが、僕は下記のように書きたい場合があります。

/// <summary> ここにテキストを書く </summary>
public void Hoge() 
{
    // TODO: Implement
}

今回はこれをキーマクロとショートカットで簡単に実現するための方法を紹介します。

参考

こちらの記事にある方法を、画像付きで紹介している形になります。

neue cc - どう書く。ドキュメントコメント。

Riderで1行summaryをショートカットで挿入する方法

環境

  • macOSX Catalina 10.15.3
  • Rider 2019.2.4 (有償版)

マクロの作成

始めにキーボード操作をマクロとして記録します。

参考: マクロ - 公式ヘルプ | JetBrains Rider

[Edit]->[Macros]->[Start Macro Recording] で記録を開始し、エディタ上で1行summaryを次のように入力します。

記録されるのはキーボード操作のみで、マウス操作は含まれないことに注意してください。また、使いやすさを考えた場合、最終的なカーソルの位置がドキュメントコメントの開始位置にくるようにすると良さそうです。

fdsfasdfads.gif

実際に記録された操作は次のようになります。

スクリーンショット 2020-03-19 6.44.16.png

EditorBackSpace:
EditorRightWithSelection: ⇧+←

入力が終わったら[Edit]->[Macros]->[Stop Macro Recording]で記録を終了します。任意の名前を付けて保存してください。(e.g.Add single line summary)

正しく記録できたか確認します。エディタ上で空行にカーソルを合わせた状態で、[Edit]->[Macros]->[任意の名前]を選択してください。

Mar-19-2020 06-58-58 (1).gif

次のように正しく再生されれば完了です。

ショートカットの割当

次の先ほど作成したマクロにショートカットを割り当てて行きます。⌘+,で設定画面を開き、Keymapを選択します。

スクリーンショット 2020-03-19 7.02.33.png

Macrosというフォルダの中に、先ほど作成したマクロが追加されていると思います。項目をダブルクリックし、Add keyboard Shotcutを選択します。

スクリーンショット 2020-03-19 7.03.40.png

この状態で割り当てたいキーの組み合わせを入力します。被ってしまった場合はこのように警告をしてくれるので、重複しない組み合わせを探しましょう。私は⌘+⌥+Iにしました。

大丈夫そうならOKを押し、設定ウィンドウのSaveをクリックします。

先ほどと同様にエディタ上で割り当てたショートカットを入力し、正しく再生されたら完了です。

補足

XML Docmentの設定は[Preferences]->[Editor]->[Code Style]->[C#][XML Documentation]タブにあります。中のテキストの前後にスペースを含めたい場合などはここから設定が必要です (Spaces after start-tag and before end-tag otherwise)

スクリーンショット 2020-03-19 7.08.17.png

また、設定の共有機能でキーマクロは共有されない点に注意してください。

最後に

キーマクロはじめて使ったけど楽しそうな機能なので活用していきたいです。

よかったらTwitter(@nkjzm)のフォローや「LGTM」よろしくお願いします!

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

GameServerServicesで魔法石を実装するv2

https://github.com/gs2io/gs2-sample/tree/master/unity/money

のほぼ丸パクリです。

リファレンス読んでも全然実装の仕方わからんやんけ!って萎えてしばらくなやんでいたらサンプル落ちてるやん!みたいになってしまったので置いておきます。課金を実装する手段を検討するときにでも参照してください。

  1. ダウンロードしてUnityプロジェクトを開く
  2. とりあえずデータベース変えるかと言われたのでYesを選択した後、手元で最新のUnityでよみこんだらいっぱいエラーが出ます image.png
  3. プロジェクトを開きなおしたりIn-app Purchasingを有効にしたりとかいろいろしてエラーを取ります(importが裏で走るみたいな罠にご注意)
  4. GS2Consoleを立ち上げてDeployに移動します image.png
  5. テンプレートを読み込ませてリソースを作成します。 image.png

そうするとこのようなアウトプットが出力されます。
スクリーンショット (129).png

  1. サンプルプロジェクトのRunシーンを開きアウトプットの出力を入れます(普通にコピペすると最後に空白が入ってバグるので注意)
    image.png

  2. Scene起動
    image.png

  3. アカウント作成(ボタン押すだけ)
    image.png

  4. ログイン(Loginをクリック)
    image.png

  5. なんか出てくる
    image.png

  6. ここで+をおしたら商品一覧が~

image.png

_人人人人人_
> 出ない <
 ̄Y^Y^Y^Y^Y^ ̄

ごちゃごちゃやると……(長いので割愛)

image.png

でてきた!(スクショの順番待ちがえてGemsがふえてます)

image.png

無事Gemsも増えています。

このバグはサンプルでのバグであり、sdkやサービスの問題ではありません。Prefabがスクリプトで子オブジェクトに参照を持つときに、その子オブジェクトがPrefab化されていないと動かないという問題で動きません。手っ取り早く試したい方はこちらを試してください
https://github.com/piffett/gs2-sample

マージされたのでいまはちゃんと動くと思います

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

【Unity】3D Game Kitのアセットをインポートしたらエラーが出た場合の対処法

現象

Unityの公式の「3D Game Kit」という3Dアクションゲームのテンプレートアセットがあるのですが、こちらをインポートしたところ以下のようなエラーが出ました。

Library\PackageCache\com.unity.timeline@1.2.6\Runtime\Utilities\AnimatorBindingCache.cs(91,40): error CS0117: 'AnimationMode' does not contain a definition for 'GetCurveBindings'

この解決法を調べたところいくつか解決策を載せてくれているのですが、私のバージョンでは上手くいかなかったので、自分のバージョンでの解決策を載せておきます。

環境

Unity : 2019.3.0a5
3D Game Kit : 1.9
OS : Windows10

解決策

このエラーはUnityのパッケージの最新バージョンにこのアセットが対応していないことによるエラーなので、パッケージのバージョンを前のバージョンに戻すことで解決できます。

  1. 上のメニューから Window > Package Manager を開きます。
  2. 検索欄にTimelineと入力してTimelineのパッケージを探します。
  3. 左の三角アイコンをクリックして利用可能なバージョンを出します。
  4. 以前のバージョンを選択して右下のUpdateを押します。

この記事を書いたときは1.2.10から1.1.0にダウングレードしました。
image.png

すると最初のエラーは消えるはずです。

しかし今度は以下のようなエラーがでます。

Library\PackageCache\com.unity.ide.rider@1.1.4\Rider\Editor\RiderScriptEditor.cs(385,65): error CS0117: 'AssetDatabaseExperimental' does not contain a definition for 'IsAssetImportWorkerProcess'

同様の手順で、「Rider Editor」をパッケージマネージャーで検索してverifiedバージョンにupdateします。

最後に「ProBuilder」も同様の手順でupdateします。

Library\PackageCache\com.unity.probuilder@4.2.3\Editor\EditorCore\ShapeEditor.cs(186,37): error CS0117: 'ActiveEditorTracker' does not contain a definition for 'RebuildAllIfNecessary'

これでサンプルシーンから実行ができるようになりました!

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