この記事はロックマン風2D横スクロールアクションゲームの作り方講座の第6回です。
前回まででカメラをプレイヤーキャラに追尾して移動させる処理や背景画像の表示・スクロール処理等を実装しました。
前回の記事:
今回は1つのステージを複数のエリアに分割して大規模なステージを構築・管理できるようにしていきます。前回実装したカメラの移動範囲システムも分割エリアステージの実装に大いに役立ってきます。
Unityでゲームステージを複数のエリアに分割する
サンプルゲームの元ネタであるロックマンシリーズは1つのステージがいくつかの領域で分けられており、その領域の間に立つと一気に1画面分の画面スクロールが発生します。
エリア分けを行わなくても1つの広いステージをシームレスに探索できる形になるので良いのですが、エリア分けをすることで順路が分かりやすくなる等もメリットも存在します。今回はその方式で作成してみましょう。
ステージの枠組みを作る オブジェクト間の親子関係を設定
エリア分けの準備として最初にステージ全体を1つのオブジェクトの親子関係にまとめてみましょう。
つまり全ての親であるオブジェクト1つを用意し、今あるMain Cameraやアクターオブジェクト等は全てこのオブジェクトの子にしていきます。
空オブジェクトとしてStageManagerを作成し、Hierarchyビューの操作で他の5オブジェクトを全てStageManagerの子になるように変更します。
また、StageManagerのTransformのPositionの値が(0,0,0)になっているかチェックしておきましょう。StageManagerが最上位の親オブジェクトとなり、その他の子オブジェクトの基準位置になるため、必ず(0,0,0)にしておきましょう。
ステージマネージャクラスを仮作成
このオブジェクトはステージ全体を親としてまとめて管理できるオブジェクトでもあります。よってこのオブジェクトにはステージを管理するためのスクリプトをアタッチしておくと色々と都合が良くなります。
StageManagerクラスを作成し、このオブジェクトにアタッチしておきましょう。まだ中身は編集しなくてOKです。
Areaオブジェクトをプレハブ化してステージ分割表示の準備
ステージ内のエリアを分割していきます。
分割といっても現在あるオブジェクトに関してはほとんど手を付ける必要はありません。Main CameraやActor、BackGroundオブジェクトは全エリア共通で使いまわすのでこのままStageManagerオブジェクト直下に置かれた状態で問題ありません。
タイルマップを持つGridオブジェクトに関しても同様です。あくまでエリアごとに異なるのは「カメラの移動範囲」と「敵や各種ギミック等のオブジェクト」のみです。
一度作ったものをできるだけ再利用できるようにゲーム開発していきましょう。
まずは空のオブジェクトとしてAreaオブジェクトをStageManagerオブジェクト以下に作成し、CameraMoveAreaオブジェクトを自身の子に移動させます。
今後エリアを2つ3つと配置する時はこのAreaオブジェクトを複製していく形になります。
先を見据えるなら、このAreaオブジェクトにさらに空オブジェクトとして「Enemies」、「Gimmics」を追加しておくと良いでしょう。(任意)
- Ennemies … 敵オブジェクトを作成したらこの中に配置していきます。
- Gimmics … 動く床やトゲ等の機能を持つステージオブジェクト(ギミック)を作成したらこの中に配置していきます。
敵オブジェクトやギミックオブジェクトはのちの章で開発します。
Areaオブジェクトをプレハブ化
Areaオブジェクトを用意できたら、これを複製・管理しやすくするためにプレハブ(Prefab)化しておきます。
ProjectビューでAssets/Prefabsフォルダを開いておき、ここにHierarchyビューからAreaオブジェクトをドラッグ&ドロップすればプレハブ化完了です。
プレハブ化が成功していれば該当のオブジェクトがHierarchyビュー上で青色に変化しているはずです。
プレハブ化したので、今後この(Prefabフォルダに生成されている)Area.prefabファイルはProjectビューからHierarchyビュー上にドラッグ&ドロップする事で簡単に複製できるようになりました。
さらにArea.prefabファイル選択し、Inspectorビュー上端付近にある[Open]ボタンを押下する事でPrefabの編集モードに移る事で出来ます。ここで編集したデータは、シーン内に既に配置されているPrefab由来のオブジェクト(インスタンスと言います)に同じ変化が発生します。
つまり、複数オブジェクトに対して共通の処理を行えるのでこの操作はぜひ覚えておきましょう(逆に言うと、シーン上のインスタンスに行った操作は他インスタンスに影響を与えません)。
エリアマネージャクラスを仮作成
先ほどのステージマネージャ同様、このエリアを管理するクラスであるAreaManagerクラスをC#スクリプトで作成し、Prefab編集モードでアタッチを行ってみましょう。
プレハブ編集モード中はHierarchyビューやSceneビュー上にプレハブ名が表示されており、Sceneビューでの背景も青になっています。モードの切り替え忘れに気を付けつつ作業しましょう。
Unityでエリア間移動(マップの端まできたら画面スクロール)を実装
現在は複数のエリアが独立して存在しているのみです。
ここからは「指定の場所に触れたら次のエリアに切り替わる」というシステムを作っていきましょう。
スクロール開始地点プレハブ
まずはエリアの端に設置する、次エリアに切り替えるトリガーとなるSpriteオブジェクトを作成します。
名前はScrollEnterとします。エリア内オブジェクトの1つですので、ひとまず最初のAreaオブジェクト以下に作成しましょう。
表示する画像はTextures/MapAreas/ScrollEnterArea.pngを指定します。
このオブジェクトにアクターが触れたらエリア切り替えを開始する、という流れですので接触を検知する為にBox Collider 2Dをアタッチし、Is Triggerをオンにします。
さらに接触検知時の処理を行うためにScrollEnterクラスを新規作成し、ここにアタッチしておきます。
ここまでの準備が完了したらScrollEnterオブジェクトをプレハブ化しておきます。
シーン内に1つ存在しているScrollEnterインスタンスについては、この後画面スクロール実装の確認に使用するため適当な距離だけ右に離して置いておきます。
判定漏れを防ぐためにある程度縦長に拡大しておきましょう。スプライトオブジェクトの位置・拡大率はSceneビュー上でも直接編集できます。
ステージ・エリア管理と画面スクロールの処理を実装
ここまで形だけ作成しておいたStageManager・AreaManager・ScrollEnterの3クラスを編集し、ステージの管理やエリア間の画面スクロール等の機能を実装していきましょう。
さらにスクロール処理を完成させるためにCameraControllerクラスにも編集を加えます。
一度に4クラス変更していくので、1クラスずつ保存してUnityに戻ってもエラーが出ることになります。全部の編集を完了してエラーがなくなっていればOKです。
StageManager.cs
子オブジェクトに複数存在しているAreaManagerオブジェクト(・クラス)を取得・管理し、常に1つのエリアのみがアクティブになるようにします。
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 41 42 43 |
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// ステージマネージャクラス /// </summary> public class StageManager : MonoBehaviour { [HideInInspector] public ActorController actorController; // アクター制御クラス [HideInInspector] public CameraController cameraController; // カメラ制御クラス [Header ("初期エリアのAreaManager")] public AreaManager initArea; // ステージ内の最初のエリア(初期エリア) // ステージ内の全エリアの配列(Startで取得) private AreaManager[] inStageAreas; // Start void Start() { // 参照取得 actorController = GetComponentInChildren<ActorController> (); cameraController = GetComponentInChildren<CameraController> (); // ステージ内の全エリアを取得・初期化 inStageAreas = GetComponentsInChildren<AreaManager> (); foreach (var targetAreaManager in inStageAreas) targetAreaManager.Init (this); // 初期エリアをアクティブ化(その他のエリアは全て無効化) initArea.ActiveArea (); } /// <summary> /// ステージ内の全エリアを無効化する /// </summary> public void DeactivateAllAreas () { foreach (var targetAreaManager in inStageAreas) targetAreaManager.gameObject.SetActive (false); } } |
- GetComponentsInChildrenメソッドによって、子オブジェクト以下にある指定のコンポーネントを配列でまとめて取得できます。
- foreach文で配列の全要素に対して同じ処理(今回はInit呼び出し)を実行しています。
まとめ
これでオリジナルステージを奥まで進んでいくことが可能になりました。
次回からはいよいよ攻撃システムとザコ敵キャラクターの実装を行い、アクションゲームらしく戦闘を楽しめるようにしていきます。
次の記事:
コメント