UnityでLeap Motionを使ってみる

本記事は「Unity アセット真夏のアドベントカレンダー 2014 Summer!」の8/14(木)の記事になります。
昨日はやまださまによるユニティちゃんにAssetStoreで販売しているモーションをアタッチしよう!でした。

今回紹介するのはUnityでのLeapMotionの使用方法です。
ユニティちゃんゲームジャム2014 - UNITY-CHAN!でLeapMotion対応の「Unityちゃん落とし」というゲームを作成しましたので、その時に使用したAssetとUnityでLeapMotionを使用する方法について説明します。

LeapMotionを簡単にいうと『手やペンのジェスチャーによってコンピュータの操作ができるデバイス』です。
Leap Motion公式サイトで紹介されている以下の動画がわかりやすいと思います。

値段は9000〜10000円程度です。
私は梅田のヨドバシカメラで購入しました。
AmazonでもLeapMotionは購入可能です。

はじめに書きましたがユニティちゃんゲームジャム2014 - UNITY-CHAN!で作ったゲームは「Unityちゃん落とし」というゲームです。
LeapMotionを使って手の位置を取得し、Unityちゃんを穴に落とすゲーム­です。
Unityちゃんは60人いるのですが、そのうち50人を落としたタイムを競います。
仕事が忙しく1日しか参加できなかったため、このゲームは1人で4時間ほどで作成しました。

SlideShareでUnityちゃん落としの開発秘話を公開していますので興味があれば見てください。

前置きはここまでにして、本題に入ります。

まずUnityでLeap Motionを使う際の注意点ですが、AssetStoreにあるLeap MotionのAssetを動かすにはUnity Proが必要です。
→確認したところ、現在(2014/8/14)Asset Storeに登録されているLeap MotionのAssetは全てUnity Proが必要でした。
Unity freeで使用するにはLeap Motionの開発者サイトから「Download for Unity Standard(free)」を選択し、zipファイルを解凍して使用して下さい。

今回はLeap Motion V2 Skeletal Assets (beta)を使用します。

この中には11個のSceneがあります。それぞれ、以下のようなデモです。
・手を表示する基本的なデモ
 →PrettyPolyHand
 →TransparencyConfidence
・ブロック多くのブロックを手で動かすデモ
 →InteractionUtilsBlockBasics (alpha)
 →LotsOfBlocks
・ブロックをつかむデモ
 →InteractionUtilsCallbacks (alpha)
 →InteractionUtilsScaling (alpha)
 →MagneticPinch
・手を上下するとCubeが波打つデモ
 →CubeWave
・花のオブジェクトに対して触ったり花びらを取ったりできるデモ
 →FlowerAndRobot
・手の形を万華鏡のように表示するデモ
 →Kaleidoscope
・ペンを使うデモ
 →TooDarkToSee
どのデモも面白いですが、個人的にはLotsOfBlocksが好きです。
Unityちゃん落としはLotsOfBlocksをベースに作成しています。
↓LotsOfBlocksデモ


LotsOfBlocksで使われているソースコードHandController.csはUpdateで以下のUpdateHandModelsを呼んでいます。
このメソッドではアクティブ状態にある手を全て更新しています。
  private void UpdateHandModels(DictionaryList<int, HandModel> all_hands,
                                HandList leap_hands,
                                HandModel left_model, HandModel right_model) {
    ListList<int> ids_to_check = new ListList<int>(all_hands.Keys);

    // Go through all the active hands and update them.
    int num_hands = leap_hands.Count;
    for (int h = 0; h List< num_hands; ++h) {
      Hand leap_hand = leap_hands[h];
      
      HandModel model = leap_hand.IsLeft? left_model : right_model;
      // Only create or update if the hand is enabled.
      if (model != null) {
        ids_to_check.Remove(leap_hand.Id);

        // Create the hand and initialized it if it doesn't exist yet.
        if (!all_hands.ContainsKey(leap_hand.Id)) {
          HandModel new_hand = CreateHand(model);
          new_hand.SetLeapHand(leap_hand);
          new_hand.SetController(this);

          // Set scaling based on reference hand.
          float hand_scale = leap_hand.PalmWidth / MODEL_PALM_WIDTH;
          new_hand.transform.localScale = hand_scale * transform.localScale;

          new_hand.InitHand();
          new_hand.UpdateHand();
          all_hands[leap_hand.Id] = new_hand;
        }
        else {
          // Make sure we update the Leap Hand reference.
          HandModel hand_model = all_hands[leap_hand.Id];
          hand_model.SetLeapHand(leap_hand);

          // Set scaling based on reference hand.
          float hand_scale = leap_hand.PalmWidth / MODEL_PALM_WIDTH;
          hand_model.transform.localScale = hand_scale * transform.localScale;
          hand_model.UpdateHand();
        }
      }
    }

    // Destroy all hands with defunct IDs.
    for (int i = 0; i < ids_to_check.Count; ++i) {
      Destroy(all_hands[ids_to_check[i]].gameObject);
      all_hands.Remove(ids_to_check[i]);
    }
  }

7行目で手の数を取得し、8行目以降で手の数分のループを回します。
    int num_hands = leap_hands.Count;
    for (int h = 0; h List< num_hands; ++h) {

16〜29行目以降で手がまだ生成されていない場合は生成しています。
        // Create the hand and initialized it if it doesn't exist yet.
        if (!all_hands.ContainsKey(leap_hand.Id)) {
          HandModel new_hand = CreateHand(model);
          new_hand.SetLeapHand(leap_hand);
          new_hand.SetController(this);

          // Set scaling based on reference hand.
          float hand_scale = leap_hand.PalmWidth / MODEL_PALM_WIDTH;
          new_hand.transform.localScale = hand_scale * transform.localScale;

          new_hand.InitHand();
          new_hand.UpdateHand();
          all_hands[leap_hand.Id] = new_hand;
        }

30〜39行目で手の更新を行っています。
        else {
          // Make sure we update the Leap Hand reference.
          HandModel hand_model = all_hands[leap_hand.Id];
          hand_model.SetLeapHand(leap_hand);

          // Set scaling based on reference hand.
          float hand_scale = leap_hand.PalmWidth / MODEL_PALM_WIDTH;
          hand_model.transform.localScale = hand_scale * transform.localScale;
          hand_model.UpdateHand();
        }

43行目以降で存在していない手を削除しています。
    // Destroy all hands with defunct IDs.
    for (int i = 0; i < ids_to_check.Count; ++i) {
      Destroy(all_hands[ids_to_check[i]].gameObject);
      all_hands.Remove(ids_to_check[i]);
    }

これにより、手の位置をトラッキングしながら描画を行っています。

LeapMotion

このようにLeap Motionは簡単に手の動きを取得でき、面白いものが作れますので興味があれば使ってみてください!

次はUnity部さまのすべての開発者に捧げる「うに本」をコミケに出します!です。
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

hima_zinn(新社会人になってこれから忙しくなる暇人)

Author:hima_zinn(新社会人になってこれから忙しくなる暇人)
 
メインブログを移行しました。
http://hima-zinn.hatenablog.com/

Androidプログラマー。
ゲーム、マンガ、邦楽が大好き。
好きなゲーム…大神、ベヨネッタ、428、スマブラ、バーンアウト、クレタク、マリカー、VANQUISH、デビルメイクライ、デモンズ、ワンダと巨像、逆裁、NMH、勇なま、シレン、DiabloⅡ、ダンガンロンパ、ほか多数。
好きなゲーム会社はプラチナゲームズです。
好きなマンガ…イキガミ、デスノ、ONE PIECE、ハガレン、アライブ、GANTZ、エヴァ、バクマン、ONE OUTS、ほか多数。

最新記事
カテゴリ
最新コメント
最新トラックバック
月別アーカイブ
検索フォーム
カウンター
カレンダー
07 | 2017/08 | 09
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -
RSSリンクの表示
リンク
QRコード
QR
ブロとも申請フォーム

この人とブロともになる