Update の中身はわずか10行程度で、こんな感じで、空間を摘んで移動できるようになります。
空中も自由自在ですね。さらっとご紹介。
解説
ほんと簡単です。
まずはつまんでいる状態を検知します
こんな感じで、つまみ始めるとキューブが小さくなり、摘んだを検出するとキューブが緑色に変わるようにしました。
プログラム
using UnityEngine;
public class PinchDetection : MonoBehaviour
{
[SerializeField] private OVRHand ovrHand;
[SerializeField] private Transform cube;
[SerializeField] private MeshRenderer cubeRenderer;
[SerializeField] private Material on; // キューブの色変更用
[SerializeField] private Material off; // キューブの色変更用
public bool IsPinching = false;
void Update()
{
// つまみの強さを取得、0から1の間で変化し、1は完全に親指と人指し指がくっついている状態
var strength = ovrHand.GetFingerPinchStrength(OVRHand.HandFinger.Index);
// 5cm x つまみの強さを取得していて、消えないように 0.1cm は残るようにしています
var scale = Mathf.Max(0.05f * (1 - strength), 0.01f);
// 人差し指のピンチングの強さに応じて cube の scale を変更します
cube.localScale = new Vector3(scale, scale, scale);
// キューブが 2cm 未満になっていることを検出
IsPinching = cube.localScale.x < 0.02f;
// 検出したら、キューブの色を変えます
cubeRenderer.materials = IsPinching ? new[] {on} : new[] {off};
}
}
そして、摘んでいるときに移動できるようにします
1フレーム前の手の位置と、現在の手の位置との差分を取得して、その変化量に応じて自分自身を移動させます。
using UnityEngine;
public class PinchingMover : MonoBehaviour
{
[SerializeField] private GameObject me;
[SerializeField] private GameObject hand;
[SerializeField] private PinchDetection detection; // 上のプログラム
private float speed = 20f; // 移動スピード、適当な値です
private Vector3 previous;
void Update()
{
// 摘んでいるときは
if (detection.IsPinching)
{
// 1フレーム前の手の位置と、現在の手の位置との差分を移動量のベースに、speed を積算します
var movement = (previous - hand.transform.localPosition) * speed;
// 自分自身を移動させます
me.transform.position += movement;
}
// Update の最後で、再び自分の手の位置を設定
previous = hand.transform.localPosition;
}
}
注意
- hand.transform.
local
Position にしないと、自分(me)と一緒に手(hand)が動くので、ぶっ飛んで死にます。 - previous は Start で初期化しておいた方がいいとか、細かいところは見やすさ重視で割愛しています。
Unity の設定
PinchingMover
PinchingDetection
Green16, Red16 とかは適当にMaterialを作って設定してもらえれば大丈夫です。
備考
- 摘むの補足は、前に書いた OculusQeust のハンドトラッキングの摘むを試しみた を参照ください。
- 本当は指だけで移動できるようにしたかったり、ボルダリングみたいなのを考えていたりしていく中で、デバッグ用ならこれでいいかってなった結果の産物です。