Unityのゲームで上下に動く床、ベルトコンベアーを作成する

アクションゲーム等によくある床が上下に動いたり、ベルトコンベアーのようにキャラクターを押し戻すような機能をUnityで作成していきたいと思います。

床から床へと飛び移っていくようなアクションゲームでこの機能があるとより楽しくなりそうですね♪

逆に操作性が悪いとストレスが発生する原因ともなりかねませんが・・・・(^_^;)

スポンサーリンク

キャラクターをCharacterControllerで動かしている弊害

キャラクターをCharacterControllerで動かしている場合は外部からの力を受けないし、こちらから相手に影響を与える事が出来ません。

Rigidobody+CapsuleColliderで動かしている場合はRigidbodyコンポーネントを持っているので、外部からの力、こちらからの力を働かせる事が出来ます。

CharacterControllerを使ってキャラクターを動かしている場合は相手方でOnTriggerEnterやOnCollisionEnter等で検知をする事が出来ません。
(コライダのIsTriggerにチェックが入ってない物理的な判定をしている場合)

つまりベルトコンベアーを作成してキャラクターを検知しようと思っても検知が出来ないんです。

空間に見えないコライダを設置しIsTriggerにチェックを入れて検知するという事も出来ますが、全部に検知エリアを作るのは大変です。

こりゃまいりましたね・・・・((+_+))

これではキャラクターが床と接触しているかどうか?を検知出来ません。

しかし、CharacterControllerコンポーネントを持っているキャラクターは
何かと接触した時にOnControllerColliderHitという関数を呼び出します。

キャラクター側でこのOnControllerColliderHit関数を作成し、ベルトコンベアーの床の上に乗ったかどうかを検知するようにします。

ここまではCharacterContllerを持ったキャラクターの接触判定について見てきました。

上下に動く床を作成する

ベルトコンベアーの処理はとりあえず置いておいて、まずは上下に動く床の作成からしてみましょう。

上下に動く床の作成

↑のように空のゲームオブジェクト(MoveBlocks)、子要素にCubeを2つ作成します。

実際の動かすスクリプトを設定するのはMoveBlocksで子要素にはスクリプトは設定しません。

親要素が動くと子要素も相対的に動くのでCubeとCube(1)は同じように動く事になります。

親要素にRigidbodyとスクリプトを追加

↑がMoveBlocksのインスペクタです。

MoveBlocksのtransform.positionの値を直に変更してオブジェクトを動かす事も出来ますが、transform.positionで動かす場合は
物体に力を加えて動かすのではなくパラメータ値を変更して細かいワープをしているという感じになります。

なので、他のゲームオブジェクトからの影響を受けたい、または与えたい場合はtransform.positionの更新で動かさない方がいいかもしれません。

そもそも動く物体の場合はRigidbodyを取りつけて動かした方がいいみたいです。

Rigidbodyが取り付けられていないゲームオブジェクトは動かないものとして取り扱われているので、もし動かすと処理速度にも影響するかも?

というわけで、今回はRigidbodyコンポーネントを取りつけその機能で床を動かしたいと思います。

また、RigidbodyのIs Kinematicにチェックを入れておきます。

ここで入れておかないとキャラクターが床とぶつかった場合にその影響を受けて床が移動してしまいます。

MoveBlocksには新しくMoveBlockスクリプトを作り取り付けてください。スクリプトは後で作成します。

実際の動くブロックの様子

↑が実際の床の画像です。

階段にして上下に動くようにします。

床を上下に動かす為のスクリプトMoveBlockを作成

それでは床を上下に動かすスクリプトMoveBlockを作成していきましょう。

MoveBlockのRigidbodyコンポーネントを取得してrb変数に参照を入れます。

FixedUpdate関数はUpdate関数と似たものでフレーム毎に呼ばれる関数ですが、固定フレームレートで呼ばれるみたいです。

Rigidbody等で物体を動かす時はこちらを使用した方がいいようです。

RigidbodyのMovePosition関数で指定した位置に移動するようにしています。

指定している位置はX座標、Z座標はMoveBlockの位置をそのままにし、Y座標は

Mathf.PingPong(Time.time, 2)

の値を設定しています。

Mathf.PingPongは卓球のピンポンと同じで第1引数に指定した値を、0から第2引数で指定した値の間で設定します。

つまり上限までいったら跳ね返った値を返します。

例えば第1引数を4にすれば0が返ってきて、3にすれば1が値として返ってきます。

今回の場合Time.timeとUnity実行開始時からの時間を設定しているので、時間の経過と共に0~2の値が繰り返されるという事になります。

これでスクリプトが出来上がったので床の動きを確認してみましょう。

床がちゃんと動くか確認する

↑のように初期位置から上に2m上がり、その後に最初の位置まで戻るというのを繰り返しています。

キャラクターを上下に動く床にジャンプさせて登らせてみましょう。

Unityでキャラクターがジャンプ出来るようにする
Unityのゲームでキャラクターがジャンプ出来るようにする機能を作成します。

ジャンプ機能に関しては↑の記事を参考にしてください。

キャラクターを動く床に乗せてみる

↑のようにキャラクターが床にジャンプして登れるようになりました。

しかし、残念ながら床の下からジャンプをすると床をすり抜けて床の上に移動してしまいます。

現状では対処法が見つからないので、キャラクターを動く床の下に移動出来なくさせたり、床の下だとジャンプ出来ないようにするしかないかもしれません。

単純に左側の床の下にいて上から床がせまってくるとキャラクターと床が衝突し、居所をなくしたキャラクターが床の上に移動してしまいますね・・・(^_^;)

Rigidbody+CapsuleColliderでキャラクターを動かしている場合はブロックの影響を受けてキャラクターがはじかれるので問題はなさそうですが、CharacterControllerの場合は相手の力の影響を受けないのでこういう風になってしまうのかもしれません。

衝突の影響を受けたいならRigid+Capsuleに変更するのがいいのかも?

Rigidbody+Capsuleコライダでキャラクターを動かすには

キャラ操作をCharacterControllerからRigidbody+コライダに変更する
Unityでキャラクターを操作する時CharacterControllerを使ってきましたが、物理的な影響を得る為にRigidbody+CapsuleColliderでキャラクターの移動、ジャンプ、坂や段差を登れるようにしてみます。

↑を参照してください。

とりあえずこれで上下に動く床の作成が完了しました。

ベルトコンベアーの床を作成する

次はベルトコンベアーのような床を作成したいと思います。

ヒエラルキー上で右クリック→3D Object→Cubeで平べったい床を作成します。

名前をBeltConveyorにします。
また、BeltConveyorのタグにはBlockを設定します(新しいタグを作成し設定してください)。

Localに変更する

BeltConveyorを選択した状態でUnity画面の左上の方にある↑のボタンがLocalになっている事を確認します。

ベルトコンベアー

↑がBeltConveyorです。

青い矢印の方向にキャラクターを動かすので、床を回転させてキャラクターを動かしたい方向に青い矢印が来るようにBeltConveyorを回転します。

キャラクター操作スクリプトにベルトコンベアーを検知する処理を追加

記事の最初の方で言及しましたが、床からはキャラクターとの接触を検知出来ないのでキャラクター側のスクリプトで床と接触したかどうか判断します。

キャラクター操作スクリプトに↑のような変数を宣言します。
onTheFloorは動く床の上にいるかどうかのフラグです。

floorMoveDirectionはキャラクターが乗っている床の動いている方向を入れる変数です。

↑のようにキャラクターの移動処理をした後に動く床の上にいた場合は再度ベルトコンベアーが動いている方向にキャラクターを動かします。

今回はCharacterControllerのMove関数で動かしましたが、velocityの値を変更してMoveを2回呼ばないようにするというのでもいいかもしれません。

↑がキャラクターが他のコライダと接触した時に呼ばれる関数です。
ControllerColliderHit型の引数を受け取ります。

接触した相手のコライダに設定されているのがベルトコンベアーに設定したタグのBlockであった時に
ベルトコンベアーに設定されているBeltConveyorスクリプトのConveyor関数を呼び出します。

これは後で作成しますが、ベルトコンベアーの流れる向きを取得出来ます。

その値をfloorMoveDirectionに入れてonTheFloorをtrueにします。
接触したのがBlock出なければonTheFloorをfalseにします。

ベルトコンベアーの流れている方向を返すスクリプトBeltConveyorを作成する

それではBeltCoveyorスクリプトを作成します。

↑のようにBeltConveyorの前方の向きを返しているだけです。

これでベルトコンベアーの機能が出来たので、Unityの実行ボタンを押して確認してみましょう。

ベルトコンベアーの機能を確認する

↑のようにキャラクターがベルトコンベアーの上に乗ると左側に移動するようになりました。

ベルトコンベアーの流れている方向を視覚的にわかりやすくする

しかしこのままだとベルトコンベアーがどちらの方に動いているのかわかりません。

そこでベルトコンベアーにマテリアルを設定し、そのマテリアルを切り替える事でベルトコンベアーが動いているように見せかけましょう。

動く床のマテリアル用画像1

↑が最初のマテリアルです。

動く床用のマテリアル用画像2

↑の2つの画像のように線が流れるような画像を2つ作ります。
BeltConveyorオブジェクトの角度と画像の方向を合わせる必要があります。

合わない場合は画像を回転させて再度Unityに取り込むか、BeltConveyorの動く向きを変えるかどちらかをしてください。

滑らかな動きにしたい場合は画像をもう少し増やしてください。

わたくしの作った適当な画像をサンプルとして使ってもかまいません。

画像が出来たらUnityに取り込み、ProjectのAssetsエリアの上で右クリック→Create→Materialを選択します。

MoveFloor1とMoveFloor2という名前のマテリアルを作ります。

MoveFloor1のインスペクタ

次にMoveFloor1のAlbedoにさきほど取り込んだMoveFloor1の画像、MoveFloor2のAlbedoにMoveFloor2の画像を指定します。

ベルトコンベアーのマテリアルを変更する処理を追加

それでは、ベルトコンベアースクリプトのBeltConveyorにマテリアルを変更する処理を追加しましょう。

変更するマテリアルはpublicで宣言し、インスペクタで設定出来るようにします。
マテリアルの変更は一定時間が来たら変更しています。

マテリアルの変更には

mesh.material

を変える事で出来るようになります。

これでスクリプトが出来たのでBeltConveyorオブジェクトを選択しインスペクタでマテリアル等の設定をしてください。

BeltConveyorのインスペクタにパラメータを設定する

BeltConveyorは↑のようになりました。

実行して確認

これで設定が完了したので、Unityを実行して確認してみましょう。

ベルトコンベアーのマテリアルが変更されるか確認する

↑が実行結果です。

ベルトコンベアーがどちらに流れているかわかるようになりました!

画像が汚いのであまり流れてる感が出てないような気もしますが・・・・。

また、錯覚で右に流れているように見える事も・・・・さすがにそれはなさそうです・・・。

錯覚するベルトコンベアーを作成する

さきほど錯覚で右に流れているように見える事もと書きましたが、実際にそれを行ってみましょう。

本当は錯覚させたいのではなくもう少し綺麗な絵にしたいという事だったんですが・・・(^_^;)

ベルトコンベアー3

ベルトコンベアー4

ベルトコンベアー5

↑のように3色で塗られた床を3パターン用意しUnityに取り込みます(上の画像はダウンロードして使って頂いてかまいません)。

記事の背景色と1色がかぶっているので解り辛くなってますね・・。

Unityに取り込んだらMoveFloor3~MoveFloor5のマテリアルを作成し、それぞれのマテリアルのAlbedoに取り込んだ画像を設定します。

ここまではさきほどもやったので問題ないと思います。

次にマテリアルの設定を変更します。

ベルトコンベアー用のマテリアルの設定

マテリアルのMoveFloor3~MoveFloor5のインスペクタを開きTilingのYを3にします。

Tilingの数を3にしたので、マテリアルには元の画像がY方向に同じパターンが3つ並ぶようになります。
(向きによってはXの値を変更する必要があるかも)

その為MoveFloor1やMoveFloor2のようにパターンを自分で作成しなくても1つのパターンを作りマテリアルの設定でそのパターンを連続させる事が出来ます。

それでは作成したマテリアルをBeltConveyorスクリプトのMaterialに設定し、動きを確認してみます。

3色パターンのベルトコンベアー

↑のように同じ模様でテクスチャが張られるようになりました。

1つのパターンをループしてテクスチャとして使いたい時にTilingを使うと便利ですね。

今度は錯覚で左にも右にも動いているように見えます・・・・。

これはどうやって左に流れてるように見せればいいでしょうかね・・・・(^_^;)

とりあえずこれで上下に動く床とベルトコンベアーの機能が完成しました。