冬季オリンピック
いつの間にか冬季オリンピックが始まっていてビックリしている皆さんこんにちは。ここ最近の報道がコロナ禍一色でそれほどオリンピックの話題が無かったし、個人的にはブレスオブザワイルドの剣の試練にドハマりしていたこともあって全く意識にありませんでした。週末の新聞の一面がオリンピックの話題で埋まっていてビックリ。
表か裏か
現在開発を進めている3D脱出ゲームにて、プレイヤーの視点の先にあるアイテムについて説明文を表示するという機能を作成しました。
仕組みとしては簡単で、まずアイテム側にプレイヤーの視点を検知する為のColliderを取り付けて、
このCollider内にプレイヤー側の視点(camera)の視界を表すCollider(下の図の青いBoxの部分)が接触(OnTriggerEnter)したら説明文を表示するという仕組みですが、
例えば上図のPCモニターのようにアイテムに表と裏がある場合、プレイヤーがPCモニターの裏面側に回ったとしてもColliderの接触判定は有効なので説明文が表示されてしまいます。
なので、この問題を回避するためにLinecastを利用してプレイヤーが裏側に回った際の遮蔽物を判定するように対応しました。
裏側を判定する
まずPCモニターの裏側に、裏側だと判定するためのColliderを設置します。下の図の紫の箇所がそのColliderです。
このColliderには「PlayerRayIsBlocked」のタグが設定してあります。
そして、PCモニター側のOnTriggerEnter内でプレイヤー側の視点Colliderを検知した際、プレイヤーとPCモニターの間に「PlayerRayIsBlocked」のタグが付いたColliderが存在すればプレイヤーは裏側にいると判定することができます。
この「PlayerRayIsBlocked」Colliderの存在有無を判定するためにLinecastを使用します。
Linecast
Linecastは始点と終点を設定してそこに線を張り、その範囲内でヒットしたCollider情報を取得する事ができます。
Colliderが複数接触してる時、始点に近いCollider情報を取得できるようです。
こういった手法を取る場合、主にRaycastを使用する事が多いと思いますが、今回のケースでは明確に始点と終点が分かるのでLinecastを使用することにしました。
public void OnTriggerEnter(Collider other) { Vector3 startPos = this.transform.position; Vector3 endPos = other.gameObject.transform.position; RaycastHit hit; if (Physics.Linecast(startPos, endPos, out hit, myLayerMask)) { if (hit.transform.gameObject.CompareTag("PlayerRayIsBlocked")) { return; } } }
上記のソースでは始点(PCモニター)と終点(Player視点)の間にLinecastで線を張り、ヒットしたColldierのタグ名が「PlayerRayIsBlocked」であるかどうか判定しています。
この対応によって
プレイヤーがPCモニターの裏側にいる場合、説明文は表示されなくなり、表に回ると表示されるようになりました。