【Unity】壁をよじ登らせる

前回、壁の上端まで登った所で止める処理を作りました。
ここからは、少し手間のかかるよじ登りのモーションを作ってみます。

正直、出来がよくないので少し恥ずかしいのですが、
ま、今まで作った処理も出来がよくないので、
構わず記事にしようと思います。
(;^o^) \(ToT )あんたほんとにそれでいいの

よじ登りなんですが、
壁の上端で停止 → 手を壁の縁に掛ける → Animationで登る動き

と、こんな流れで簡単に作れそうです。
早速、Animationを作っていきます。
よじ登り①.jpg
サンプルレートを10に設定して、0:1毎にモーションを作ります。
サンプルレートを10にしておくと0:1=0.1秒で計算しやすいからでっす。

アンドロイド君の白背景がColliderの範囲になります。
まず、壁の上に手を掛けないと登れないので、
Collider範囲の右側より外に手を出しておきます。

壁に張り付いている時は、手が掛けやすいのですが、
飛びついた場合は、壁とアンドロイドの距離が開くので、
手が届かない事が起こります。

なので、手を掛ける部分を0.2秒ほどキープしておいて、
壁に掛かるようにします。

これでモーションができたので、スクリプトを作ります。
ActionTest

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

public class ActionTest : MonoBehaviour
{
//よじ登り関連
private float clingProgress; //壁登り終了処理経過時間
private bool risingStop; //上昇停止フラグ
private bool clingMode; //壁登りモード
private int clingPattern; //よじ登りモーションのパターン

private const string CLIP_KEY="Action"; //Animatorの変数名

void Update()
{
//よじ登りモーション
if (clingMode)
{
ClingWallMotion();
return;
}
}

private void FixedUpdate()
{
MoveProcessing();

if (jump)
{
JumpMotion();
}

if (risingStop)
{
playerRB.velocity = new Vector2(playerRB.velocity.x, 0f);
risingStop = false;
}
}

//よじ登り処理
private void ClingWallMotion()
{
clingProgress += Time.deltaTime;

wallCollider.SetActive(false);

motion.SetInteger(CLIP_KEY, clingPattern);

if (clingProgress > 0.6f)
{
clingProgress = 0f;
clingMode = false;
}
}

//Waistセンサーが反応したら
public void WallTop(int clipNumber)
{
clingPattern = clipNumber;
risingStop = true;
clingMode = true;
}
}

説明すると、
まず、腰のセンサーがトリガーに接触するとWallTop関数に情報を流します。
腰センサーからサインが来たら、各フラグをONにします。

このフラグをUpdateとFixedUpdateで監視しておいて、
発動させる感じです。

ClingWallMotion関数では、よじ登りのモーションを再生させるのですが、
壁用のColliderが邪魔になるのでfalseします。

今までは、AnimationChange関数を使ってクリップの切り替えを行っていましたが、
少し考えがあって、直接クリップ変更を行う事にしました。

clingPatternと言う整数型を使って、Animationのクリップナンバーを指定します。

続いて、腰センサーのスクリプトを修正します。
SensorCS

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

public class SensorCS : MonoBehaviour
{
public int clipNumber; //クリップナンバーInspectorで設定
public GameObject body; //アンドロイド本体
private ActionTest actionTestCS; //ActionTestスクリプト
private string wallTop = "WallTop"; //壁上端トリガータグ

// Start is called before the first frame update
void Start()
{
SensorSetting();
}

private void SensorSetting()
{
actionTestCS = body.GetComponent<ActionTest>();
}

private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == wallTop)
actionTestCS.WallTop(clipNumber);
}
}

修正点は、クリップナンバーの変数を追加して、
WallTop関数に渡す部分です。

Unityに戻って、腰に入れてるSensorCSのクリップナンバーを設定します。
よじ登り②.jpg
パブリックにしてるのでInspectorから設定します。
よじ登りのクリップナンバーは9になります。

準備ができたのでPLAYしてみます。
よじ登り③.jpg
手は掛かるのですが、体が持ち上がる前に滑って落ちて行きます。
(・_・;)エー

手が掛かればリフトして登るとばっかり思ってました。T^T)

ここでいろいろ試したのですが、
挙動がおかしくなるだけで、上手く行かなかったんですね~

これも10月から停滞していた一因でっす。

しかもBoneに設定したColliderを使いたいって欲が出て、
他の選択肢を無視していました。

年を越して、動くようにするのが一番って気づいて、
他の選択肢を導入する事にしました。
もっと早くやってれば… (- .-)ヾ ポリポリ

よじ登り④.jpg
よじ登り用のColliderを作りました。
オレンジ色のやつです。

これをAnimationで同時にリフトさせます。
よじ登り⑤.jpg
オレンジのColliderは、手の座標に合わせておいて、
後は、よじ登るタイミングに合わせて、上から下へ移動させます。
モーションを0.6秒で設定しましたが、
Colliderが下まで行ったままだと、次の呼び出しで上がってない場合があるので、
0.7秒にColliderを元の位置に戻すキーを追加しておきます。

これで、オレンジのColliderはY座標しか変化しないので、
上手くリフトしてくれるはずでっす。

このColliderは、通常時は邪魔になるので、
よじ登りモーションのときだけONにさせる必要があります。
また、クリップ再生の時間が0.7秒になったので、スクリプトを修正します。
ActionTest

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

public class ActionTest : MonoBehaviour
{
public GameObject clingCollider; //よじ登り補助Collider

//よじ登り処理
private void ClingWallMotion()
{
clingProgress += Time.deltaTime;

wallCollider.SetActive(false);

motion.SetInteger(CLIP_KEY, clingPattern);

if (clingProgress > 0.7f)
{
clingProgress = 0f;
clingMode = false;
clingCollider.SetActive(false);
}
}

//Waistセンサーが反応したら
public void WallTop(int clipNumber)
{
//よじ登りモードに入っていたら抜ける
if (clingMode) return;

clingCollider.SetActive(true);
clingPattern = clipNumber;
risingStop = true;
clingMode = true;
}
}

ClingColliderを追加して、
WallTop関数が呼び出されたらON、
よじ登りが終了したらOFFにします。

モーションの再生を0.7秒にしたいので、
clingProgressを0.7秒に設定すれば完了です。

スクリプトが修正できたのでPLAYしてみます。

モーションがショボイので見た目がイマイチですが、
一応は作る事ができました。

これで大きく飛び上がる事が無くなったので、
壁の上からジャンプさせる処理なんかも作れるようになりそうです。
よじ登りについては以上となります。


最後に、いろいろ試していて気付いたと言うか、
これはダメだってのがあったので、書いておこうと思います。

まず、Rigidbodyのある本体にBoneのColliderを設定しているので、
Animationでは、Colliderを動かす事になるんですが落とし穴があります。

本来、Rigidbodyの物理挙動をTransformで動かしてはいけないって事です。
実際にAnimationでよじ登りを作って登れたのを紹介します。
よじ登り⑥.jpg
少し説明すると、白背景がRigidbodyを積んだ本体になります。
要するにRigidbodyのある本体よりColliderを壁の上に乗せてしまえば良いって考えです。

立ち上がりまでColliderをRigidbodyより壁の上に置いておけば、
後は、Animationの最後で本体を戻せば上に乗ったままになると考えました。

実際、よじ登らせる事ができたのですが、
本体がColliderに追いついた所で、飛び上がってしまいました。

処理的には、Colliderを動かしただけなんですが、
実際には、Rigidbodyを引き寄せる動きになってしまっています。

Animationの処理は、Transformで動かす挙動なので、
RigidbodyをAnimationで動かすと物理力が計算されて、
跳ね上がる力が加わったと考えられます。

AnimationでColliderを動かす時は、Rigidbodyのある本体に影響が出ない
クリップを作成しないと挙動がおかしくなるので注意が必要になります。

また、Rigidbodyを積んでるColliderは、Animationで動かさない方がよさそうです。

Colliderだけを動かしていると思っていたんですが、
Rigidbodyまで動かしていたとは、精進が足りません(;^_^A アセアセ・・・

Animation処理をされる際は、Rigidbodyの動きに注意しておく事をおすすめします。
と書きましたが、知らなかったのは私だけかもしれないですね(T-T) グスッ

RigidbodyのあるキャラをAnimationで動かす時の参考にでもなれば幸いです。
それでは、今回はこの辺で。
(o・・o)/~マタネェ




この記事へのコメント