シンプルなアクションゲームを作ってみよう12-ゲームクリアとゲームオーバーエリアを作成する-

記事内に広告が含まれています。

シンプルなアクションゲームを作ってみようの第12回です。

今回はキャラクターがゲームのクリアエリアに到達したらゲームを終了する機能を作成していきます。

前回はゲームの舞台のゲームオブジェクトにPhysic Materialを設定しました。

シンプルなアクションゲームを作ってみよう11-PhysicMaterialを作成する-
シンプルなアクションゲームで使用するゲームの舞台にPhysic Material(物理マテリアル)を作り設定していきます。

シンプルなアクションゲームを作ってみようの他の記事は

シンプルなアクションゲームを作ってみよう

シンプルなアクションゲームを作るのを通してUnityの使い方を学ぶカテゴリです。

から参照出来ます。

スポンサーリンク

ゲームのクリアエリアの作成

キャラクターが到達したらゲームクリアとするエリアを作成します。

Stage1シーンのEnvironmentゲームオブジェクトを選択した状態で右クリックから3D Object→Cubeを選択し、名前をGoalAreaとします。

GoalAreaを作成

ヒエラルキーでGoalAreaを選択し、インスペクタで以下のように設定します。

GoalAreaのインスペクタの設定

Transformの値はゴールエリアの位置やサイズの調整の為の変更です。

またBox ColliderのIs Triggerにチェックを入れます。

Is Triggerにチェックを入れると他のゲームオブジェクトとの衝突が起きなくなり、スクリプトで他のゲームオブジェクトのコライダの検知に使用することが出来ます。

ゴールエリアはゴールの空間として使うので物理的に衝突をせず検知エリアとして使います。

GoalArea用のマテリアルの作成

ゴールエリアはゴールとする空間なので、半透明の表示にしたいと思います。

Assets/Materialsフォルダ内に右クリックからCreate→Materialを選択し、名前をGoalAreaとします。

GoalAreaマテリアルを選択し、インスペクタで色の変更と透明度の変更をします。

GoalAreaのマテリアルの設定をする

Rendering ModeをTransparentにし透明可能なモードにします。

次にAlbedoの横の白色部分を押し、新しく出てきたウインドウでR(赤)に255、G(緑)に0、B(青)に0、A(255で完全に見え、0で完全に見えない)に100を設定します。

設定する値は0~255の値を設定します。

これで少し透明な赤色のマテリアルが出来ます。

マテリアルが出来たら、ヒエラルキーのGoalAreaゲームオブジェクトにドラッグ&ドロップして設定します。

シーンビューで確認すると、以下のような位置とサイズと色合いになっているのを確認出来ます。

シーンビューでGoalAreaを確認する

ゲームオーバーエリアの作成

次にゲームオーバーするエリアを作成していきます。

今回作成したゲームの舞台は横に壁がないので、床を降りると永遠に落下するだけでゲームを進行できなくなります。

そこでゲームの舞台から落下した場合はゲームオーバーとします。

単純にキャラクターのYの位置が一定の値に達したらゲームオーバーとしてもいいんですが、今回はゲームオーバーエリアを作成し、その範囲にキャラクターが侵入したらゲームオーバーとすることにします。

Environmentゲームオブジェクトの子にあるWholeFloorゲームオブジェクトを選択した状態で右クリックから3D Object→Cubeを選択し、名前をGameOverAreaとします。

GameOverAreaゲームオブジェクトの作成

GameOverAreaを選択し、インスペクタでTransformの値の変更とBox ColliderのIs Triggerにチェックを入れます。

GameOverAreaのインスペクタの設定

GameOverAreaはキャラクターが侵入したかどうかの検知範囲に使用するので、Box ColliderのIs Triggerにチェックを入れています。

Transformの値は、ゲームの全体の床よりも大きいサイズにし、位置を少し下げる為の設定です。

GameOverAreaはキャラクターを検知するためだけのゲームオブジェクトなので見た目は必要ありません。

そこでインスペクタのCube(Mesh Filter)とMesh Rendererコンポーネントの右の3つの丸を押し、Remove Componentを選択し、削除します。

表示用コンポーネントの削除

GameOverAreaゲームオブジェクトのインスペクタは以下のようになり、

最終的なGameOverAreaのインスペクタ

シーンビューで確認するとWholeFloorの下にそれよりも大きいサイズのGameOverAreaがあるのを確認出来ます。

シーンビューでのGameOverAreaの確認

ゲームマネージャーの作成

ゲームのクリアやゲームに関する事を管理するGameManagerゲームオブジェクトを作成し、それにGameManagerスクリプトを取り付けて管理出来るようにします。

ヒエラルキーで右クリックからCreate Emptyを選択し、名前をGameManagerとします。

GameManagerゲームオブジェクトの作成

ゲームマネージャースクリプトの作成

次にAssets/ScriptsフォルダにGameManagerスクリプトを作成し、GameManagerゲームオブジェクトに取り付けます。

GameManagerスクリプトをGameManagerゲームオブジェクトに取り付ける

GameManagerという名前のスクリプトを作ると、他のスクリプトと違って歯車のアイコンになりますが、これは通常のスクリプトと変わりません。

UnityではGameManager(という名前)は重要なスクリプトなので、アイコンを別にしているのかもしれません。

GameManagerスクリプトのアイコンが変わる

GameManagerスクリプトに記述していきます。

GameOverプロパティはゲームオーバーかどうかを設定したり取得出来ます。

ClearGame、EndGameメソッドはそれぞれクリアした時、ゲームオーバーになった時に外部から呼び出します。

現時点ではGameOverプロパティにtrueを入れているだけです。

GameManagerスクリプトは、他の機能を追加していく過程で処理を追加していきます。

キャラクターを検知するスクリプトの作成

GoalAreaゲームオブジェクトとGameOverAreaゲームオブジェクトが出来たので、それぞれにキャラクターを検知するスクリプトを作っていきます。

GoalAreaスクリプトの作成

Assets/ScriptsフォルダにGoalAreaスクリプトを作成し、GoalAreaゲームオブジェクトに取り付けます。

GoalAreaスクリプトをGoalAreaゲームオブジェクトに取り付ける

gameManagerはGameManagerスクリプトを入れるフィールドです。

gameClearは一旦ゲームクリアと判定されたらtrueにし、次に同じ条件になっても再度クリアと判定しない為のフラグです。

StartメソッドではGameObject.Findを使ってGameManagerという名前のゲームオブジェクトを探し、そこからGetComponentでGameManagerスクリプトを取得しています。

GameObject.Findメソッドは非常に時間がかかる処理なのでStartメソッドで1回だけ実行しています。

もし処理が遅いようならばgameManagerフィールドに[SerializeField]アトリビュートを取り付けて、GoalAreaゲームオブジェクトのインスペクタのGoalAreaコンポーネントのgameManagerに直接GameManagerゲームオブジェクトをドラッグ&ドロップして設定しておくことも出来ます。

OnTriggerEnterメソッドは、GoalAreaスクリプトが取り付けられているゲームオブジェクトのコライダに、他のコライダを持つゲームオブジェクトが侵入した時に呼ばれるメソッドです。

説明が長くて分かり辛いかもしれませんが、要はゴールエリア内に他のコライダが入ってきたら呼ばれます。

Collider型の引数を受け取ります。

Collider型はCapsule ColliderやSphere Collider等のコンポーネント(スクリプト)の継承元になっている型で、親の型を引数として指定しておけば、そこから継承して作成したクラスの型は引数として受け取れるようになっています。

つまり、親の型にはそれを継承したクラスの型であれば代入できるという事です。

なので、どんなコライダであれ(Collider型を継承して作成されたコライダであれば)OnTriggerEnterメソッドの引数のColliderに値が渡されます。

!gameClearはゲームクリアをしていない状態。

other.CompareTag(“Player”)は、侵入したコライダのゲームオブジェクトのタグがPlayerかどうかで

&&記号(日本語だと かつ)でこれら二つの条件が両方成立していればtrueになります。

この処理は最初にgameClearかどうか判定し、そこでreturnしてそれ以降の処理をしない条件にし、その後コライダのタグを判定するのでも構いません。

&&記号

&&は左右の条件が両方成立した場合にtrueを返しますが、

上のように&ひとつでも出来ます。

上の場合は!gameClearの条件が成立しなくてもother.CompareTag(“Player”)の条件が成立するかも実行します。

&&の場合は最初の条件!gameClearがfalseになった時点で次のother.CompareTag(“Player”)は実行しません(通常はする必要がないので)。

なので、通常は&&で、他の条件の処理も実行する必要がある場合は&にします。

ゲームクリアしていない かつ 侵入したゲームオブジェクトのコライダのタグがPlayerだった場合はgameClearにtrueを入れ、GameManagerスクリプトのClearGameメソッドを呼び出しています。

ここでは&&(かつ)についてやりましたが||(または)の場合も同じで、||の場合は左右の条件のどちらかひとつがtrueになれば全体としてtrueになるので、||の左の条件がtrueになれば右の条件の処理は実行しません。

実行したい場合は|ひとつを使います。

GameOverAreaスクリプトの作成

Assets/ScriptsフォルダにGameOverAreaスクリプトを作成し、ヒエラルキーのGameOverAreaゲームオブジェクトに取り付けます。

GameOverAreaスクリプトをGameOverAreaゲームオブジェクトに取り付ける

GameOverAreaスクリプトを作成していきます。

ほぼGoalAreaスクリプトと同じなので説明は割愛させて頂きます。

違う部分はGameManagerのEndGameメソッドを呼んでいる部分だけです。

GoalAreaスクリプトとGameOverAreaスクリプトはプレイヤーを検知し、何らかの処理を実行するという目的は同じなので、インスペクタで「ゴールにするのか」、「ゲームオーバーにするのか」の設定を出来るようにし、その設定によって処理をif文で分岐して、実行したい処理を分けるというやり方も出来ます。

今回は設定するスクリプトを分けました。

タグを設定しよう

GoalAreaスクリプトとGameOverAreaスクリプトではキャラクターにPlayerタグが設定されているかどうかで判定しています。

そこでEthanにPlayerタグを設定したいと思います。

ヒエラルキーでEthanを選択し、インスペクタでTagの部分を押しPlayerタグを選択します。

Playerタグを設定する

Playerタグは最初からあります。

他のタグを作りたい場合はAdd Tag…を選択し、Tagsの+を押して新しいタグを追加出来ます。

新しいタグを追加する

キャラクタ移動スクリプトに処理を追加する

ゲームクリア、ゲームオーバーになったら、GameManagerゲームオブジェクトのGameManagerスクリプトでGameOverプロパティをtrueにしました。

GameOverプロパティがtrueの場合はキャラクターの操作も出来ないようにします。

PlayerControllerスクリプトを開き、処理を追加します。

まずはフィールドにgameManagerとcanControlを用意します。

gameManagerはGameManagerスクリプトを入れるフィールドでcanControlはキャラクターが操作可能かどうかのフィールドです。

次にStartメソッドでGameManagerスクリプトの取得をします。

Rigidbodyの取得等の前にGameManagerを取得する処理を追加しています。

GameManagerスクリプトの取得方法はGoalAreaスクリプト等で行った方法と同じです。

またcanControlをtrueにし、キャラクターを操作可能であると設定します。

次にUpdateメソッドでCheckGroundメソッドを呼ぶ前に処理を追加します。

まず最初に、!canControlで操作可能でない時はreturnを使ってそれ以降の処理を実行しません。

GameManagerのGameOverプロパティがtrueの時は既にゲームクリアかゲームオーバーの状態なので、キャラクターを移動させたくありません。

そこでキャラクターの移動速度を0にし、アニメーションパラメーターのSpeedを0にしてアニメーションをIdleにし、RigidbodyのisKinematicをtrueにし、canControlをfalseにしたあとreturnでそれ以降の処理をせず終了します。

RigidbodyのisKinematicをtrueにすると、スクリプトでしかRigidbodyを操作出来なくなるので力を加える事も力を受ける事もなくなります。

今回は2段階の条件でreturnでそれ以降の処理を回避していますが、これはgameManager.GameOverだけで判断すると毎回velocityやアニメーションパラメータ―のSpeedを設定し直す必要が出てくるので、canControlフィールドを用意し、一度値をリセットしたらそれ以降は同じ処理をしないようにしています。

!canControlの条件のところをrigidBody.isKinematicに変えても出来ますが、それだと後からスクリプトを見た時になんでその条件を付けたのか忘れる可能性もあるのでcanControlを新たに作って条件に設定しました。

実行して確認する

これで機能が出来たのでキャラクターを移動させて床を外れて落下させたり、ゴールエリアに接触してキャラクターを操作出来なくなるか確認してみましょう。

上のようになりました。

終わりに

キャラクターが侵入したことをコライダで検知し、ゲームマネージャーでゲームの管理をするということをやりました。

次回はゲームのタイマーを作成し、ゴールするまでの時間を計測出来るようにしていきます。

タイトルとURLをコピーしました