tanaka's Programming Memo

プログラミングについてのメモ。

Leap Motionでマウス的な操作をする LeapMotionPointer

Leap Motionを使って、マウスと同じようにスクリーン上の場所を指定する操作を実装しました。以下は、開発中のVoxelorer Birdに組み込んだ作例です。

以下のリポジトリーで公開しています。

github.com

使い方を紹介します。

f:id:am1tanaka:20190217005740g:plain
動作例

目次

前提

動作確認をしたのは以下の環境です。

  • Windows10
  • Unity2017.4.20と2018.3.2
  • Leap Motion Orion 4.0.0
  • Unity Core Assets 4.4.0

WebGLについて

Unity2017.4ではビルドできませんでした。Unity2018.1にして、Unsafe Codeを許可するとビルドはできましたが、実行時にエラーが出て動きませんでした。WebGLでの動かし方は分かっていません。

環境設定

Leap MotionをUnityで使えるようにする手順はこちらの公式ページで説明されています。すでに環境を構築済みでしたら、飛ばして構いません。

  • 公式ページを開きます
  • DOWNLOAD ORION BETAのボタンをクリックして、Leap Motion Orionの最新版をダウンロードしてインストールします
  • 公式のこちらを開きます
  • DOWNLOAD UNITY CORE ASSETS X.X.Xのボタンをクリックして、Unity Core Assetsをダウンロードします

以上で下準備完了です。

デモを動かす

デモの実行方法です。

Leap Motion用のアセットがないので、以下のようなエラーが出ます。次の手順で消えますので作業を進めてください。

f:id:am1tanaka:20190217010038p:plain
エラーが出ても構わず進めて良い

  • 上の手順でダウンロードしたUnity Core Assetsをプロジェクトにインポートします

f:id:am1tanaka:20190217010102p:plain
インポート

これでエラーが消えます。

  • Projectウィンドウから、LeapMotionPointer > Demoフォルダーを開いて、Demoシーンをダブルクリックして開きます

以上でデモ用のシーンが開きます。Playするとデモが動きます。

f:id:am1tanaka:20190217010115p:plain
デモの画面

操作方法

手を水平に開いておくのが基本姿勢です。以下のように、Leap Motionの上に手を開いて、水平にかざします。

f:id:am1tanaka:20190216211447j:plain
基本姿勢

手のひらを水平にしたまま、上下左右に手を動かして画面にカーソルが表示される場所を探してください。Leap Motionから少し奥で、30cmぐらい上の位置ぐらいで表示されると思います。

左手でも操作できます。

左右移動

手を左右に動かします。

f:id:am1tanaka:20190217010155g:plain
左右操作

上下移動

手を上下、あるいは前後に動かします。

f:id:am1tanaka:20190217010233g:plain
上下操作

上下、前後のどちらも、カーソルは上下移動と見なします。

クリック

クリックは、人差し指を下げます。

f:id:am1tanaka:20190216211523j:plain
クリック

人差し指薬指の高さの違いでクリック判定をしています。中指は見ていないので、曲げても曲げなくてもどちらでも楽な方で。

手のひらが人差し指側に傾いていると誤クリックが発生しやすくなり、操作が安定しません。

f:id:am1tanaka:20190216211546j:plain
誤クリックが増える

小指側に傾けておく方が安定した操作ができます。

f:id:am1tanaka:20190216211538j:plain
小指側に傾けると安定する

丸いのをドラッグしたり、左上のボタンをクリックしたりしてみてください。

f:id:am1tanaka:20190217005740g:plain
動作例

手のひらを小指側に傾けておけば、適当に操作してもそれっぽく動きます。

手の認識がうまくいっていないと動作が不安定になります(結構頻繁に起きます)。反対側に動いたり、クリックがおかしかったり、震えたりする場合は、手をLeap Motionの視野から一旦外してから、手を認識しなおしてください。

プロジェクトに組み込む

組み込みたいプロジェクトをUnity2017.4以降で開いてから、以下の作業をします。

必要なアセットをインポート

  • ダウンロードしてあるUnity Core Assets(Leap_Motion_Core_Assets_ x.x.x.unitypackage)をインポートします
  • LeapMotionPointerリポジトリーのReleasesを開いて、最新版のLeapMotionPointerX.X.X.unitypackageをダウンロードして、プロジェクトにインポートします
  • LeapMotionを使いたいシーンを開きます
  • Projectウィンドウで、LeapMotionPointer > Prefabsフォルダーを開きます
  • LeapMotionPointerプレハブをドラッグして、Hierarchyウィンドウにドロップします

これで準備完了です。ついでに、動作確認のためにデモ用のCanvasを配置しておくと楽です。

  • ProjectウィンドウのLeapMotionPointer > Demo > Prefabsフォルダーを開いて、DemoCanvasプレハブをHierarchyウィンドウにドロップします
  • EventSystemがシーンにない場合は、HierarchyウィンドウのCreateボタンをクリックして、UI > Event Systemを選択して追加します

f:id:am1tanaka:20190217010456p:plain
Hierarchyの様子

これでLeapMotionを使ってカーソルを操作できます。カーソルは、DemoCanavsの子供のCursorオブジェクトです。これの画像を差し替えればオリジナルのものに差し替えることができます。

f:id:am1tanaka:20190217010526p:plain
DemoCanvas

スクリプトで情報を得る

情報は、LeapMotionManagerExクラスのstaticプロパティーで得られます。

利用したいスクリプトの冒頭に、以下のusingを追加します。

// :
using AM1.LeapMotionPointer;

bool LeapMotionManagerEx.isEnable

Leap Motionで手を確認している時にtrueになります。

Vector3 LeapMotionManagerEx.screenPoint

Leap Motionが指している画面座標を返します。

// :
Debug.Log(LeapMotionManagerEx.screenPoint);

補足

デフォルトの設定では、Camera.mainのスクリーン座標を返します。Main Cameraタグが未設定だった場合など、Camera.mainが取得できない状態の時はscreenPointは無効な値を返します。

カメラを指定するには、シーンに配置したLeapMotionPointerオブジェクトのTarget Cameraプロパティーに目的のカメラを設定します。

f:id:am1tanaka:20190217010543p:plain
カメラを設定する場所

Vector3 LeapMotionManagerEx.viewportPosition

Leap Motionが指している場所をビューポート座標で返します。

bool LeapMotionManagerEx.isPressDown

クリックを開始した時にtrueになります。

// :
if (LeapMotionManagerEx.isPressDown) {
    Debug.Log("クリック!");
}

bool LeapMotionManagerEx.isPress

クリック状態の時、ずっとtrueになります。ドラッグを判定したい場合などに利用します。

// :
if (LeapMotionManagerEx.isPress) {
    Debug.Log("押し続けている");
}

bool LeapMotionManagerEx.isPressUp

クリックが解除された時にtrueになります。

// :
if (LeapMotionManagerEx.isPressUp) {
    Debug.Log("クリック終了");
}

UIのボタン

UIのボタンは、クリック時に自動的に押すようにしてあります。何もしなくても反応します。

パラメーター

LeapMotionPointerの調整用パラメーターは以下の通りです。

f:id:am1tanaka:20190217012026p:plain
LeapMotionPointerのインスペクター

  • Leap Provider
  • Model Pool
    • 手のモデルを表示したい時に利用します。本プロジェクトでは設定不要です
  • Target Camera
    • LeapMotionManagerEx.screenPointを計算する時に使うカメラを指定します。未設定の時は、Camera.mainの値を使います。Camera.mainnullの時は、LeapMotionManagerEx.screenPointの値が設定されません
  • Move Rate
    • 手の動きと、カーソルの動きを対応させる係数です。この値を大きくすると、手の動きに対して、カーソルの動きが速くなります
  • Visible Under
    • 手の低さの下限値です。この値を小さくすると、低い位置で手を認識するようになります。小さくしすぎると指の動きが認識できなくなるので、0.15程度が下限です
  • Click Threshold
    • クリックを判別する人差し指と薬指の高さの差です。この値を大きくすると、クリックの誤動作は減りますが、クリックの反応が鈍くなります
  • Bank Limit
    • 手首の傾きがこの値よりも大きくなったら、誤動作を避けるためにクリック判定を無視します。0は傾き無し。0.5が90度です
  • Viewport Click Limit
    • 画面端でクリックを無視する範囲です。特に不要な場合は0のままで構いません
  • Flat Rate
    • 手の震えを止めるための平均係数です。この値を小さくすると反応はよくなりますが、Leap Motionの誤差による震えが出やすくなります

特に調整する必要はないと思います。手を認識する場所を下げたい時に、Visible Underを設定するぐらいだと思います。

今後について

現在、UIのボタンは無理やりButtonコンポーネントを取得して、クリック時のイベントを実行するようにしています。レイヤーの指定などができず、他の要素のクリックもできないので、将来的にはEvent Systemに対応させることを考えています。

人差し指と薬指の高さ判定に手首の回転を考慮していませんが、試しに実装したら動作が不安定になったので削除した経緯があります。よい方法があればご教示いただければ幸いです。

プルリク歓迎です。

github.com

ライセンス

MITライセンス

参考URL

www.leapmotion.com