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

- ステージのシーン:夜の芝生に、スライムちゃんと扉
- 矢印キー(WASD)やゲームパッドで、スライムちゃんを上下左右に動かす
- 扉に入ると、画面がキラッと白く光ってから暗くなり、エンディングへ
作るスクリプトは3つです。
| スクリプト | 役割 | 付ける場所 |
|---|---|---|
| PlayerMove | 上下左右に動かす | スライムちゃん |
| Door | 入ってきたら、次のシーンへ | 扉 |
| ScreenFlash | 画面を白く光らせてから暗くし、シーンを切り替える | 画面いっぱいの板 |
前回作ったタイトルとエンディングは、そのまま使います。間に1つはさむだけなので、どこかを作り直すことはありません。
ステージのシーンを作ろう

ステージも、タイトルのシーンを複製して作ります。カメラや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番)に入れる

前回作ったSceneButtonは、行き先をInspectorで決めるようにしてありました。だから、行き先を変えるのはScene Nameを書きかえるだけです。スクリプトは1行も変えていません。
この時点で再生すると、「はじめる」で芝生のステージに切りかわります。ただ、ステージには出口がないので、ここで止まってしまいます。次は、スライムちゃんを置いて動かしましょう。
スライムちゃんを動かそう

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(扉や、あとで置く星・おばけより手前に描く)

Order in Layerは、絵を重ねる順番です。数字が大きいほど手前に描かれます。同じ数字どうしだと、どちらが手前になるか決まらないので、扉に入ったときにスライムちゃんが扉の後ろに隠れてしまうことがあります。主役のスライムちゃんは、先に大きめの数字にしておきましょう。
Frame Animation(ぷるぷる弾む動き)は、タイトルから持ってきたものがそのまま付いています。
入力をスクリプトで使えるようにしよう
キーボードとゲームパッドの入力は、Input Systemで受け取ります。
- Projectウインドで
Assets/SettingsのInputSystem_Actionsを選ぶ - InspectorのGenerate C# Classにチェックを入れて、Apply
- 同じフォルダに
InputSystem_Actions.csが出来る
- 同じフォルダに

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キャラクターを動かそう:移動とジャンプの後半でも紹介しています。
扉に入ったらエンディングへ

次は、ゴールの扉です。
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を作ってから、扉に付けましょう。
入ったらキラッと光らせよう

扉に入った瞬間に、いきなりエンディングに切りかわると、なんだか味気ないですよね。そこで、画面をキラッと白く光らせてから、暗くして切り替えます。たったこれだけで、「ゴールした!」という手応えがぐっと出ます。
まずは、画面いっぱいの板を作ります。
- Canvasを右クリック>UI (Canvas)>Image、名前をFlashにする
- アンカーをstretch-stretch(右下の四角)にして、Left・Top・Right・Bottomを0にする
- Colorを白(255, 255, 255)にして、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ならちょうど半分の色
- 2つの色の間の色を作る。0なら
- 透明な白 → 白 → 黒
- 0.15秒で一気に白く光り、0.6秒かけて暗くなる。光るのは速く、暗くなるのはゆっくりにすると、「キラッ」と感じます
付けていきます。
- FlashにScreenFlashを付ける
- 扉のゲームオブジェクト(HierarchyのDoor)に、スクリプトのDoorを付ける
- Screen Flashの欄にFlashをドラッグ(Next Scene NameはEndingのまま)
スライム光るのは一瞬なのに、「ゴールした!」って感じが全然ちがいますね・・・!
完成チェック


Titleシーンを開いて再生し、最初から最後まで通して遊びます。
- 「はじめる」を押すと、芝生のステージに切りかわる
- 矢印キー(WASD)やゲームパッドで、スライムちゃんが上下左右に動く
- 扉に入ると、白く光ってから暗くなり、エンディングに切りかわる
- 「タイトルへ」を押すと、タイトルに戻る
これで、「動かして、ゴールして、クリア」できるゲームになりました!前回と同じく、どこで止めても遊べる形のままです。
ビルドして遊ぼう


前回と同じように、ビルドして.exeで遊びます。
- File>Build Profilesを開いて、Scene ListにTitle・Stage1・Endingの3つが入っているのを確かめる
- Buildを押して、前回と同じ
Build/StarGardenのフォルダを選ぶ(上書きしてOK) - 出来たStarGarden.exeを起動して、扉までたどり着けるか遊んでみる
Scene Listに入っていないシーンは、ビルドしたゲームには入りません。Stage1を入れ忘れると、「はじめる」を押しても何も起きません(エディタでは動くので気づきにくいです)。
あとがき
今回は、タイトルとエンディングの間にステージを1つはさみました。作ったのはスクリプト3つと、シーン1つだけ。それでも、自分で動かしてゴールできる、ちゃんとした「ゲーム」になりました。
ただ、今のステージは、まっすぐ扉に向かえば終わってしまいます。次回は、生け垣の壁で迷路を作って、スライムちゃんが歩く向きに合わせて絵を切り替えます。壁にぶつかったときの「ぽよん」も付けますよ!



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



次の回で、ちゃんと壁を作るからね!迷子にならないうちに、扉に帰ってきて!
コメント
コメント一覧 (1件)
[…] 前回:#2 ステージをはさもう:扉に入ったらエンディング […]