はじめに
オブジェクトを水平方向(前後左右)に移動させる際、AddForce()
にて力を加えていたため、移動キーを入力し続けると際限なく加速し続け、限界突破してしまう。
そのため、rigidbody.velocity.magnitude
にてオブジェクトの速度を取得し、一定の速度を超えないようにプログラムを書こうと思ったが、上下方向の速度、つまりジャンプも考慮されてしまい、ジャンプした際に高さが低くなってしまう。
そこで、特定の平面(xz平面)に関してのみ上限速度を設定してみた。
内容
非常に単純な実装で対応できた。要するに任意の平面に関しての速度を計算し、上限の速度を超えた際はrb.velocity
の各値を調整する。
public class PlayerMoveController : MonoBehaviour
{
void FixedUpdate()
{
// 移動速度設定
rb.AddForce(playerSpeedSide, playerJumpPower, playerSpeedFront);
// 移動速度上限チェック
float horizontalSpeed = (float)Math.Sqrt(Math.Pow(rb.velocity.x, 2) + Math.Pow(rb.velocity.z, 2));
if (horizontalSpeed > Main.PLAYER_SPEED_MAX)
{
rb.velocity = new Vector3(
rb.velocity.x / (horizontalSpeed / Main.PLAYER_SPEED_MAX),
rb.velocity.y,
rb.velocity.z / (horizontalSpeed / Main.PLAYER_SPEED_MAX)
);
}
}
}
詳細
まず、通常通りAddForce()
にて力を加える。その後、現在の特定の平面の速度を計算し、上限と比較する。
もし上限を超えていた場合、velocity
の各値を調整する。
1. 特定平面に関する速度
float horizontalSpeed = (float)Math.Sqrt(
Math.Pow(rb.velocity.x, 2) + Math.Pow(rb.velocity.z, 2)
);
今回はxz平面の速度を制限したいので、x方向とz方向の速度を合成して算出する。やっていることはただのベクトルの合成となる。(それぞれの速度をvx,vzとする場合、√(vx^2+vz^2)となる。)
2. 速度の制限
if (horizontalSpeed > Main.PLAYER_SPEED_MAX)
{
rb.velocity = new Vector3(
rb.velocity.x / (horizontalSpeed / Main.PLAYER_SPEED_MAX),
rb.velocity.y,
rb.velocity.z / (horizontalSpeed / Main.PLAYER_SPEED_MAX)
);
}
上限を超えた分だけ、各方向の速度を制限する。
例えば、vxが9, vzが12, 上限が5だった場合、平面に関する速度は15となる。
この場合、上限が5なので、vx,vzそれぞれを15/5 = 3で割り、vx=3, vz=4となるため、方向を変えずに速度を制限することができる。
まとめ
これで、ジャンプに関する挙動はそのままに速度制限ができる。限界突破せずに安心して世界を移動できる。