バグと言うか思った動作をしてくれない部分があって、
悩んでいる今日この頃なんですが…
何がおかいしかと言うと、
壁に接触した状態から登って行くと、うまくよじ登るようになったんですが、
壁に向かってジャンプして、壁に張り付く前に上端に届くと、
上手く登ってくれない状態なんです。 ( ノД`)シクシク…
また、タイミングによっては、壁の上によじ登っても、
走り出さずに同じモーションを繰り返すなんて事も起こっています。
この辺りを解消しないと動きとしては問題になります。
まず、登り切った所でモーションを繰り返す原因を考えてみたのですが、

青い線がRayです。
足元のオブジェクトが、白が壁でWallレイヤー、茶色が床でFloorレイヤーとしています。
スクリプトでは、
ActionTest
public LayerMask floorLayer;
private bool bodyUnder; //体下Ray
void Update()
{
SetLinecast();
//床の接触判定
if (bodyUnder)
{
FloorAction();
}
else
VerticalMotion();
}
//Rayの設定
private void SetLinecast()
{
//LineCast用座標設定
Vector2 under1 = transform.position + (transform.right * 0.8f) - (transform.up * 2.3f);
Vector2 under2 = transform.position - (transform.right * 0.8f) - (transform.up * 2.3f);
//足元センサー
bodyUnder = Physics2D.Linecast(under1, under2, floorLayer);
}
FloorAction関数が呼び出されて、初めて走るモーションに切り替わるように
設定しています。
当然、よじ登りモーションがスクショの位置で終わると
床にRayが届いてないので、よじ登りモーションがループする事になります。
壁に張り付いて登らせた場合、Rayが上手く床に届くんですが、
ジャンプ中に上端のセンサーに届くと、壁とアンドロイドの距離が開くので、
Rayが届かない位置で登り切ってしまうのが原因と分かりました。
解決方法としては、
・壁を薄くする
・床に関係なく何かに乗れば接地してると判断させる
今後、壁の上からジャンプさせたりしたいので、
壁を薄くするのは意味がないなって事で、2番目の解決方法を模索する事にしました。
まず、Linecastのおさらいですが、
Rayは、接触するCollider情報を全て取得する事ができる。
レイヤーを指定する事で、他のレイヤーを無視する事ができる。
この特徴があります。
なので、指定レイヤーを外してやれば、
接触するColliderに全て反応するようになります。
早速、Rayを修正していきます。
ActionTest
private bool bodyUnder; //体下Ray
//Rayの設定
private void SetLinecast()
{
//LineCast用座標設定
Vector2 under1 = transform.position + (transform.right * 0.8f) - (transform.up * 2.3f);
Vector2 under2 = transform.position - (transform.right * 0.8f) - (transform.up * 2.3f);
//足元センサー
bodyUnder = Physics2D.Linecast(under1, under2);
}
これは簡単でレイヤーを外すだけでっす(^.^; オホホホ
これで足元のRayに、どのColliderが接触しても反応するようになります。
早速テストしてみます。

壁で止まったままの状態でジャンプしてます。
(~_~;Aオイオイ
調べて分かったんですが、
壁ジャンプの際、

後ろ脚がRayを突き抜けます (~_~;A
当然、Rayが反応します。
足元のRayと前方のRayが両方trueなら停止モーションを再生させてるので、
ジャンプさせると止まったままの態勢で体が浮き上がるカオスな状態です。(^.^; オホホホ
足がRayより下に突き抜けないようにAnimationを変更すればいいのですが、
体全体を上げると張り付きのAnimation時に位置が大きく変わるので、
見た目が変化しすぎます。
となると、足なら非接触と判断させる必要があります。
Rayは、接触するCollider情報を全て取得しているので、
それを利用して判別処理を作ってみます。
判別の材料としては、オブジェクトネーム・タグ・レイヤーがありますが、
レイヤーで判別した方がスクリプトが組みやすいと思うので、
レイヤーを設定していきます。
まず本体にレイヤーを設定します。

Bodyレイヤーを追加して番号を確認します。
今回は、9番レイヤーに追加しました。
続いて、アンドロイド本体にレイヤーを割り当てます。

親オブジェクトにレイヤーを設定すると、
子を全て同じレイヤーにするかと聞いてくるのでOKにします。
後は、各パーツがBodyレイヤーになってれば準備OKでっす。
判別用のスクリプトを作成します。
ActionTest
//レイヤー関連
private const int bodyLayerNumber = 9; //本体レイヤーナンバー
//Ray用フラグ
private bool bodyUnder; //足元Ray
void Update()
{
SetLinecast();
}
//Rayの設定
private void SetLinecast()
{
//足元センサー
bodyUnder = DiscriminationCollider();
}
//足元のCollider判別
private bool DiscriminationCollider()
{
Vector2 under1 = transform.position + (transform.right * 0.8f) - (transform.up * 2.3f);
Vector2 under2 = transform.position - (transform.right * 0.8f) - (transform.up * 2.3f);
Debug.DrawLine(under1, under2, Color.blue);
RaycastHit2D which = Physics2D.Linecast(under1, under2);
if (which)
{
if (which.collider.gameObject.layer == bodyLayerNumber)
return false;
else
return true;
}
else
return false;
}
SetLinecast関数の中がややこしくなるので、
新しくDiscriminationCollider関数を用意しまいた。
DiscriminationCollider関数の中身ですが、
まず、レイヤーで判別させると書きましたが、
レイヤー名で判別させるには、Name変換のコマンドが必要になるので、
レイヤー番号で判別させる方がコマンドが楽になります。
which.collider.gameObject.layerでレイヤーナンバーを読み取る事ができるので、
レイヤー番号を設定しておいて判別させます。
PLAY中のアンドロイドの動きなんですが、
足がRayを突き抜ける状態は、壁ジャンプ中なので空中に浮いてる時になります。
足元のフラグとしては、接地してないのでfalseを返します。
Body以外の接触なら接地してる状態なのでtrueを返します。
なにも接触してなければ当然falseになります。
これでPLAYすると壁ジャンプも問題なく、
壁の縁に乗っても走りだしてくれるようになりました。(^ё^) ♪♪
応用と言っては、なんですが、
レイヤー判別を利用するとギミックの処理にも利用できそうです。
例えば、トランポリンやジャンプ台、坂道、移動床etc
この辺り悩んでいる方がいれば、応用して頂けると幸いかと思います。
ただ注意点も。
Rayに接触するオブジェクトが増えるとリソースも使うって事になります。
同時に接触する全てのCollider情報を取得して格納するので、
細かいオブジェクトを多数接触させると重くなります。
この辺りはゲーム性なんかを考慮して使うか使わないか判断した方がいいように思います。
RayのCollider判別は以上となります。
まだまだ記事に出来ない、細かなバグがあるので、
修正が終わるまで記事が書けないかも…
なにか新しいものが作れたら記事にしたいと思います。
それまでは、(^.^/)))~~~bye!!
この記事へのコメント