のしメモ アプリ開発ブログ

Unityアプリとかロボットとか作ってるときに困ったこととかメモ

HoloLensアプリ「ENGLISH BIRD」をリリースするまで

ENGLISH BIRDというHoloLensアプリをつくってリリースしてみました。
HoloLensと「ENGLISH BIRD」を使って、英語の発音を楽しみながら身につけることができます。

ということで無事にWindowsStoreに載ったので、「ENGLISH BIRD」をリリースするまでの簡単な時系列をメモ。(時間は割とざっくりです)

日付 出来事
2/6 5時 申請(1回目)
2/6 5時 審査落ち(DLLが原因)
2/6 12時 申請(2回目)
2/7 10時 審査通過
2/7 20時? ストアに掲載
2/16 朝頃 HoloLensアプリのリスト入り(リスト入りは5~7営業日かかる)

2/16 追記: 現状はSTOREに新着順で表示してくれているみたいです。

申請について

HoloLensアプリのWindowsStoreリリースはこちらを参考にしました。
WindowsストアにHoloLensアプリをリリースする手順まとめ | develog.holo

審査落ちの原因

エラーの内容はこちら

AudioPluginMsHRTF.dll has failed the AppContainerCheck check

AudioPluginMsHRTF.dllで怒られています。

対処法

Unity5.5で空間音響がおかしくなっているらしく、5.5.0p3のパッチがでて修正されていますが、なんと5.5.1f1で復活しているみたいです。
Unityを5.5.0p3にすれば直るかもしれませんが、自分の場合は、[Project Settings] -> [Audio] -> [Spatializer Plugin]の項目を[MS HRTF Spatializer]から[None]に変更することで対応しました。
なのでとりあえずは立体音響ではなくステレオ音響になってしまっていますが、Unityの対応待ちですね。

HoloLensにビルド時にエラー

Unityで生成したプロジェクトをHoloLensの実機にビルドする際に下記のエラーがでました。

DEP6701 : Bootstrapping failed with unexpected error: 'Wrong format: Unrecognized date-time format.'

う~ん。よくわからん!

対処法

とりあえずVisualStudioを更新してみることに。

Visual Studio 2015 Update 3をインストーラーをダウンロードしてきて更新します。
この辺をインストール。
f:id:noshipu:20170201050650p:plain

インストール後にビルドしたら直りました。

HoloLens+Unity開発 入力の取得まとめ編

HoloLensが届きました!
こんな感じでVRで作っていた「Makebox」の移植をしてみました。Unityで開発できて、開発環境も揃っているので楽しいですよ!

今回は「HoloToolKit-Unityを使用した入力の取得方法」をまとめてみました。
これができるようになれば、後はUnityのコードをがりがり書くだけで色々な表現ができるようになるはずです。

HoloToolKitの導入はこちらを参照してください。

HoloToolkit-Unity/GettingStarted.md at master · Microsoft/HoloToolkit-Unity · GitHub

以下のオブジェクトがシーンに存在する状態で使用してください

HoloLensCamera.prefab
InputManager.prefab
DefaultCursor.prefab
EventSystem

紹介する機能

機能 モジュール名 コールバックのタイミング
入力 IInputHandler 対象へのInputDown / 対象へのInputUp
クリック IInputClickHandler 対象へのクリック
フォーカス IFocusable 対象とGazeが重なったとき / 対象からGazeが外れたとき
手の検出 ISourceStateHandler 対象を見ている状態で手が認識されているとき / 対象を見ている状態で手が認識から外れたとき
ホールド IHoldHandler 対象をつまみだした / 対象をつまんでいる / 対象をつまみ外した
ドラッグ(操作) IManipulationHandler 対象をつまみだした / 対象をつまんでいる / 対象をつまみ外した / 途中でトラッキングが外れた
ドラッグ(ナビゲーション) INavigationHandler 対象をつまみだした / 対象をつまんでいる / 対象をつまみ外した / 途中でトラッキングが外れた
音声の検出 ISpeechHandler 対象を見ながらしゃべった時のテキストを返す

※ IManipulationHandler、INavigationHandlerの違いについて
Manipulationは空間でものを動かしたり、何か書いたりしている基本的な動かすことに向いている。
Navigationはジョイスティックのようなもので、閾値(-1~1)も設定されているので、UIとかで使ったりするのに向いている。
詳細は下記
https://developer.microsoft.com/en-us/windows/holographic/Gestures.html#manipulation

※「対象」というのはスクリプトとコライダーがアタッチされているゲームオブジェクトを指します。
またSetGlobalListenerを同じオブジェクトにアタッチすることで、どこを見ていてもコライダーをつけずにイベントを発火することが可能です。

概要

それぞれのモジュールを継承することで、任意のコールバックが呼ばれるような仕組みとなっています。
Monobehaviourを継承したら、StartやUpdateが呼ばれるような感じで、Inputの際も定義したコールバックが呼ばれます。

使い方

InputModuleをusing

using HoloToolkit.Unity.InputModule;

使用するモジュールを継承(複数可)

public class InputTest : MonoBehaviour, IInputHandler, IInputClickHandler, IFocusable

コールバックを定義する

IInputHandler

public void OnInputUp(InputEventData eventData)
{
    Debug.LogFormat("OnInputUp\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}

public void OnInputDown(InputEventData eventData)
{
    Debug.LogFormat("OnInputDown\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}
IInputClickHandler

public void OnInputClicked(InputClickedEventData eventData)
{
    Debug.LogFormat("OnInputClicked\r\nSource: {0}  SourceId: {1} TapCount: {2}", eventData.InputSource, eventData.SourceId, eventData.TapCount);
}
IFocusable

public void OnFocusEnter()
{
    Debug.Log("OnFocusEnter");
}

public void OnFocusExit()
{
    Debug.Log("OnFocusExit");
}

ISourceStateHandler

public void OnSourceDetected(SourceStateEventData eventData)
{
    Debug.LogFormat("OnSourceDetected\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}

public void OnSourceLost(SourceStateEventData eventData)
{
    Debug.LogFormat("OnSourceLost\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}

手の検知はあんまり知られてなさそう。仕組み的に指さし->パーの検知ができる。ちょっと何かに使えるかも?

IHoldHandler

public void OnHoldStarted(HoldEventData eventData)
{
    Debug.LogFormat("OnHoldStarted\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}

public void OnHoldCompleted(HoldEventData eventData)
{
   Debug.LogFormat("OnHoldCompleted\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}

public void OnHoldCanceled(HoldEventData eventData)
{
   Debug.LogFormat("OnHoldCanceled\r\nSource: {0}  SourceId: {1}", eventData.InputSource, eventData.SourceId);
}

IManipulationHandler

public void OnManipulationStarted(ManipulationEventData eventData)
{
    Debug.LogFormat("OnManipulationStarted\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

public void OnManipulationUpdated(ManipulationEventData eventData)
{
    Debug.LogFormat("OnManipulationUpdated\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

public void OnManipulationCompleted(ManipulationEventData eventData)
{
    Debug.LogFormat("OnManipulationCompleted\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

public void OnManipulationCanceled(ManipulationEventData eventData)
{
    Debug.LogFormat("OnManipulationCanceled\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

INavigationHandler

public void OnNavigationStarted(NavigationEventData eventData)
{
    Debug.LogFormat("OnNavigationStarted\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

public void OnNavigationUpdated(NavigationEventData eventData)
{
    Debug.LogFormat("OnNavigationUpdated\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

public void OnNavigationCompleted(NavigationEventData eventData)
{
    Debug.LogFormat("OnNavigationCompleted\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

public void OnNavigationCanceled(NavigationEventData eventData)
{
    Debug.LogFormat("OnNavigationCanceled\r\nSource: {0}  SourceId: {1}\r\nCumulativeDelta: {2} {3} {4}",
        eventData.InputSource,
        eventData.SourceId,
        eventData.CumulativeDelta.x,
        eventData.CumulativeDelta.y,
        eventData.CumulativeDelta.z);
}

ISpeechHandler


使用される単語をどれか一つのオブジェクトにあらかじめ登録しておく必要があります。
SpeechInputSourceを任意のオブジェクトにアタッチし、単語を登録する。
f:id:noshipu:20170128041538p:plain

public void OnSpeechKeywordRecognized(SpeechKeywordRecognizedEventData eventData)
{
    Debug.Log(eventData.RecognizedText.ToLower());
}

最後に

これでインタラクションコンテンツが作れるようになるのではないでしょうか。
また、間違った記載がありましたら、コメントやTwitter等でご指摘ください。

VRアプリ「Makebox」をリリースしました!

VR空間で3Dモデリングを簡単に行えるVRアプリをOculus Storeでリリースしました!
直感的な操作で簡単に3Dモデルの制作をすることが可能です。

Oculus Storeのダウンロードリンクは以下から
https://www.oculus.com/experiences/rift/1569582573068780/

特徴

■ 3Dモデリングを簡単にできる

VR空間で積み木感覚で直感的に3Dモデリングが可能です。

■ 作ったモデルをWebに共有できる

Makeboxで制作した3DモデルをアプリからWebにアップロードすることが可能です。
アップロードしたモデルは簡単に共有でき、モバイルVRで見ることもできます。

MakeboxのWebサイトはこちら:
https://make-box.com

■ 3Dモデルをファイルに書き出しできる

作ったモデルをobjファイルとして書き出し、他の3Dモデリングツールで編集可能!「Unity」や「UE4」のゲームエンジンにそのまま取り込んで使用することもできます。

Unityに取り込む動画:

UE4に取り込む動画:

もちろん、書き出したモデルを3Dプリンタで印刷することも可能です。
誰でも簡単にモデリングができるので、プロトタイプの作成に向いています。

■ 毎日お題が更新される

毎日変わるお題に挑戦することができます。
作りたいものがなくても、気軽にお題に沿った3Dモデルを作れます。
もちろん。自由に3Dモデリングを楽しむこともできます。

アプリ概要

アプリ名: Makebox
価格: $9.99
対応機種: Oculus Rift CV1, Oculus Touch
Oculus Store:
https://www.oculus.com/experiences/rift/1569582573068780/

Makebox公式サイト:
https://make-box.com

ViRD公式サイト:
http://vird.co.jp


ぜひぜひダウンロードして使ってみてできたらフィードバックください!