この記事は Unity Assets Advent Calendar 2016 20日目の記事になります。
今日はHoloLensの空間認識を利用して、現実の壁とか床とか天井とか机などで反射するレーザーを撃ってみます。
ArcReactor Rays Generator 1.8 (Dec 16, 2016)
反射するビームのポイントとなるのは、Demo3_reflectデモシーンに含まれたLaserLauncher、PlasmaLauncherゲームオブジェクトにアタッチされたArcReactor_Launcher.csになります。これのReflection Settingsで反射させたいLayerを指定。
あと、反射する壁にアタッチされたArcReactorDemo3Mirror.csが実際の反射を行っているようです。
なので、HoloToolkit-Unityに含まれる、空間認識後によしなにPlaneを生成して配置してくれるSpatialProcessingデモシーンをもとに、生成されたPlaneに対してArcReactorDemo3Mirror.csもアタッチするようにちょこっとカスタマイズしていきます。
// どっかに追加してインスペクター上で\ArcReactor\Demos\Prefabs\Particles\MirrorHitBubbles.prefabをアタッチする
public GameObject hitParticles;
// 265行目付近に追加
ArcReactor.Demo.ArcReactorDemo3Mirror mirror = destPlane.AddComponent<ArcReactor.Demo.ArcReactorDemo3Mirror>();
mirror.hitParticles = hitParticles;
Gradient g;
GradientColorKey[] gck;
GradientAlphaKey[] gak;
g = new Gradient();
gck = new GradientColorKey[2];
gck[0].color = Color.red;
gck[0].time = 0.0F;
gck[1].color = Color.blue;
gck[1].time = 1.0F;
gak = new GradientAlphaKey[2];
gak[0].alpha = 1.0F;
gak[0].time = 0.0F;
gak[1].alpha = 0.0F;
gak[1].time = 1.0F;
mirror.colorGrad = g;
mirror.rotationSpeed = new Vector3(0f, 0f, 0f);
destPlane.transform.parent = planesParent.transform;
SurfacePlane surfacePlane = destPlane.GetComponent<SurfacePlane>();
レーザーをAir-Tapで出す
次にDemo3_reflectデモシーンにあったLaserLauncherゲームオブジェクトを参考に、ArcReactor_Launcher.csを適当なゲームオブジェクトを作ってアタッチして値を設定。
Demo3_reflectデモシーンのLaserLauncherゲームオブジェクトをプレハブ化して持ってきてもOK
Air-Tapで好きなイベントを実行できる汎用スクリプト
下記のスクリプトを使って、Air-TapでLaserLauncher.csのLaunchRay()が実行されるように設定する。
※Managerオブジェクトとかにアタッチして汎用的に使える。
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.VR.WSA.Input;
using HoloToolkit.Unity;
[RequireComponent(typeof(GazeManager))]
public class AirTapAction : MonoBehaviour
{
GestureRecognizer recognizer;
public UnityEvent myEvent;
void Start()
{
recognizer = new GestureRecognizer();
recognizer.SetRecognizableGestures(GestureSettings.Tap);
recognizer.TappedEvent += Recognizer_TappedEvent;
recognizer.StartCapturingGestures();
}
void OnDestroy()
{
recognizer.StopCapturingGestures();
recognizer.TappedEvent -= Recognizer_TappedEvent;
}
private void Recognizer_TappedEvent(InteractionSourceKind source, int tapCount, Ray headRay)
{
OnTap();
}
void LateUpdate()
{
#if UNITY_EDITOR
if (Input.GetMouseButtonDown(0))
{
OnTap();
}
#endif
}
private void OnTap()
{
if (myEvent != null)
myEvent.Invoke();
}
}