Unity+OculusRift+LeapMotionで3Dキャラクターに触れる

# デモ
こんな感じのを作りました。

画像：
![demo.jpg](https://qiita-image-store.s3.amazonaws.com/0/6794/0149661b-935e-a3c5-98e9-0d7d934feb24.jpeg)

動画：
[OculusRift & LeapMotion with Hatsune Miku](http://youtu.be/MMOOXE5JFrQ)

# 材料

* Unity v4.3.1（Oculusを使うにはProライセンスが必要）
* Oculus Rift, Oculus SDK v0.2.5c : Unity 4 Pro Integration
* Leap Motion, Leap Motion SDK v1.0.9
* [MikuMikuDance for Unity](https://github.com/mmd-for-unity-proj/mmd-for-unity) (バージョン不明。たぶん master branch から last commit d944c94063 のものを使った)

以下は各人のお好みで

* [Tda式初音ミク・アペンドVer1.00](http://seiga.nicovideo.jp/seiga/im2018614)
* [ＭＭＯの素朴なモーション](http://www.nicovideo.jp/watch/sm19111558)
* [日常・非日常モーションセットV102(全部入り)](http://www.nicovideo.jp/watch/sm18033187)

*各バージョンは制作時のもの

# 作り方
## 材料を混ぜる
各材料をDLしたらUnityプロジェクトに放り込みます。

それぞれの放り込み方は各ダウンロードしたファイルに添付されているreadmeファイルや以下を参照。

* Oculus SDK : Unity 4 Pro Integration
    * [Oculus Unity Integration ＆ MMD for Unity 事始め](http://d.hatena.ne.jp/hecomi/20130624/1372083555)
* Leap Motion SDK
    * [UnityでとりあえずLeap Motionを組み込んでみる](http://d.hatena.ne.jp/jonki/20130731/1375285888)
* MMD for Unity
    * [MMD for Unityでミクさんのツインテールを物理演算させるお話 その1](http://eral.blog.eonet.jp/default/2013/06/mmd-for-unity-1-12bc.html)
* MMD for Unity で キャラクターのシェーダが変な時
    * [MMD for Unityでミクさんとケロリン町を周るお話 その1](http://eral.blog.eonet.jp/default/2013/10/mmd-for-unity-1-a42b.html)

## 特定の部位に触れるようにする
LeapMotionで触れるのは下図のPhysicsの部分。
![physics.png](https://qiita-image-store.s3.amazonaws.com/0/6794/d161db38-9a96-9a20-15c0-ea4321241d2b.png)

LeapMotion SDK から引っ張ってきたResources > Prefab > LeapFinger >Tip にアタッチされている Collider の Is Trigger を OFFにする。

これでキャラクターに触れるようになります。

## 触れると反応を返すようにする

まず空のGameObjectを作る。名前はとりあえず”Controller”とする。
そしてその"Controller"に以下のコードをアタッチする。

```csharp:AnimationScript.cs
using UnityEngine;
using System.Collections;

public class AnimationScript : MonoBehaviour {
	
	public GameObject miku = null;
	private Animation mikuAnime;

	// Use this for initialization
	void Start () {
		if (miku == null)
			return;
		
		mikuAnime = miku.GetComponent<Animation>();
	}
	
	// Update is called once per frame
	void Update () {
	}
	
	public void touch(AnimationClip clip) {
		mikuAnime[clip.name].wrapMode = WrapMode.Once;
		mikuAnime[clip.name].layer = 2;
		mikuAnime.CrossFade(clip.name);
	}
}
```
Mikuには下図のようにアニメーションさせるGameObjectを設定する。
![controller.jpg](https://qiita-image-store.s3.amazonaws.com/0/6794/04a2c008-2d6c-613c-abc5-35f4f6abb898.jpeg)

次に反応を返したい部位（Physicsの下にある）に以下のコードをアタッチする。

```csharp:TouchMessage.cs
using UnityEngine;
using System.Collections;

public class TouchMessage :   MonoBehaviour {
	
	public AnimationClip  animationClip = null;
	private GameObject controller = null;
	private float timer = 0.0f;
	
	// Use this for initialization
	void Start () {
		controller = GameObject.Find("Controller");
	}
	
	// Update is called once per frame
	void Update () {
		if (timer > 0)
			timer -= Time.deltaTime;
	}
	
	private void OnCollisionEnter(Collision collision) {
		if (animationClip == null)
			return;

		if (timer > 0)
			return;
		
		if (collision.gameObject.CompareTag("FingerTip")) {
			controller.SendMessage("touch",animationClip);
			timer = animationClip.length;
		}
	}

}
```

animationClipには下図のように反応させたいアニメーションを設定する。
![touch.jpg](https://qiita-image-store.s3.amazonaws.com/0/6794/ff701a95-4f89-7f84-fd32-5cdaf20e7e24.jpeg)

この方法だといちいち衝突時にどこの部位と衝突したかをif文等で判定する必要がなくて楽ちんです。
ですが、複数の反応箇所に触った時の排他制御を書いていないのでその辺りもしっかり書いておきたいところです。
このままでもUnityさんがよしなにやってくれるので放っておいてますが反応箇所が多くなるとよくないことが起きそうな気がします。

これで無事に反応を返してくれるようになりました。
以上となります。お読みいただきありがとうございました。

# 謝辞
各ツール・データ・開発情報を公開されている皆様に感謝の意を表します。
これらがなければ私では到底開発できません。ありがとうございます。