Nuitrack 1.5.0
3D スケルトン トラッキング ミドルウェア
 すべて クラス 名前空間 関数 変数 Typedefs 列挙型 列挙子 プロパティ イベント グループ ページ
Nuitrack を使用した VRアプリの作成方法

このページをご覧頂いているということは、体全体のトラッキングを用いたモバイル VR アプリの開発に関心があるということでしょう。でも、複雑で時間がかかり過ぎると思っているかもしれません。そんなことはありません!モバイル VR 開発のプロになるために知っておくべきことを伝授します。

作成に必要なもの

まず、ハードウェアです。

  • TVico
  • 平均レベルよりも強力な Android スマートフォン (快適な認識のためには最低 5” 画面)
  • 適切な VR ヘッドセットより最適な環境には、Gear VR セットがお勧めです。
注意
TVico をお使いの場合、Android スマートフォンを Wi-fi 経由で TVico につなげる必要があります。詳細な情報は、TVico ユーザーガイドを参照ください。
Android プラットフォームの USB センサーをサポートしている他の Android デバイスを使用することもできます (サポートしているデバイスの一覧は、Nuitrack Webサイトを参照)。 デバイスに TVico.apk をインストールし、自分の Android スマートフォンにこのデバイス経由で Wi-Fi に接続することが条件です。

次に、ソフトウェアです。

  • Unity (2017.4 以上)
  • 開発環境 (箱から出したばかりの MonoDevelop で十分)
  • VicoVR アプリをスマートフォンにインストール済みであること (VicoVR アプリは、クライアント アプリで TVico へのワイヤレス接続を可能にします)
  • TVico デバイスにインストールされた TVico アプリ (TVico センサーをを使用する場合に必要)
  • Nuitrack SDK、最も重要かつ興味深いもの。

どんな仕組み?

カラー カメラと深度モジュールにより、センサーが、通常の RGB イメージと深度マトリクス (センサーから見える各点への距離) としてデータを生成します。深度マトリクスは、グレースケールのように、暗いトーンは近い距離、明るいトーンは遠い距離に対応します。

VicoVR_1_1.png

参考となる情報
センサーは、体全体がフレーム内にすべて入っている (できれば手を挙げた状態) 位置に設置します。何かにぶつかったり、誰かにぶつかったりすることがないように、周りをクリアな状態にします。

このデータが無線でスマートフォンに転送され、Nuitrack が利用できるようになります。外部アルゴリズムの助けを得て、Nuitrack はあなたの体の重要部分を見極め、センサー ポイントの 0 を含む 3要素ベクターによるグラフィック スケルトンを表示します。Nuitrack は最大 19 のスケルトン関節を認識できます。それに加え、以下に挙げるような、あなた自身の判断で使用できる追加のデータもあります。

これらすべての操作は、周波数 30 FPS で自動的に実行されますので、安心してお使いください。

注意すべき危険も...

まず、とりわけ VR アプリについて知っておくべき重要なことがあります。多くの人は、VR によって深い没入感を実現でき、開発者はユーザーが驚くような壮大なシーンを作り出すことができると思っています。しかし、気を付けるべき危険もあります。PC ゲームの開発者に我よく使う機能でも、 VR では避けなければいけないものがあります。

  • ゲーム内での高速移動や爆発の際に、カメラを揺らさない。吐き気を生じさせてしまう可能性があります。
  • 彼らを異なる速度で、異なる方向に移動させない。ユーザーはめまいを生じさせてしまうかもしれません。
  • カメラの回転方向とユーザーの頭の回転方向が同じであること。そうしないなら、ユーザーの前庭系機能に障害を生じさせてしまいます (VR ゲームは宇宙飛行士のための訓練ではありません)。
  • 手足や目を動かすという通常と異なる操作にユーザーが慣れていないことを覚えていましょう。インターフェイスとゲームの筋は、次にあげる事実を考慮して作成します。
  • インターフェイスとゲームの世界で使う要素はユーザーがアクセスしやすい領域に配置すること。
  • 届きやすいように、ボタンに十分な大きさがあること。
  • インタラクティブな要素に気を付け、ユーザーの手が他のオブジェクトの形状に沈み込むことがないようにすること。
  • センサーの視野角度が限られていること。ユーザーをゲームのスコープから強制的に離れるよう求めることはしない。
  • 表示されるフィールドは周囲よりずっと狭いので、ヒントを参考にし、ユーザーがゲームの主要な場面に集中できるようにするとよいでしょう。
  • 体のトラッキングを含むアプリを開発する際、ユーザーがセンサーの方を向き、視野フィールド内に体のすべての部分が表示されるように気を付けます。

本題に入りましょう!

まず、Nuitrack を Unity プロジェクトに統合する必要がありますが、比較的簡単にできます。Unity で、[Assets] > [Import package] > [Custom Package…] > [NuitrackSDK.unitypackage] > [Import]を選択します。

注意
Nuitrack では、ハードウェア制限上、頭の関節の回転をトラッキングすることはできません。そのため、通常のヘッドセットに GoogleVR プラグインを使用するか、GearVR プラットホームで OculusVR を使用する必要があります。

NuitrackUtils ヘルパークラスが、Nuitrack から得たデータを簡単に変換する助けとなります。拡張メソッドの説明を含みます:

  • どの nuitrack.Vector3 ベクターでも UnityEngine.Vector3 Unity ベクターに変換できます。Nuitrack は万能なシステムで、中には、意味的に Unity タイプと同じものがありますが、実のところ絶対的なやり取りがありません。

    public static Vector3 ToVector3(this nuitrack.Vector3 v)
    {
    return new Vector3(v.X, v.Y, v.Z);
    }

参考となる情報
nuitrack.Vector3 はデータをミリメートルで保存するので、1メートルを 1 Unity 単位に変換するには、nuitrack.Vector3 に 0.001f を掛ける必要があります。掛け算の操作をお勧めするのは、割り算よりも早いからで、最初からコードを最適化するとよいでしょう。

  • Unity 座標の関節の位置はどれでも、以下のように取得できます。

    public static Vector3 ToVector3(this nuitrack.Joint joint)
    {
    return new Vector3(joint.Real.X, joint.Real.Y, joint.Real.Z);
    }

  • 関節の回転位置を四元数で取得します。Unity では、四元数のほうが Euler の座標システムより使いやすいです。関節の回転をそれぞれの関連で計算する時やゲーム スケルトンに結果を適用する時に周辺領域のスケーリングの影響を受けないので、ゲームのキャラクターに生気を与える主な方法となります。

    public static Quaternion ToQuaternion(this nuitrack.Joint joint)
    {
    Vector3 jointUp = new Vector3(joint.Orient.Matrix[1], joint.Orient.Matrix[4], joint.Orient.Matrix[7]); //Y(Up)
    Vector3 jointForward = new Vector3(joint.Orient.Matrix[2], -joint.Orient.Matrix[5], joint.Orient.Matrix[8]); //Z(Forward)
    return Quaternion.LookRotation(jointForward, jointUp);
    }

手本をまねるわけではありません

このチュートリアル記事で取り上げる主役ともいえるゲーム THEFT (Google Play でダウンロード) について少し紹介します。THEFT は、アクションの要素が含まれている本人がランナーのゲームです。プレイヤーが、強盗を行った後に、ホバーボードに乗って、市内の狭い路地を警察の追っ手から逃げるというストーリーです。プレイヤーが利用できるゲームの機能:

  1. 体を傾けながら、体を左右に動かします。
  2. 手でゲームの世界にあるオブジェクトをひっくり返します。
  3. 足で踏みこむことによって加速します。
  4. 腕についたガジェットから撃つと、様々なものを散乱させることができ、警察の追跡を少しの時間引き留めることができます。

スケルトンの使用方法としていくつかのケースを選び出すことができます。具体的に名前を挙げるなら、ポイント 1 と 2 で世界との direct interaction とポイント 3 と 4 での intermedium interaction です。ここでいう direct interaction とは、キャラクターが自分の手でゲームのオブジェクト等を触ることができるケースのことです。

VicoVR_2_1.png

双方向性 対 美しさ
ダイレクトマップ方式とインダイレクトマップ方式のどちらかを選択できます。前者のケースでは、ユーザーの動きがゲームのキャラクターに完全にマッピングされており、後者のケースではアニメーションが開始されるだけで、動きは指定されたもののみです。後者のオプションは、間違った動作を避けたい場合や、特定の境界をユーザーが超えることのないようにしたい場合に有効です。

Here’s Johnny!

シーンの設定を始めます。Nuitrack 要素のいずれかを参照する場合は、シーンに NuitrackScripts プレハブをドラッグ アンド ドロップする必要があります (該当プレハブは、Nuitrack/Prefabs フォルダーでみつけることができます)。シーンを実行すると、自動的に DontDestroyOnLoad として印がつけられるので、ゲーム内の別のシーンに移動しても心配ありません。

VicoVR_3_1.png

NuitrackManager スクリプトの設定にご注意ください。特定の Nuitrack 要素の有効化/無効化はプロジェクト内で行えます。

VicoVR_4_1.png

RiggedAvatar と呼ばれる特別なクラスが Nuitrack SDK にあり、スケルトンの動作管理に使用します。VicoAvatar という RiggedAvatar の洗練された類似品を使用することもできます。すべての関節がスクリプトにハードコードされているため、ゲーム スケルトンの関節変形と nuitrack.JointType からの関節の種類が含まれている JointGameObject サブクラスを選択して、RiggedAvatar の変更を行います。これにより、スケルトンの設定をエディターで簡単に行えるようになります。

VicoVR_5_1.png

ちょっとしたアドバイス
System.Serializable 属性を指定することで、クラスをフィールドとして表示し、Unity で編集可能にします。

[System.Serializable]
public class JointGameObject
{
public nuitrack.JointType typeObj; // Joint type
public Transform obj; // Character's joint transform
public Quaternion offset; // Initial rotation offset
}

ネタバレ注意: Nuitrack は 19 関節を検出しますが、nuitrack.JointType には 25 種類の関節があることに気が付くかもしれません。

スケルトンと Nuitrack スケルトンを揃えるには、最初の回転オフセットを考慮に入れる必要があります。キャラクターの関節と同じ位置の Nuitrack 関節が親オブジェクトに紐つけされた別の回転となっている場合に、最初の画像に表示されているような間違った表示になってしまうことがあります。

VicoVR_6_1.png

参考となる情報
T ポーズはデフォルトの姿勢ですが、関節の回転角度が親オブジェクトに対して 0 になります。キャラクターを T ポーズにすることにより、スケルトンを揃えます。

VicoVR_8_1.png

TPoseCalibrationCalibrationInfo の両スクリプトは、キャリブレーションに使用し、 NuitrackScripts オブジェクトに紐つけされます。キャリブレーションの実施をゲームの最初に行うなら、ユーザーが指定した位置に立っていることを確認できます。キャリブレーションには、T ポーズまたは X ポーズ を使用できます。後者のポーズでは、ユーザーのひじを 90° 上方向に曲げます。

VicoVR_9.bmp

私を見て、まねをしてください!

簡単なものから始めて、キャラクターの手のアニメーションを行います。手については、ダイレクトマップ方式を使用します。RiggedAvatar クラスを調整し、すっきりさせます。

public class RiggedAvatar :MonoBehaviour
{
public JointGameObject[] jointPers;
void Start()
{
for (int q = 0; q <jointPers.Length; q++)
jointPers[q].offers = jointPers[q].obj.rotation;
}
void Update()
{
if (CurrentUserTracker.CurrentUser != 0)
{
nuitrack.Skeleton skeleton = CurrentUserTracker.CurrentSkeleton;
for (int q = 0; q <obj.Length; q++)
{
nuitrack.Joint joint = skeleton.GetJoint(obj[q].typeObj);
obj[q].obj.rotation= CalibrationInfo.SensorOrientation * obj[q].offset * joint.ToQuaternion();
}
}
}
}

シーン読み込み時に Start メソッドが呼び出されます (イベントの実行命令に関する詳細は、こちら)。ここでは、キャラクターの関節に関する最初の回転オフセットを計算します。

Update では、検出されたユーザーの存在を確認します。Nuitrack は、最大 6 ユーザー まで認識できます。CurrentUserTracker.CurrentUser が 0 を戻す場合は、センサーの前のユーザーが認識されていません。 ユーザーの数が表示される場合は、フレームに最初に入った人から優先的に番号がふられます (例: 1人のユーザーがフレーム外に出た場合、二番目にフレームに入ったユーザーが現ユーザーになります)。

CurrentUserTracker.CurrentSkeleton は、現ユーザーのスケルトン データを取得します。

参考となる情報
CalibrationInfo.SensorOrientation はセンサーの上下方向の傾きを修正します。これにより、センサーを設置する高さに関わりなく、スケルトンの正しい位置を取得できるようになります。

真のヒーローはいつも動いています

インダイレクト マップ方式に関する都市伝説はこれまで多々あり、開発者毎に内容が異なっていました。このスケルトン動作を実装することはなかなか特定なタスクであり、主要な原因ともいえます。特定の関節の位置または速度のみが必要なケースもありますし、THEFT では、 “push” のアニメーションを有効にするには特定のジェスチャを行う必要があります。

このシナリオでは、最もスマートな方法ではないが、最も簡単な方法でジェスチャ アナライザーとしての中間層を追加できます。そのためには、架空スケルトンの半分を別個に作成し、ユーザーの足の動きをダイレクト マップ方式で受け取るようにします。

VicoVR_10_1.png

SphereColliderRigidBody は膝の関節に紐つけされています (イメージ内の赤丸の部分)。幾つかの BoxCollidersisTrigger としてフラグが付けられており、特定領域に特定のポイントが入るイベントの処理に使用されます (イメージ内の緑の枠の部分)。

VicoVR_11_1.png

ここからの作業は少し簡単になります。isTrigger としてフラグが付けられたオブジェクトは、ObjectRegistration スクリプトが紐付けされており、特定領域の指定した関節の存在に関する情報と独自の認識子を ActionManager スクリプトに渡します。管理スクリプトはがメッセージ チェーンを作成し、テンプレートと比較して。アニメーションを有効にします。幾つかのパターンがあります。例えば、ユーザーが足を振って前に自分を押し出すと、 “strong push” イベントが生じます。個々のケースで異なるので、長々と話すことはしません。

詐欺ではなくごまかし

完璧なものは存在しません。Nuitrack も例外ではなく、検出した関節の位置は比較的正確ですが、深度マトリクスの解像度が無線データ転送であるがゆえに制限されており、小さな動作領域での問題の原因となるかもしれません。オブジェクトがプレイヤーから遠く離れている場合に、ゲーム内での照準の実装が非常に難しくなります。視界にオブジェクトが入ってきた時点で自動的に照準を合わせる、自動照準を実装することでユーザーを助けることができます。

VicoVR_12_1.png

実際的な狙い方のシステムとして3種類開発されています:

  1. 目線を使用: 最も精度が高いが、直感的ではありません。
  2. 現スケルトンの手のみを使用: 最も精度は低いですが、直感的。
  3. 混合: ユーザーの視線と手の位置の中間地点が決定されます。

二番目の方法は、ユーザーが狙うオブジェクトを見る傾向に基づいており、視線によるオフセットは微小で自然に見えます。

より精度を上げるには、ゲーム キャラクターの関節位置ではなく、実際の関節の位置を使用することもできます。少し前にも紹介した RiggedAvatar スクリプトを変更できます。狙うのに使用される関節の配列を簡単に追加できます。肩、ひじ、右手の関節は計算に使用されます。

追加のフィールド:

public JointGameObject[] jointPersMove;

関節の位置を取得:

Vector3 cJoint = skeleton.GetJoint(nuitrack.JointType type).ToVector3() * 0.001f;
注意
コントロールを統一することで、アプリをエディターでテストできます。Nuitrack メソッドには、何等かのキーを押すことによってスケルトンの動作をまねすることのできるスタブを使用できます。

これは、Nuitrack を使用したゲームの基本的なサンプルです。ボディーコントロールは、ゲーム操作の開発と実装において、全く新しい分野といえます。コンテンツの最適化や調整を行う必要もありますが、それは別の機会に。