絶対に完成させるゲーム制作#2|ステージをはさもう:扉に入ったらエンディング

夜の芝生のステージで、スライムちゃんが右へ、上へと動いて扉に入ると、画面がキラッと白く光ってから暗くなり、エンディングに切りかわる

前回は、タイトルとエンディングだけで「星ふる夜の庭」を完成させました。でも、「はじめる」を押すとすぐにエンディングなので、まだ遊ぶところがありません・・・。今回は、タイトルとエンディングの間にステージをはさみます。スライムちゃんを上下左右に動かして、扉に入ったらエンディング。いよいよ、自分で動かして「クリア」できるゲームになりますよ!

目次

今回作るもの

今回のゲームの流れ。「タイトル」から「はじめる」で「ステージ」へ、「扉に入る」で「エンディング」へ、「タイトルへ」でタイトルに戻る。「ステージ」が今回つくるもの
  • ステージのシーン:夜の芝生に、スライムちゃんと扉
  • 矢印キー(WASD)やゲームパッドで、スライムちゃんを上下左右に動かす
  • 扉に入ると、画面がキラッと白く光ってから暗くなり、エンディングへ

作るスクリプトは3つです。

スクリプト役割付ける場所
PlayerMove上下左右に動かすスライムちゃん
Door入ってきたら、次のシーンへ扉
ScreenFlash画面を白く光らせてから暗くし、シーンを切り替える画面いっぱいの板

前回作ったタイトルとエンディングは、そのまま使います。間に1つはさむだけなので、どこかを作り直すことはありません。

ステージのシーンを作ろう

Stage1シーンを開いたエディタ。HierarchyにMain Camera・Global Light 2D・Background・Player・Canvas(Flash)・EventSystem・Door。Gameビューに夜の芝生、左下にスライムちゃん、右上に明かりのついた扉

ステージも、タイトルのシーンを複製して作ります。カメラやCanvasの設定が、そのまま使えるからです。

  • ProjectウインドでTitleシーンを選んでCtrl+D、出来た「Title 1」の名前をStage1にして開く
  • いらないものを消す
    • Canvasの子のTitleTextとStartButtonを消す(Canvasは残す)
  • Backgroundを選んで、Sprite RendererのSpriteをbg_lawn(上から見た芝生)にする

これで、何もない芝生のステージが出来ました。

タイトルの行き先を変えよう

今は「はじめる」の行き先がエンディングなので、ステージに変えます。

  • Titleシーンを開いて、StartButtonのScene ButtonのScene NameをStage1にする
  • File>Build ProfilesのScene ListにStage1をドラッグして、TitleとEndingの間(1番)に入れる
Build ProfilesのScene Listに、0がCompleteGame/Scenes/Title、1がCompleteGame/Scenes/Stage1、2がCompleteGame/Scenes/Ending

前回作ったSceneButtonは、行き先をInspectorで決めるようにしてありました。だから、行き先を変えるのはScene Nameを書きかえるだけです。スクリプトは1行も変えていません。

この時点で再生すると、「はじめる」で芝生のステージに切りかわります。ただ、ステージには出口がないので、ここで止まってしまいます。次は、スライムちゃんを置いて動かしましょう。

スライムちゃんを動かそう

PlayerのInspector。TransformのPositionが-7, -3, 0、Scaleが0.8, 0.8, 1。Rigidbody 2DのGravity Scaleが0、Freeze RotationのZにチェック。Circle Collider 2DのOffsetが0, -0.2、Radiusが0.5

Stage1シーンにもSlimeが残っているので、それをプレイヤーにします。

  • Slimeの名前をPlayerにする
  • Transformを Position(-7, -3, 0)、Scale(0.8, 0.8, 1)にする(画面の左下に、タイトルより小さめに置く)
  • Add ComponentでRigidbody 2Dを付ける
    • Gravity Scale:0(上から見たゲームなので、下に落ちないように)
    • Constraints>Freeze Rotation:Zにチェック(ぶつかったときに回らないように)
  • Add ComponentでCircle Collider 2Dを付ける
    • Offset:(0, -0.2)、Radius:0.5(体の丸いところに合わせる)
  • Sprite RendererのOrder in Layer:3(扉や、あとで置く星・おばけより手前に描く)
PlayerのInspectorで、Sprite Rendererを開いたところ。Spriteがslime_walk_21、Additional SettingsのOrder in Layerが3

Order in Layerは、絵を重ねる順番です。数字が大きいほど手前に描かれます。同じ数字どうしだと、どちらが手前になるか決まらないので、扉に入ったときにスライムちゃんが扉の後ろに隠れてしまうことがあります。主役のスライムちゃんは、先に大きめの数字にしておきましょう。

Frame Animation(ぷるぷる弾む動き)は、タイトルから持ってきたものがそのまま付いています。

入力をスクリプトで使えるようにしよう

キーボードとゲームパッドの入力は、Input Systemで受け取ります。

  • ProjectウインドでAssets/SettingsのInputSystem_Actionsを選ぶ
  • InspectorのGenerate C# Classにチェックを入れて、Apply
    • 同じフォルダにInputSystem_Actions.csが出来る
InputSystem_ActionsのInspector。Generate C# Classにチェックが入っている

Input Systemのくわしい使い方は、6-7 Input Systemで入力を受け取ろうで紹介しています。

PlayerMoveを作ろう

ScriptsフォルダにPlayerMoveを作ります。

using UnityEngine;

// 上下左右に動かす(上から見たゲーム)
public class PlayerMove : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f; // 1秒に進むマスの数

    private InputSystem_Actions inputActions;
    private Rigidbody2D rb;
    private Vector2 moveInput;

    private void Awake()
    {
        inputActions = new InputSystem_Actions();
        rb = GetComponent<Rigidbody2D>();
    }

    private void OnEnable()
    {
        inputActions.Enable();
    }

    private void OnDisable()
    {
        inputActions.Disable();
    }

    private void Update()
    {
        // 斜めが速くならないように、長さを1以下にする
        moveInput = Vector2.ClampMagnitude(inputActions.Player.Move.ReadValue<Vector2>(), 1f);
    }

    private void FixedUpdate()
    {
        rb.linearVelocity = moveInput * moveSpeed;
    }

    // 動けなくする(扉に入ったあとなど)
    public void Stop()
    {
        enabled = false;
        rb.linearVelocity = Vector2.zero;
    }
}
  • ReadValue<Vector2>()
    • 矢印キー・WASD・ゲームパッドのスティックの向きを、x(左右)とy(上下)の数で受け取る
    • 上から見たゲームなので、受け取った向きを、そのまま動く向きに使える
  • rb.linearVelocity
    • Rigidbody 2Dの速さ。向き × 速さを入れると、その方向に動く
    • 物理の動きなので、FixedUpdateで入れる
  • Stop()
    • 扉に入ったあとに動けないようにするためのメソッド。enabled = falseでUpdateとFixedUpdateが止まり、速さも0にする

PlayerにPlayerMoveを付けたら、再生して矢印キーで動かしてみましょう。スライムちゃんが、ぷるぷる弾みながら上下左右に動けばOKです。

この回では、まだ壁がないので、画面の外にも出ていけてしまいます。壁は次の回で置くので、今は画面の外に行かないように気をつけて遊んでください。

上から見たゲームの動かし方は、12-3 2Dキャラクターを動かそう:移動とジャンプの後半でも紹介しています。

扉に入ったらエンディングへ

扉のゲームオブジェクト(Door)のInspector。TransformのPositionが7, 2.5, 0、Sprite RendererのSpriteがdoor_open、Box Collider 2DのIs Triggerにチェック、Sizeが0.8, 1.2。スクリプトのDoorのNext Scene NameがEnding、Screen FlashにFlash

次は、ゴールの扉です。

  • Sprites/Itemsのdoor_open(明かりのついた扉)を、Hierarchyにドラッグ&ドロップ
    • 名前をDoorにして、Positionを(7, 2.5, 0)にする
  • Add ComponentでBox Collider 2Dを付ける
    • Is Triggerにチェック
    • Size:(0.8, 1.2)(扉の内側だけにする)

Is Triggerにチェックを入れると、ぶつかって止まるのではなく、「重なった」ことだけを知らせる当たり判定になります。くわしくは6-10 衝突を検知しよう:当たり判定のイベントとタグで紹介しています。

Doorスクリプトを作ろう

Scriptsフォルダに、扉のスクリプトDoorを作ります。さっき置いた扉のゲームオブジェクトと同じ名前ですが、こちらはスクリプトの名前です。

using UnityEngine;

// 扉:スライムちゃんが入ったら、次のシーンへ
public class Door : MonoBehaviour
{
    [SerializeField] private string nextSceneName = "Ending"; // 入ったら行くシーンの名前
    [SerializeField] private ScreenFlash screenFlash;          // 画面を光らせて、シーンを切り替える

    private bool isEntered; // もう入ったか(2回入らないように)

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (isEntered)
        {
            return;
        }
        PlayerMove player = other.GetComponent<PlayerMove>();
        if (player == null)
        {
            return;
        }
        isEntered = true;
        player.Stop();
        screenFlash.FlashAndLoad(nextSceneName);
    }
}
  • OnTriggerEnter2D
    • Is Triggerの当たり判定に、ほかのColliderが重なった瞬間に呼ばれる
  • GetComponent<PlayerMove>()
    • 重なったのがスライムちゃん(PlayerMoveが付いているもの)かを確かめる。ほかのものなら何もしない
  • isEntered
    • 入った直後に何度も呼ばれて、シーンの切り替えが2回始まらないようにする

Doorスクリプトの中でScreenFlashを使っているので、今はまだエラーになります。次のScreenFlashを作ってから、扉に付けましょう。

入ったらキラッと光らせよう

扉に入る瞬間を3コマ並べたもの。スライムちゃんが扉に重なる → 画面が白く光る → 暗くなる

扉に入った瞬間に、いきなりエンディングに切りかわると、なんだか味気ないですよね。そこで、画面をキラッと白く光らせてから、暗くして切り替えます。たったこれだけで、「ゴールした!」という手応えがぐっと出ます。

まずは、画面いっぱいの板を作ります。

  • Canvasを右クリック>UI (Canvas)>Image、名前をFlashにする
  • アンカーをstretch-stretch(右下の四角)にして、Left・Top・Right・Bottomを0にする
  • Colorを白(255, 255, 255)にして、A(透明度)を0にする
  • Raycast Targetのチェックを外す(マウスのクリックをじゃましないように)
FlashのInspector。Rect Transformがstretch-stretchでLeft・Top・Right・Bottomが0、ImageのColorが白(Aは0)、Raycast Targetのチェックが外れている

ScreenFlashを作ろう

ScriptsフォルダにScreenFlashを作ります。

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

// 画面いっぱいの板で、白く光らせてから暗くして、シーンを切り替える
public class ScreenFlash : MonoBehaviour
{
    [SerializeField] private float flashSeconds = 0.15f; // 白く光るまでの時間
    [SerializeField] private float fadeSeconds = 0.6f;   // 白から暗くなるまでの時間

    private Image screenImage;

    private void Start()
    {
        screenImage = GetComponent<Image>();
        screenImage.color = Color.clear; // 最初は見えないようにしておく
    }

    // 光らせてから、sceneName のシーンに切り替える
    public void FlashAndLoad(string sceneName)
    {
        StartCoroutine(FlashAndLoadRoutine(sceneName));
    }

    private IEnumerator FlashAndLoadRoutine(string sceneName)
    {
        yield return ChangeColor(new Color(1f, 1f, 1f, 0f), Color.white, flashSeconds);
        yield return ChangeColor(Color.white, Color.black, fadeSeconds);
        SceneManager.LoadScene(sceneName);
    }

    // from の色から to の色へ、seconds 秒かけて変える
    private IEnumerator ChangeColor(Color from, Color to, float seconds)
    {
        float time = 0f;
        while (time < seconds)
        {
            time += Time.deltaTime;
            screenImage.color = Color.Lerp(from, to, time / seconds);
            yield return null;
        }
        screenImage.color = to;
    }
}
  • コルーチン(IEnumeratorとyield return)
    • 「少しずつ色を変えて、終わったら次へ」のように、何フレームもかけて進む処理を書ける
    • yield return nullで1フレーム待ち、yield return ChangeColor(…)で色の変化が終わるまで待つ。コルーチンは6-11 時間を扱う処理:コルーチン・Invoke・一時停止で紹介しています
  • Color.Lerp
    • 2つの色の間の色を作る。0ならfrom、1ならto、0.5ならちょうど半分の色
  • 透明な白 → 白 → 黒
    • 0.15秒で一気に白く光り、0.6秒かけて暗くなる。光るのは速く、暗くなるのはゆっくりにすると、「キラッ」と感じます

付けていきます。

  • FlashにScreenFlashを付ける
  • 扉のゲームオブジェクト(HierarchyのDoor)に、スクリプトのDoorを付ける
    • Screen Flashの欄にFlashをドラッグ(Next Scene NameはEndingのまま)
スライム

光るのは一瞬なのに、「ゴールした!」って感じが全然ちがいますね・・・!

Flashは、Canvasの子の一番下(Hierarchyで一番下)に置いておきます。UIは下にあるものほど手前に描かれるので、あとでライフや星の数を表示しても、その上から光らせられます。

完成チェック

タイトルでEnterを押すとステージへ。矢印キーで右・上と動いて扉に入ると、白く光って暗くなり、エンディングへ。Enterで「タイトルへ」を押すとタイトルに戻る。右下に押したキーが出る

Titleシーンを開いて再生し、最初から最後まで通して遊びます。

  • 「はじめる」を押すと、芝生のステージに切りかわる
  • 矢印キー(WASD)やゲームパッドで、スライムちゃんが上下左右に動く
  • 扉に入ると、白く光ってから暗くなり、エンディングに切りかわる
  • 「タイトルへ」を押すと、タイトルに戻る

これで、「動かして、ゴールして、クリア」できるゲームになりました!前回と同じく、どこで止めても遊べる形のままです。

ビルドして遊ぼう

Build ProfilesでWindowsがActive。Scene ListにTitle・Stage1・Endingの3つが入っていて、右下にBuildのボタン

前回と同じように、ビルドして.exeで遊びます。

  • File>Build Profilesを開いて、Scene ListにTitle・Stage1・Endingの3つが入っているのを確かめる
  • Buildを押して、前回と同じBuild/StarGardenのフォルダを選ぶ(上書きしてOK)
  • 出来たStarGarden.exeを起動して、扉までたどり着けるか遊んでみる

Scene Listに入っていないシーンは、ビルドしたゲームには入りません。Stage1を入れ忘れると、「はじめる」を押しても何も起きません(エディタでは動くので気づきにくいです)。

あとがき

今回は、タイトルとエンディングの間にステージを1つはさみました。作ったのはスクリプト3つと、シーン1つだけ。それでも、自分で動かしてゴールできる、ちゃんとした「ゲーム」になりました。

ただ、今のステージは、まっすぐ扉に向かえば終わってしまいます。次回は、生け垣の壁で迷路を作って、スライムちゃんが歩く向きに合わせて絵を切り替えます。壁にぶつかったときの「ぽよん」も付けますよ!

スライム

画面の外まで歩いていけるの、ちょっと楽しいんですけど・・・

フェアリー

次の回で、ちゃんと壁を作るからね!迷子にならないうちに、扉に帰ってきて!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (1件)

コメントする

目次