【Unity】CharacterControllerのisGroundedは初期状態では false でファイナルアンサー!

isGrounded.png

 Unityには、3Dアクションゲームを簡単に構築できるよう「Character Controller」というコンポーネントが備わっています。キャラクターが階段や坂道を登る時の動作や、地面と接地しているかの判定などを扱ってくれます。

 今回はその中の一つ「isGrounded」が若干じゃじゃ馬ということで挙動を理解しようと思います。

Character Controller の isGrounded を理解する

  1. KuroMikanの環境
  2. 使ってみる

KuroMikanの環境

  • Windows10 Home Edition
  • Unity 2019.4.1f1(LTS)

使ってみる

3DモデルのプレハブにCharacter Controllerコンポーネントを追加することで使えるようになります。
Add Component > Physics > Character Controller

これによってキャラクターを移動させたりジャンプさせたりといった一連の機能にアクセスできるようになります。
「isGrounded」は地面と接地していれば「true」、接地していなければ「false」を返す関数で、これを使うことで「地面に接地しているときだけキー入力を受け付ける」といったことができます。

ぴったり地面と接地していなければならない、ということだったのでぴったり地面と接地させて実行してみました。

isGrounded1.png

超ぴったり。

でも、実行結果は false 

positionを超細かく調整して true になる座標を入力しても、実行すると false 。

どうやら isGrounded は初期状態では接地してようがしてまいが false であると思ったほうが良さそうです。対策としては、常に自由落下の処理を入れるようにします。
    void Update()
{
if (controller.isGrounded)
{
// 移動とかジャンプの処理
}
// 自由落下
moveDirection.y -= gravity * Time.deltaTime;
// 移動処理
Vector3 globalDirection = transform.TransformDirection(moveDirection);
controller.Move(globalDirection * Time.deltaTime);
// 接地したら落下停止
if (controller.isGrounded) moveDirection.y = 0;
   }
これにより、isGrounded が無事 true になりました。
どうやら Character Controller は Ridigbody と違って自動で重力の影響を受けないため、自由落下の処理を用意してあげないといけないのでした。

今回はこれで上手くいったのですが、下り坂を降りると false になる、という現象が起こるようです。

isGrounded2.png

この赤矢印の距離の分だけ「浮いている」と判断されている可能性があります。
この対策としては、下記の2つがあるそうです。


対策 1
Physics.Linecast で仮想的な光線を飛ばして衝突を調べます。
Physics.Linecast(開始地点, 終了地点)
開始視点を若干めり込ませた位置に設定し、地面に向かって短距離だけRayを飛ばして判定します。
Update関数内でRayを飛ばしまくるのはどうなんだって話があるので、その対策は必要かもしれません。


対策 2
isGrounded が true の時にキャラをオフセットで下方向に移動させ、無理やり接地させます。
🔍参考にさせていただいたサイトではこの方法が良さそうという結論になっていました。


Character Controllerを使ってみて感じたことは、初心者~中級者くらいまでが使うコンポーネントなのかなと思いました。Rigidbodyと比べると動作が少し大雑把なので、精緻な処理を実現したいならイチからRigidbodyで組み上げたほうが良いでしょう。