シンプルなアクションゲームを作ってみようの第16回です。
今回はプレイヤーキャラクターを邪魔する障害物を作成していきます。
前回はゲームにBGMを付けました。
シンプルなアクションゲームを作ってみようの他の記事は
シンプルなアクションゲームを作るのを通してUnityの使い方を学ぶカテゴリです。
から参照出来ます。
障害物を作成する
今回はプレイヤーキャラクターがゴールエリアに到達するまでの間に障害物を置き、それを解除する解除エリアに到達するとその障害物を消して通れるようにしていきます。
また障害物を消す時にエフェクトの表示と効果音を鳴らしたいと思います。
障害物ゲームオブジェクトの作成
障害物用のゲームオブジェクトを作成します。
Stage1シーンのEnvironmentゲームオブジェクトを選択した状態で右クリックから3D Object→Cubeを選択し、名前をObstacleとします。
Transformの値を以下のように設定します。
シーンビューで見ると以下のような位置と大きさで設定されます。
障害物用のマテリアルの作成と取り付け
障害物には障害物用のマテリアルを作成し取り付けます。
Assets/Materialsフォルダで右クリックからCreate→Materialを選択し、名前をObstacleとします。
Obstacleマテリアルを選択し、インスペクタでAlbedoの横の白色の部分を押し、青色に変更します。
ObstacleマテリアルをObstacleゲームオブジェクトにドラッグ&ドロップして設定します。
パーティクルアセットと効果音のダウンロード
障害物を消す時にエフェクトを表示し、効果音を鳴らしますが、そのエフェクトと効果音には無料のアセットをダウンロードして使用させて頂きます。
エフェクトはUnityのパーティクルシステムで作られたもので、自分でも色々な効果のパーティクルを作成出来ますが、今回は出来上がたったものを利用するだけです。
アセットストアで「cartoon fx free」で検索して出てくる無料のアセットをインポート&ダウンロードします(有料のもあるので間違えないようにしてください)。
効果音は「soundbits free sfx」で検索して出てくる無料のサウンドを利用させて頂きます。
Audio Sourceコンポーネントの取り付け
ヒエラルキーのObstacleゲームオブジェクトを選択し、Add ComponentからAudio→Audio Sourceを選択し取り付けます。
AudioClipにはAssets/SoundBits_FreeSFX/Samples/Just_Whoosh_004.wavを設定します。
この効果音はスクリプトから再生をさせるので、このゲームオブジェクトが登場時には音声を鳴らしたくありません。
そこでPlay On Awakeのチェックを外します。
また効果音なので繰り返し音声を再生させないのでLoopのチェックを外します。
3D上のゲームオブジェクトが消える時にこの効果音を鳴らすので、3D音声でもいいんですが、必ず聴こえるように今回はSpatial Blendを2Dの方にドラッグします。
パーティクルの表示と音声再生スクリプトの作成
効果音を設定したAudio Sourceの設定が出来ましたので、次はスクリプトからパーティクルの表示と効果音を再生できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class EffectScript : MonoBehaviour { // 表示するパーティクル [SerializeField] private GameObject particle; private AudioSource audioSource; // 消去中かどうか private bool erasing; // Start is called before the first frame update void Start() { audioSource = GetComponent<AudioSource>(); } // Update is called once per frame void Update() { // 消去中でなければ何もしない if(!erasing) { return; } // 音声が再生されていなければパーティクルを表示してゲームオブジェクトを非表示にする if (!audioSource.isPlaying) { Instantiate(particle, transform.position, Quaternion.identity); gameObject.SetActive(false); } } // 消失効果処理 public void AddEffect() { audioSource.Play(); erasing = true; } } |
particleはパーティクル機能を持ったゲームオブジェクトをインスペクタで設定します。
audioSourceはAudioSourceコンポーネントを設定します。
erasingはゲームオブジェクトを消去中かどうかのフラグです。
Startメソッドで自身に設定しているAudioSourceコンポーネントを取得しています。
Updateメソッドでは少しややこしい処理をしていますが、効果音が鳴って完全に再生が止まってから障害物を消す処理をしています。
!erasingの状態、つまりゲームオブジェクトを消している時でなければreturnでそれ以降の処理をしません。
その後!audioSource.isPlayingプロパティで音声が再生されていないか確認し、効果音が止まっていればInstantiateメソッドを使ってparticleゲームオブジェクトをインスタンス化しています。
Instantiateメソッドを使うと第1引数で指定したプレハブを第2引数の位置、第3引数の回転でインスタンス化しゲーム内に登場させることが出来ます。
1 2 3 | Instantiate(インスタンス化するプレハブ, 登場させる時の位置, 登場させる時の回転); |
パーティクルをインスタンス化した後にgameObject.SetActive(false)を使ってゲームオブジェクトを非アクティブにしています。
1 2 3 | Destroy(gameObject) |
で消してもいいかもしれません。
AddEffectメソッドは障害物を消す前に効果音をaudioSource.Playメソッドで再生し、erasingをtrueにしています。
このメソッドは障害物消去エリアにプレイヤーキャラクターが侵入した時に呼び出すようにします。
EffectScriptの取り付けと設定
EffectScriptが出来たのでObstacleゲームオブジェクトに取り付け、設定をします。
EffectScriptのparticleにはAssets/JMO Assets/Cartoon FX/CFX Prefabs/Misc/CFX_MagicPoof.prefabを設定します。
障害物の上に乗った場合も接地出来るようにしておく
プレイヤーキャラクターは今のところジャンプが出来ません。
しかし、障害物の上にジャンプして乗れるようになった場合に接地と判断しなければなりません。
そこでObstacleゲームオブジェクトのLayerはGroundに設定しておきます。
障害物消去エリアの作成
障害物が出来たので次は障害物を消去するエリアを作成します。
Environmentゲームオブジェクトを選択した状態で右クリックから3D Object→Sphereを選択し、名前をEraseBlueObstacleとします。
EraseBlueObstackleのTransformの値を設定し、Sphere ColliderのIs Triggerにチェックを入れて範囲として使用します。
障害物消去エリアのマテリアルを作成し設定する
Assets/MaterialsフォルダにEraseBlueObstacleマテリアルを作成し、インスペクタでRendering ModeをTransparentにし、色を青色の半透明にします。
EraseBlueObstacleゲームオブジェクトに取り付けます。
プレイヤーキャラクター検知スクリプトの作成
EraseBlueObstacleゲームオブジェクトの範囲にプレイヤーキャラクターが侵入したら障害物であるObstacleを消去する必要があります。
Assets/Scriptsフォルダに新しくEraseObstacleスクリプトを作成し、EraseBlueObstacleゲームオブジェクトにドラッグ&ドロップして取り付けます。
スクリプトに記述していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class EraseObstacle : MonoBehaviour { // 無効化するゲームオブジェクト [SerializeField] private GameObject objectOfErase; private void OnTriggerEnter(Collider other) { // プレイヤーが侵入したら設定したゲームオブジェクトを無効化 if (other.CompareTag("Player")) { // 指定したゲームオブジェクトの効果処理を実行する objectOfErase.GetComponent<EffectScript>().AddEffect(); Destroy(gameObject); } } } |
objectOfEraseは範囲内にプレイヤーキャラクターが侵入したら消すゲームオブジェクトをインスペクタで設定します。
今回の場合はインスペクタにヒエラルキーのObstacleゲームオブジェクトをドラッグ&ドロップします。
OnTriggerEnterメソッドで、侵入したコライダのゲームオブジェクトに設定しているタグがPlayerだった時にobjectOfEraseゲームオブジェクトに取り付けられているEffectScriptスクリプトを取得し、AddEffectメソッドを実行しています。
これでインスペクタで設定したゲームオブジェクトのObstacleのエフェクトを発動します。
Destoryメソッドで障害物消去エリアであるEraseBlueObstacleゲームオブジェクト自体を削除します。
Erase Obstacleスクリプトの設定
スクリプトが出来たのでEraseBlueObstacleゲームオブジェクトのインスペクタのEraseObstacleのObject Of EraseにヒエラルキーのObstacleをドラッグ&ドロップします。
ナビゲーションシステムと障害物
これで機能が出来た感じがしますが、少し問題が残ります。
ObstacleゲームオブジェクトはStaticにチェックを入れていないので、NavigationウインドウのBakeボタンを押して再度ベイクをしてもナビメッシュエージェントは障害物をすり抜け移動してしまいます。
ナビメッシュはNavigation Staticにチェックが入ったゲームオブジェクトを元に移動ルートを作成するからで、Obstacleゲームオブジェクトはチェックを入れていないので障害物の所にも移動ルートが出来ます。
そこで例えばObstacleゲームオブジェクトをStaticにしてBakeボタンを押せば、そのルートが遮断されます。
ただし実行してみるとわかりますが、障害物消去エリアに入って障害物を消しても元々のルートが遮断されたものなので敵キャラクターはそこを通れません。
これでは問題があります。
ナビメッシュエージェントの障害物として認識させる
この問題を解消する為に、ObstacleゲームオブジェクトにNavMeshObstacleコンポーネントを追加します。
NavMeshObstacleを取り付けるとナビメッシュエージェントが障害物として認識するようになります。
例えば開閉を繰り返すドア等は動くものなのでStaticにすると動かなくなってしまうのでNavMeshObstacleコンポーネントを取り付けてナビメッシュエージェントに障害物と認識させます。
ヒエラルキーでObstacleゲームオブジェクトを選択し、インスペクタのAdd ComponentからNavigation→Nav Mesh Obstacleを選択し取り付けます。
ObstacleのStaticにはチェックを入れません。
NavMeshObstacleコンポーネントのShapeは障害物の範囲の形状を設定します。
デフォルトでObstacleのコライダと同じになっているので特に変更はしません。
Carveにチェックを入れると障害物をナビメッシュエージェントが回避する時に滑らかに回避出来るようになります。
今回の場合はチェックを入れないとナビメッシュのルートが遮断されないのでチェックを入れます。
これで設定が出来たのでNavigationウインドウのBakeタブのBakeボタンを押してナビメッシュをベイクします。
ナビメッシュのベイクは新しくナビメッシュエージェントの移動出来る場所が出来たら再度する必要があるので気を付けてください。
ベイクするとObstacleゲームオブジェクトの所のナビメッシュが遮断されます。
つまりObstacleゲームオブジェクトがある場合はそのルートを敵キャラクターは通れません。
ただし、障害物消去エリアにプレイヤーキャラクターが侵入して障害物を削除するとNavMeshObstacleコンポーネントを持つObstacleゲームオブジェクトを非アクティブにしますので、このルートを邪魔するゲームオブジェクトがなくなるので、ルートが繋がり敵キャラクターが通れるようになります。
実行して確認してみる
機能が出来たので実行して確認してみましょう。
上のようになりました。
終わりに
今回は障害物の作成とそれを消す消去エリアの作成、パーティクルの表示と効果音の再生を行いました。
次回はプレイヤーキャラクターのHPをUIで表示したり、敵キャラクターに近づかれた場合にHPを減らす機能を作成していきます。