Swampdog part21 -Raycastで名称取得-
はじめに
これまで以下の機能を実装してきました。
- カーソルを作成
- カーソルに骨を認識させる
- ラベルを作成
- ラベルが視界内に収まるようにする
- ラベルがこちらに正対するようにする
今回はラベル内のテキストをカーソルが当たったオブジェクトの名称に置き換えることを目指します。
デバッグ機能の確認
ここからは値が取得できているか確認しながら進めたいので、デバッグ機能について勉強します。
- Unity Documentation | Debug.Log
とりあえず、適当なスクリプトを「Assets -> Scripts」に作ります。
DebugTestとでも名付けます。
using System.Collections; using System.Collections; using System.Collections.Generic;using UnityEngine; public class DebugTest : MonoBehaviour { // Use this for initialization void Start () {         Debug.Log("debug worked"); } // Update is called once per frame void Update () { } }
これだけ。
適当にDebugManagerでもCreate Emptyで作成してスクリプトを当てます。
エミュレータを起動して確認。
取れているみたいですね。
RaycastHitからコライダーの名称を取得
Raycastでは視線がコライダーにヒットすると、hitInfo(RaycastHitクラス)の中にコライダーに関する情報が格納されます。
- Unity Documantation | Physics.Raycast
- Unity Documantation | RaycastHit
まずはコライダーの名称をデバッグで取得してみます。
Unityってどのオブジェクトにスクリプトを当てるか決まりあるんですかね?
RayCastからのコライダーを取得するスクリプトはCursorに適用するのが自然だと思いますが、その後Labelのテキストを書き換えるのはどうすれば?
とか考えながら。
調べていたらコライダーがアタッチされているオブジェクトの名前が取れそうでした。
これでコライダーが適用されているオブジェクトの名称を取得できるかなとテスト。
var objectName = hitInfo.collider.attachedRigidbody.name; Debug.Log(objectName);
Visual StudioのHoloLensエミュレータを起動。
「出力」からデバッグメッセージを確認。
debug worked
は確認できましたが、
それ以降は延々と以下のエラー。
Exception thrown: 'System.NullReferenceException' in Assembly-CSharp.dll NullReferenceException: Object reference not set to an instance of an object. at WorldCursor.Update() at WorldCursor.$Invoke6Update(Int64 instance, Int64* args) at UnityEngine.Internal.$MethodUtility.InvokeMethod(Int64 instance, Int64* args, IntPtr method) (Filename: <Unknown> Line: 0)
調べたら似たような記事を発見。
- Qiita | クリックしたオブジェクトの名前を取得
varかstringかの違い?それは関係ないか。
それよりもRaycast()でTrueの時に実行しているはずなのにSystem.NullReferenceException
が発生している。
attachedRigidbodyの使い方が怪しい。よく考えたらリジッドボディは設定していないはず。
修正。
var objectName = hitInfo.collider.gameObject.name; Debug.Log(objectName);
オブジェクト名取得できました。
同じ名前のが多いのでわかりにくいですが、カーソルが別の骨に当たったらちゃんとそいつの名前を取得しているようです。
親のオブジェクト名取得
親子関係は以下のような形です。
欲しいのは「grp1」ではなくその上の「肋軟骨l1」です。
先ほどのコードを親のオブジェクト名取得に変えます。
var objectName = hitInfo.collider.gameObject.transform.parent.gameObject.name; Debug.Log(objectName);
親子関係についてはここら辺を参考にしました。
- Unituy Documentation | Transform.parent
- Unityを使った3Dゲームの作り方(かめくめ) | Unityでゲームオブジェクト、コンポーネントを取得する方法
カーソルが当たっている部位の名前が取得できました。
次はラベルのテキストをこの名称で置き換えます。
テキストの置換
以下の記事を参考にしました。
- hiroyukitsuda.com | Unityで他のスクリプトの変数や関数を利用する
こんな感じでカーソルから目的のオブジェクト名を取得して書き換えてみます。
できるといいなぁ。
using UnityEngine; public class ReplaceLabel : MonoBehaviour { GameObject cursorObj; // Use this for initialization void Start () { cursorObj = GameObject.Find("Cursor"); } // Update is called once per frame void Update () { WorldCursor wc = cursorObj.GetComponent<WorldCursor>(); GetComponent<TextMesh>().text = wc.objectName; } }
エミュレータで確認。
できました。
次回
次回はこのラベルをAir Tapしたときに詳細説明が表示されるようにします。
今日はよい感じに開発できました。満足。
余談ですが、アイキャッチが代わり映えしない。。。