UnityのCharacterControllerコンポーネントを使うと衝突判定をするコライダと移動機能がついているので、キャラクターを動かす時に非常に便利です。
ですが、CharacterControllerを使ったキャラクターの移動処理であることをすると原因不明のバグが発生し、長い間悩まされるかもしれません。(^_^;)
そんなわけで今回はそのことについて簡単ではありますが書き残しておこうと思います。
キャラクターの移動で原因不明のバグ?
そもそも今回の記事を書いたのはコメント欄に質問があって、記事の通りに作って問題が出ないかを確認していた時でした。
その記事はキャラクターのワープ機能を作成するというものです。
上の記事ではワープ領域に入ったらエフェクトを表示し、ワープ先に移動するというものですが、ワープ領域にキャラクターが入ってもなぜかキャラクターだけその場に残ってしまいました。
既に上の記事のスクリプトは修正済です。
しかもこれ、ワープする時とワープしない時があります。
単純にワープしないのが100%ならワープ処理が実行されていないだけなので、処理されるようにするだけなので簡単なんですが、どちらもされてしまうというので少しハマりました。
スクリプトではワープする時に、以下のようにキャラクターの位置と角度をワープ先の位置と角度に変更しています。
1 2 3 4 5 6 7 8 9 | void Warp() { transform.position = warpPoint.position; transform.rotation = warpPoint.rotation; // 移動先でワープパーティクルの表示 instantiateParticle.InstantiateWarpParticle(transform.position); SetState(WarpCharaState.Normal); } |
この時にDebug.Logでtransform.positionとwarpPoint.positionの両方を出力するとどちらもワープ先の位置を表示します。
ただ、なぜかキャラクターが元のワープ元に留まるという事が起きていて、原因がまったくわかりません。
実はCharacterControllerを使っていて、上のようなスクリプトでキャラクターの位置を直接移動させた時に不具合が出るのは最初ではなく、ユニティちゃんのRPGを作ってみようのカテゴリでも同じような機能を作った時に発生しました。
どうやらCharacterControllerを使っているとこれが発生しているようです。
というわけで、UnityのスクリプトリファレンスでCharacterControllerを調べてみました。
上のページで英語で書かれている部分をGoogle翻訳してみると
CharacterControllerは力の影響を受けず、Move関数を呼び出したときにのみ移動します。その後、動きを実行しますが、衝突によって拘束されます。
となっています。
おそらくCharacterControllerコンポーネントを使った移動をさせる場合はMoveやSimpleMoveを使った移動のみで、直接位置を変更してはダメなのかもしれません(CharacterControllerで位置の処理がされている?)。
UnityのマニュアルのCharacterControllerのページのヒントに
自身でスクリプトを記述したとき、キャラクターコントローラーが物理特性を使用して、オブジェクトに影響する場合があります。
という記述もあります。
transform.positionを直接変更する時の対処法
CharacterControllerコンポーネントの機能で位置を直接変更するメソッド等がないようなので、ワープ機能等で位置を直接変更したい時は
一旦CharacterControllerコンポーネントを無効にする→transform.positionの位置を変更する→移動が完了したらCharacterControllerコンポーネントを有効にする
というのがよさそうです。
以下がその流れをスクリプトで記述した例です。
1 2 3 4 5 6 7 8 | // CharacterControllerコンポーネントを一旦無効化する characterController.enabled = false; // キャラクターの位置を変更する transform.position = warpPoint.position; // CharacterControllerコンポーネントを有効化する characterController.enabled = true; |
終わりに
CharacterControllerを使っている時の位置の直接変更でこうなるとは思いませんでした。
というか、そもそもこれが原因かもわかりませんが・・・・(^_^;)
とりあえずこれで対処出来ていればいいのですが・・・・・(-_-)