【Unity】Linecastをもう少し勉強してみた

以前、壁登りの処理を作ったのですが、
モーション付きで実装するのが難しくて、うまく処理できない。

こんな感じで停滞している毎日なんですが、
少し、おや?って事があったので、調べる事にしました。

コースとしては、高台があって壁登りで上に上がります。
Linecastテスト③.jpg
上に上がったら走り出すようにしたいので、
高台はFloorレイヤー(茶色)で作成して、
登り用のWallレイヤーの壁(黒色)を左側にくっ付けて、
登り切った所でFloorレイヤーを読み取って、走り出す設定にしました。

ところが、上に着地しても走りだしのモーションが呼び出されない!
なんで??となりました。

足元に張っているLinecastは、Floorレイヤーに反応するように設定しているのに…

と言う事で、モデルを作って検証してみる事に。
Linecastテスト⑥.jpg
緑のブロックをプレイヤーとして、右方向に動かします。
床面はWallとFloorの二つのレイヤーで作って様子を見ます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LineCastTest : MonoBehaviour
{
private float rightOffset = 0.75f;
private float downOffse = 0.76f;
private RaycastHit2D hit;
public LayerMask floorLayer;

[SerializeField]
private float run;

private Rigidbody2D playerRB;

private Vector2 underStrat;
private Vector2 underEnd;

// Start is called before the first frame update
void Start()
{
playerRB = GetComponent<Rigidbody2D>();
}

// Update is called once per frame
void Update()
{
SetLineCast();

if (hit)
Debug.Log("接地してるよ");
}

void FixedUpdate()
{
playerRB.velocity = new Vector2(run, playerRB.velocity.y);
}

//Linecastの設定
private void SetLineCast()
{
underStrat = transform.position - (transform.right * rightOffset) - (transform.up * downOffse);
underEnd = transform.position + (transform.right * rightOffset) - (transform.up * downOffse);

hit = Physics2D.Linecast(underStrat, underEnd,floorLayer);

Debug.DrawLine(underStrat, underEnd, Color.red);
}
}

こんなスクリプトをプレイヤーにアタッチしてログを取ってみます。
Floorに乗ったらログが出力されるはずなんですが…
Linecastテスト⑦.jpg
コンソールは無言です。(T-T) グスッ

なんで??

この原因は、大したことが無くて、
Linecastテスト⑧.jpg
本体下の赤ラインがLinecastなんですが、
プレイヤーのColliderとかなり近い位置に設定していた為、
Floorレイヤーに刺さってなかった事が分かりました。

ColliderとColliderの接触面は、若干の開きがあるようなので、
ギリギリに設定すると上手く刺さらないようです。

これに気付いた時に、なんてマヌケなミスと恥ずかしくなったんですが、
丁度いい機会なんで、少しLinecastの掘り下げ勉強をしてみようかと思いました。



そもそもLinecastって、床や壁の判断に使うけど、他にどんな事ができるの?
そこで、折角モデルも作ったんで、
Linecastでどんな事ができるのか検証してみようと思います。

まず情報を探ってみます。Googleセンセ~ (T人T) オネガイ!

Linecastは、
・接触するCollider情報を取得できる
・特定レイヤーだけ反応させられる
・Colliderが複数接触してる時、始点に近いCollider情報を取得できる
・ビットを使えば、特定レイヤーを複数設定できる

情報は、こんな感じでした。

Colliderが複数接触してる~ が気になるので、
Linecastテスト⑨.jpg
プレイヤーを中間に置いて様子を見てみます。

スクリプトを修正してテストしてみましょう!

// Update is called once per frame
void Update()
{
SetLineCast();

if (hit)
Debug.Log(hit.collider.gameObject.layer);
}

//Linecastの設定
private void SetLineCast()
{
underStrat = transform.position - (transform.right * rightOffset) - (transform.up * downOffse);
underEnd = transform.position + (transform.right * rightOffset) - (transform.up * downOffse);


hit = Physics2D.Linecast(underStrat, underEnd);

Debug.DrawLine(underStrat, underEnd, Color.red);
}

説明すると、
接触するCollider情報からオブジェクトの情報を取得する場合は、
RaycastHit2D変数.collider.gameObjectで取り出す事が出来ます。

今回は、オブジェクトの中のレイヤー情報なので、
デバッグの中の hit.collider.gameObject.layer これでレイヤーナンバーを取得できます。
Linecastのレイヤー指定を無くす事で接触する全てのColliderを取得する事ができます。

これでPLAYするとコンソールに7の数字が…
レイヤーナンバーなんで、どのレイヤーか分かりにくい(T-T) グスッ

って事でレイヤー名を取得します。

// Update is called once per frame
void Update()
{
SetLineCast();

if (hit)
Debug.Log(LayerMask.LayerToName(hit.collider.gameObject.layer));
}

取得したレイヤーナンバーからレイヤー名を取得するのが、
LayerMask.LayerToNameです。

引数にレイヤーナンバーを入力すると設定したレイヤー名が表示されます。
Linecastテスト⑩.jpg
実際にPLAYすと、こんな感じになります。

無事に表示されていますが、Wallですね~
これは、Linecastの設定が
Linecastテスト⑪.jpg
こんな感じで引いてるので、始点寄りのCollider情報を拾ってるからなんです。

と言う事は、始点を右側に変えるとどうなるかと言うと
Linecastテスト⑫.jpg
当然の結果でっす。

これは理解しておく必要がありますね。

二つのレイヤーの間に止まった時、どちらに居るかを調べたいってなったら、
始点の位置で取得するColliderが変わるって事になります。

基本的には、進行方向に合わせて、始点を決めるといいかと思います。
アンドロイド君は、右移動なので始点を右からに修正しないと(;^_^A

折角、覚えたんで少し遊んでみます。
色を変えた床を4つ程並べて、プレイヤーを移動させます。
各床の色を読み取って、床を通過する間、プレイヤーも同じ色にさせてみます。

collider.gameObjectは、ゲームオブジェクトとして読み込むものなので、
当然、GetComponentが使えます。

単純に色を読み取ればできるはずなんですが…

上手く読み取らせる事ができました。ヽ(´▽`)/~♪

プレイヤーの色が変わる時、あれ?って思われたかもしれませんが、
SpriteMaskを使ってます。

最後の遊びはオマケなんで、実際に使いどころはないでしょうが、
Linecastの参考になれば幸いです。

さて、止まっているアクションの処理の続きを作りますかね~ (- .-)ヾ ポリポリ
何か作れたら記事にするので、それまでは
( ^ 0 ^ )/~~~~see you again


この記事へのコメント