Unityでマウスクリックした位置にキャラクターを移動させる方法

今まではキーボードの移動キーを押したらキャラクターを移動させていました。

市販のゲーム機であればコントローラを使ってゲームをするのは当たり前ですが、
パソコンのゲームやスマートフォンのゲームでは専用のコントローラーではなくマウスを使った移動や画面を触って移動させる場合もあるかと思います。

そんなわけで今回はマウスクリック時にクリックした位置にキャラクターを移動させる機能を作成したいと思います。

また、マウスクリック時ではなく常にマウスを移動した位置にキャラクターを移動させたい場合もあると思うので、切り替えモードを作ります。

今までの記事をご覧いただいている方はキャラクターに設定しているアニメーターコントローラをそのまま使います。
キャラクター操作スクリプトは新しく作りますので、キーボード操作で動かしていたMoveTestをオフにして、新しいスクリプトを作り設定してください。

もちろん元々のMoveTestを改造してマウスクリック操作に切り替えるのもいいと思います。

この記事からご覧頂いた方は
キャラクターにはCharacterControllerとアニメーターコントローラが設定されている必要がありますので設定してください。

アニメーターコントローラーは

Unityのアニメーションの切り替えシステムとスクリプト
Unityのアニメーションを切り替える為のアニメーターの設定とアニメーションの遷移をさせるスクリプトの作成を行います

を参考にして作成し設定してください。

スポンサーリンク

キャラクター操作スクリプトMouseMoveを作成する

キャラクターの設定が出来ていればあとはキャラクター操作スクリプトを作るだけです。
キャラクター操作スクリプトMouseMoveを作成します。

public var mouseDownMode : boolean;
public var smoothRotateMode : boolean;
public var smoothRotateValue : float;

mouseDownModeはマウスクリックで移動の位置を決定するかどうかで、このモードがオフだとマウスクリックする必要はなく、マウスを動かした位置に移動します。

smoothRotateModeは移動先の方向にキャラクターを向ける時、徐々に角度を変えるかどうかです。
オフだと一気に移動先の方向を向きます。

SmoothRotateValueは1秒間にどれだけの角度を変更するかの度合いです。

if(Input.GetButton(“Fire1”) || !mouseDownMode) {

ここではInput.GetButton(“Fire1”)を使用して攻撃ボタン(デフォルトはマウスの左クリック)が押された時にしていますが、マウスの左クリックと限定したい場合は

Input.GetMouseButtonDown(0)

とします。

移動する目的地を設定する部分です。

if(Physics.Raycast(ray, hit, rayRange)) {
 targetPosition = hit.point;
}

Physics.Raycastはある位置からある方向にRay(線)を飛ばし何か他のゲームオブジェクトにぶつかったかどうかを調べます。
何かにぶつかった時は戻り値にtrueが返ってくるので、ぶつかった位置をtargetPositionに設定します。

Physics.Raycastの引数について説明します。
最初の引数rayはif文実行前に作成していて、このクラスで、ある位置とある方向を設定します。
レイのクラスの作成は

var ray : Ray = new Ray(ある位置,ある方向);

としてレイを飛ばし始める位置と飛ばす方向を指定し作成します。
ですが、Physics.Raycastの第1引数はRay型の物を指定すればいいので、そのやり方でなくても指定は出来ます。

今回の場合は

var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);

を使っています。

カメラ.ScreenPointToRay(飛ばす位置)

は指定したカメラから引数で指定した飛ばす位置にレイを飛ばします。
戻り値がRay型で返ってくるので、これを使用します。

今回の場合はメインカメラ(Camera.mainで取得出来る)からマウスの位置(Input.mousePositionで取得出来る)のRayを作成しています。

hitはRaycastHit型の変数でPhysics.Raycastの引数に指定するとぶつかった相手の情報がhitに代入されます。
rayRangeはレイを飛ばす距離です。

今回は100mにしていますが、値を小さくすると近い場所しか反応しないような仕様にする事が出来ます。

Physics.Raycastはいくつかコンストラクタが用意されており設定する引数の型や個数も変わります。
Ray型の引数を作成せず、飛ばす位置と方向を別々に指定したり、特定のレイヤーに設定されたゲームオブジェクトのみレイの当たり判定をするという事も出来ます。

Physics.Raycastに関しては

Unityでよく使う便利な標準関数について
管理人のかめくめちゃんがUnityのゲームを作成する時によく使う関数を紹介します

も参考にしてください。

位置から方向を計算する処理、位置?方向?わけわからん!

キャラクターの向きに関する処理を見てみます。

moveDirection = (targetPosition – transform.position).normalized;
velocity = Vector3(moveDirection.x * speed, velocity.y, moveDirection.z * speed);

最初に移動先の位置から自分自身の位置を引いた位置のnormalizedプロパティをmoveDirectionに代入します。

移動先の位置-自分自身の位置

で移動先の方向が算出出来ます。
その方向のnormalizedプロパティを指定するとベクトルが正規化されて方向だけが算出出来ます。

velocityは向いている方向にspeedをかけた値を設定しますが、Y座標だけは重力のみの移動にする為velocity.yを指定します。

スムースにキャラクターの向きを変える場合は現在の向いている角度から移動先の角度に少しづつ回転させます。

Quaternion.RotateTowardsを使うとスムースに角度を計算してくれるので、その値を自分自身の角度に代入します。

Vector3(moveDirection.x, 0, moveDirection.z)

とY座標を0としているのは、Y座標をmoveDirectionの値で計算してしまうと、移動先の方向が高い位置にあった場合キャラクターが上の方を向いてしまうからです。
分かりづらい方は

Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(moveDirection))

を指定して高い所をマウスクリックして試してみるといいかもしれません。

スムースに移動させない場合は

transform.LookAt(transform.position + Vector3(moveDirection.x, 0, moveDirection.z));

とキャラクターを即座に移動先の方向に向かせています。

ここで方向について考えたいと思います。
目的地をtargetというVector3型の変数で宣言されているとします。

主人公の位置はtransform.positionで取得出来ます。主人公から目的地の方向を調べたい時は

target – transform.position

で計算出来ます。

方向と位置は両方ともVector3で取得するので混乱しますが、「方向」もよく考えれば「そちら方の位置」を表しているのでそうなります。

相手の方向=相手の位置 – 自分の位置

と考えるとわかりやすくなります。

transform.LookAtは引数に向かせたい位置を指定します。例えば敵キャラをtekiという名前にしていたら
主人公を敵キャラの方に向かせたい場合

transform.LookAt(teki.transform.position)

と指定します。

角度をスムースに変更する時に使用している

Quaternion.LookRotation

は引数に指定した位置の方向を計算します。(Z方向がUnityでは向いている方向になる)
今回であれば

Quaternion.LookRotation(Vector3(moveDirection.x, 0, moveDirection.z))

としています。

引数にはY座標を0とした移動先の位置を指定しています。
移動先の位置を指定すれば移動先の向いている方向が計算されます。

位置を指定して向いている方向!?何言ってんだ!!となるかもしれませんが、
UnityではZ方向が向いている方向になりますのでこれでmoveDirection(移動先の方向)の方向が計算出来ます。

分かりづらくなるのは引数にVector3で指定しているからだと思います。
元々はmoveDirectionに計算した移動先の向きが入っているはずだからと考えればわかるかと思います。

TransformのインスペクタではX、Y、Zとなっていますが、この値を直接操作するより
Quaternion値で操作するみたいです。

なんだかんだわかってる風に言っていまsが、方向の計算はわたくしもよく混乱します。(^_^;)

マウスクリックで移動させる機能が完成したので確認する

これで移動スクリプトが完成したので、キャラクターに追加してインスペクタに変数の値をセットします。

マウス移動1

speedに3
mouseDownModeにチェック
smoothRotateModeにチェック
smoothRotateValueを360(1秒間に360度回転する)

にしてUnityの実行ボタンを押します。

マウス移動2

上のようにマウスをクリックした位置に移動し、キャラクターの向く方向がなめらかに変更されます。

マウス移動3

上の画像はsmoothRotateModeをOffにした場合です。
キャラクターの向きが一気に変わっています。

mouseDownModeをオフにするとマウスをクリック(厳密には押した時点)しなくてもマウスの位置にキャラクターが移動します。
このモードにするとキャラクターが止まる事はないので永遠に動き続けます。

またアニメーションもずっと走っている状態になります。
上の動画ではマウス操作で移動しているかは確認出来ないので、試してみてください(^^)/