magicleapのチュートリアルでレイキャストができない
とある理由でmagicleapを触り始めたのでその時の困ったことをメモします.
※C#すらろくに触ったことないレベルのメモ書きです
これは何をやっているのか
このチュートリアルは"レイキャスト"をmagicleapで扱うためのものです.レイキャストとは光線を飛ばしてそれがぶつかった先の情報を取得するものです.今回はその先にキューブを生成するようにつくっているみたいです.
困ったこと
2.2 Unityでのレイキャストをやっているとエラーが出てきた.その中でも,エラーメッセージ通りに修正しても消えなかったのはこれ.
error CS0117:
GetWorldRays' does not contain a definition for
MLRaycast'
このエラーの原因はGetWorldRaysという命令が存在しないことのようだ.結局はこのチュートリアルはSDK0.22用に作られたもので,今使っているSDKは0.24でした.
解決していく
現在使っているレイキャスト用のサンプルスクリプトが公開されていました.Raycast Snippet - Unityというv0.24用に書かれた記事を見つけたのでこれを自分なりに解釈して進めていく.
大まかな流れ
基本は0.22用のチュートリアルと同じ.
- レイキャスト用の空のゲームオブジェクトを作る
- C#スクリプトを作る
- スクリプトをゲームオブジェクトに登録する
今回は3番についてつまずいたのでそれについて書いていく.
具体的なコード
※参照したページをコピペしただけです
using System.Collections;
using UnityEngine;
using UnityEngine.XR.MagicLeap;
public class MLRaycast : MonoBehaviour
{
public Transform camTransform;
public GameObject prefab;
private MLRaycast.QueryParams _raycastParams = new MLRaycast.QueryParams();
void Start()
{
// Start raycasting.
MLRaycast.Start();
}
private void OnDestroy()
{
// Stop raycasting.
MLRaycast.Stop();
}
void Update()
{
// Update the orientation data in the raycast parameters.
_raycastParams.Position = camTransform.position;
_raycastParams.Direction = camTransform.forward;
_raycastParams.UpVector = camTransform.up;
// Make a raycast request using the raycast parameters
MLRaycast.Raycast(_raycastParams, HandleOnReceiveRaycast);
}
private IEnumerator NormalMarker(Vector3 point, Vector3 normal)
{
// Rotate the prefab to match given normal.
Quaternion rotation = Quaternion.FromToRotation(Vector3.up, normal);
// Instantiate the prefab at the given point.
GameObject go = Instantiate(prefab, point, rotation);
// Wait 2 seconds then destroy the prefab.
yield return new WaitForSeconds(2);
Destroy(go);
}
void HandleOnReceiveRaycast( MLRaycast.ResultState state,
UnityEngine.Vector3 point, Vector3 normal,
float confidence)
{
if (state == MLRaycast.ResultState.HitObserved)
{
StartCoroutine(NormalMarker(point, normal));
}
}
}
このように内容を置き換えます.この内容を読み解いていきます.
ざっくりとした理解
using System.Collections;
using UnityEngine;
using UnityEngine.XR.MagicLeap;
このあたりで各関数を呼び出す準備をしています.System
はC#の基本系,UnityEngine
はunityの基本系MagicLeap
はマジックリープ固有の命令が収納されているようです.
public Transform camTransform;
public GameObject prefab;
private MLRaycast.QueryParams _raycastParams = new MLRaycast.QueryParams();
各オブジェクトの準備です.camTransform
はこのあとレイキャストに使うパラメータを引き出す先を登録しておきます.この場合はカメラなのでヘッドセットの動きに合わせて光線が飛びます.prefab
にはレイキャストで作成されるオブジェクトを登録します._raycastParams
はレイキャストに使うパラメータを収納します.
細いメモ類
前提として 連載C#入門第3回クラスとオブジェクトを読んでおくとスムーズかもしれません.簡単に言うとクラスは命令の設計図,オブジェクトはその設計図から作った命令自体だと思って読んでいます.
using UnityEngine.XR.MagicLeap;
magicleap名前空間を追加するみたいです.名前空間というのはクラス(命令文のようなもの?)をまとめたくくりです.フォルダのように名前空間の中にさらに小さな名前空間がある場合もあるみたいです.これがあることによって同じ名前のクラスもどの名前空間の中にいるかで区別できるようになります.
つまりは,この宣言をすることによってmagicleap関係の命令文を使えるようになります.
※ちなみにSystem.Collections
はunityで標準的な名前区間(Cでいうstdioヘッダーのようなもの?),UnityEngine
はunity関係の名前空間です.
public class RaycastSnippet : MonoBehavior
RaycastSnippetというクラスを宣言しました.public
は名前空間の宣言に関係なくいつでも使える言葉です.これを使うことでこのコードの外からもこのクラスを使うことができるようになります.つまりは,unityエディタからRaycastSnippetが使えるようになります.
:MonoBehavior
はこのクラスの属性を追加しています.MonoBehavior
はunityで作ると自動でつけてくれる属性で物体の動きをきっかけとする属性のようです.
public Transfrom camTransfrom;
public
を使って外からも使える形で,camTranfromというクラスをTranfromというカタチで宣言しています.Transfromはgameobjectを動かすためのクラスで,今回はカメラを移動させるために用います.これによりgameobjectの位置情報を使う準備ができました.
public GameObject prefab;
public
を使って外からも使える形で,スクリプトからgemeobjectを扱えるようになります.レイキャストによるキューブの生成に使うようです.
private MLRaycast.QueryParams _raycastParams = new MLRaycast.QueryParams();
private
はpublic
と同じように名前空間の宣言に関係なくいつでも使える言葉です.public
とは反対にこのスクリプトの外からアクセスできないようになるります.後で使用するMLRaycast.Raycastというクラスに送るRayの情報を入れるためのクラスです.new
を付けることによって宣言と同時にオブジェクト化しています.
void Start()
Startメゾットです.メゾットとは複数のクラスが1つの塊になったものです.特にStartは特別な名前で,このスクリプトが実行されたときに1回だけ実行されます.MLRaycast.Start();
によりレイキャストが始まります.
private void OnDestroy()
これもStartメゾッドと同様に特定のタイミングで呼び出されるメゾッドです.これはgameobjectが削除した時に呼び出されるメゾッドです.今回は,MLRaycast.Stop();
によりレイキャストが終了されるように設定されています.
void Update()
これもStartメゾッドと同様に特定のタイミングで呼び出されるメゾッドです.Updateメゾッドはunityで画面が更新されるたびに実行されるメゾッドです.今回は毎回カメラの移動と入力の確認をしているみたいです.
_raycastParams.〇〇 = camTransform.〇〇;
前もって用意しておいた_raycastPatams.〇〇にcamTransfrom.〇〇を代入しています.つまりはmaincameraの状態を常にMLRaycastのパラメータとして受け取っています.これによりmaincameraと光線が同じように移動します.実際にMLRaycast.QueryParamsやTransfromがどのような構成・機能を持っているかはunityスクリプトカンファレンスなどで逐次調べる必要がありそうです.
MLRaycast.Raycast(_raycastParams, HandleOnReceiveRaycast);
レイキャストを実際に動かすクラスです.引数に光線のパラメータと物体とぶつかったときの動作を受け取ります.
private IEnumerator NormalMarker(Vector3 point, Vector3 normal)
光線が物体にぶつかったときにキューブを生成するためのクラスです.