Unityエディターのバージョン:2022.3.16f1
Y座標の移動を検知するために前のフレームと現在のフレームを比較します
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DetectYMove : MonoBehaviour
{
//判定に含まれるフレームの数
const int PreviousFramesNum = 3;
//判定の閾値
const float Threshold = 0.01f;
//前のフレームのY座標
float[] previousYPositions = new float[PreviousFramesNum];
// Start is called before the first frame update
void Start()
{
//Y座標を初期化する
for(int i = 0; i < PreviousFramesNum; i++) previousYPositions[i] = transform.position.y;
}
// Update is called once per frame
void Update()
{
//現在のY座標を取得する
previousYPositions[0] = transform.position.y;
//Y座標の差が閾値を超えていたら移動中と判定する
for (int i = 0; i < PreviousFramesNum - 1; i++)
{
if (Mathf.Abs(previousYPositions[i] - previousYPositions[i + 1]) > Threshold)
{
Debug.Log("Y座標の移動がありました");
break;
}
}
//前のフレームを更新する
for(int i = PreviousFramesNum - 1; i > 0; i--)
{
previousYPositions[i] = previousYPositions[i - 1];
}
}
}
PreviousFramesNum・・・判定に含まれるフレームの数
Threshold・・・動いたと判定されるY座標の差の閾値
どちらも大きすぎても小さすぎてもだめなので、小さい数から試してみるのがいいと思います。今回はそれぞれ3と0.01でなめらかに動きました。
このコードは接地判定のために書きました。コライダーで上手くいったらよかったのですが、ブロックの側面に触れたときも地面についていると判定されてしまって、コライダーの大きさや形を色々ためしても上手くいかなかったのでY座標の移動があるかで判定しました。この方法で接地判定をする場合は、「Y座標の差が閾値を超えていたら移動中と判定する」の部分を以下のように変更すればできます。
//Y座標の差を判定してisGroundedを更新
for (int i = 0; i < PreviousFramesNum - 1; i++)
{
if (Mathf.Abs(previousYPositions[i] - previousYPositions[i + 1]) > Threshold)
{
isGrounded = false;
//一度でも変化が閾値を超えたら地面にいない
break;
}
else
{
isGrounded = true;
}
}