
前回は、タイトルとエンディングの間にステージをはさんで、扉に入ったらクリアできるようにしました。でも、まっすぐ扉に向かえば終わってしまうし、スライムちゃんはずっと正面を向いたまま・・・。今回は、生け垣の壁で迷路を作り、歩く向きに合わせてスライムちゃんの絵を切り替えます。さらに、壁にぶつかったら「ぽよん」とつぶれる演出も付けますよ!
- シリーズの目次:絶対に完成させるゲーム制作
- 前回:#2 ステージをはさもう:扉に入ったらエンディング
今回作るもの

ゲームの流れは前回と同じです。今回は、ステージの中身だけを足していきます。
- 生け垣の壁をプレハブにして、迷路を作る
- 歩く向き(上下左右)に合わせて、スライムちゃんの絵を切り替える
- 壁にぶつかると、ぽよんとつぶれてから元に戻る
作るスクリプトは2つ、前回までのスクリプトに1つメソッドを足します。
| スクリプト | 役割 | 付ける場所 |
|---|---|---|
| PlayerFacing | 動いている向きで、歩くコマを切り替える | スライムちゃん |
| SquashOnBump | 壁にぶつかったら、ぽよんとつぶれる | スライムちゃん |
| FrameAnimation(#1で作ったもの) | コマを入れかえるメソッドを足す | - |
生け垣の壁を作ろう

迷路の壁には、Sprites/Itemsのhedge(生け垣)を使います。1マス(100×100ピクセル)の絵なので、そのままだと小さな四角が1つだけです。
長い壁にしたいとき、Scaleで伸ばすと、上の図の真ん中のように絵まで引き伸ばされてしまいます。そこで、Sprite RendererのDraw ModeをTiledにします。Tiledにすると、Sizeを大きくしたぶんだけ、同じ絵がタイルのように並びます。
生け垣の絵を、並べられるようにしよう

Tiledで並べる絵は、取り込みの設定を1つ変えておきます。
- Projectウインドで
Sprites/Itemsのhedgeを選ぶ - InspectorのMesh TypeをFull Rectにして、Apply
Mesh TypeがTightのままだと、Tiledにしたときに絵の並び方がくずれます(Inspectorに注意のメッセージも出ます)。Tightは、絵の透明なところを切り落として形を作る設定なので、四角いタイルとして並べられないためです。
壁の形を作ろう

Stage1シーンを開いて、壁を1つ作ります。
- hedgeをHierarchyにドラッグ&ドロップして、名前をWallにする
- Sprite Renderer
- Draw Mode:Tiled
- Size:(1, 1)のまま
- Order in Layer:-1
- Add ComponentでBox Collider 2Dを付けて、Auto Tilingにチェック
Auto Tilingにチェックを入れると、当たり判定の大きさがSprite RendererのSizeに合わせて、自動で変わります。壁を長くするたびに、当たり判定を直さなくてよくなります。
プレハブにしよう

この壁を、何個でも置けるようにプレハブにします。
CompleteGameフォルダの中にPrefabsフォルダを作る- HierarchyのWallを、Prefabsフォルダにドラッグ&ドロップ
- Hierarchyに残ったWallは、消しておく(次の節で、プレハブから置き直します)
プレハブは、ゲームオブジェクトの「型」です。型を1つ作っておけば、同じ壁をいくつでも置けます。あとで生け垣の色を変えたくなっても、プレハブを直せば、置いた壁が全部まとめて変わります。くわしくは7-1 プレハブの基本概念と作成方法で紹介しています。
迷路を作ろう

プレハブを並べて、迷路にします。
- Hierarchyで右クリック>Create Emptyで、空のゲームオブジェクトを作り、名前をWallsにする(Positionは0, 0, 0)
- PrefabsフォルダのWallを、Wallsの上にドラッグ&ドロップして、子にする
- 下の表のとおりに、名前・Position・Sprite RendererのSizeを変える
- 7つ置き終わるまで、くり返す
| 名前 | Position | Size |
|---|---|---|
| WallTop | (0, 5) | (20, 1) |
| WallBottom | (0, -5) | (20, 1) |
| WallLeft | (-9.5, 0) | (2, 9) |
| WallRight | (9.5, 0) | (2, 9) |
| Wall1 | (-4, -1.5) | (1, 6) |
| Wall2 | (2, 1.5) | (1, 6) |
| Wall3 | (4, 0) | (3, 1) |
上の4つが画面のまわりを囲む壁、Wall1〜3が迷路の中の壁です。WallLeftとWallRightは、画面の端にすき間が出来ないように、半分ほど画面の外にはみ出させています。

再生すると、スライムちゃんが壁で止まるようになります。前回は画面の外まで歩いていけましたが、もう迷子にはなりません。
スライム壁があるだけで、急に「ステージ」っぽくなりましたね!
壁にぶつかって止まるのは、スライムちゃんのRigidbody 2DとCircle Collider 2D、壁のBox Collider 2Dのおかげです。壁にはRigidbody 2Dを付けていないので、押しても動かない「動かない壁」になります。ColliderとRigidbodyの関係は、3-4 当たり判定とPhysics:ColliderとRigidbodyで紹介しています。
向きで絵を替えよう


今のスライムちゃんは、どっちに歩いても正面を向いたままです。素材には、上下左右の4つの向きの歩くコマが入っているので、動いている向きに合わせて、使うコマを切り替えます。
番号の十の位が向き(2が下、4が左、6が右、8が上)、一の位がコマです。どの向きも、#1のタイトルと同じく1 → 2 → 3 → 2の順に並べます。
FrameAnimationにコマの入れかえを足そう
#1で作ったFrameAnimationは、決めたコマを順番に出すだけでした。ここに、コマを入れかえるメソッドを足します。一番下のSetFramesが、今回足すところです。
using UnityEngine;
// 絵(コマ)を順番に切り替えて、パラパラまんがのように動かす
public class FrameAnimation : MonoBehaviour
{
[SerializeField] private Sprite[] frames; // 出す順番に並べたコマ
[SerializeField] private float secondsPerFrame = 0.15f; // 1コマを出す時間
private SpriteRenderer spriteRenderer;
private int frameIndex;
private float timer;
private void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
private void Update()
{
timer += Time.deltaTime;
if (timer < secondsPerFrame)
{
return;
}
timer -= secondsPerFrame;
frameIndex = (frameIndex + 1) % frames.Length;
spriteRenderer.sprite = frames[frameIndex];
}
// コマを入れかえる(今と同じコマなら何もしない)
public void SetFrames(Sprite[] newFrames)
{
if (frames == newFrames)
{
return;
}
frames = newFrames;
frameIndex = 0;
timer = 0f;
spriteRenderer.sprite = frames[frameIndex];
}
}
frames == newFrames- 今使っているコマと同じなら、何もしない。同じ向きに歩いている間は毎フレーム呼ばれるので、ここで止めないと、ずっと1コマ目に戻されて動かなくなる
frameIndex = 0とtimer = 0f- 向きが変わったら、新しい向きの1コマ目から出し直す
PlayerFacingを作ろう
ScriptsフォルダにPlayerFacingを作ります。
using UnityEngine;
// 動いている向きに合わせて、歩くコマ(上下左右の4つ)を切り替える
public class PlayerFacing : MonoBehaviour
{
[SerializeField] private Sprite[] downFrames; // 下に歩くコマ
[SerializeField] private Sprite[] leftFrames; // 左に歩くコマ
[SerializeField] private Sprite[] rightFrames; // 右に歩くコマ
[SerializeField] private Sprite[] upFrames; // 上に歩くコマ
private Rigidbody2D rb;
private FrameAnimation frameAnimation;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
frameAnimation = GetComponent<FrameAnimation>();
}
private void Update()
{
Vector2 velocity = rb.linearVelocity;
// 止まっているときは、最後に向いていた向きのまま
if (velocity.magnitude < 0.1f)
{
return;
}
// 左右と上下で、大きく動いている方の向きにする
if (Mathf.Abs(velocity.x) > Mathf.Abs(velocity.y))
{
if (velocity.x > 0f)
{
frameAnimation.SetFrames(rightFrames);
}
else
{
frameAnimation.SetFrames(leftFrames);
}
}
else
{
if (velocity.y > 0f)
{
frameAnimation.SetFrames(upFrames);
}
else
{
frameAnimation.SetFrames(downFrames);
}
}
}
}
rb.linearVelocity- 今の速さと向き。入力ではなく「実際に動いている向き」を見るので、PlayerMoveは1行も変えずにすむ
velocity.magnitude < 0.1f- ほとんど止まっているときは、向きを変えない。手を離したときに、最後の向きのまま止まる
Mathf.Abs(velocity.x) > Mathf.Abs(velocity.y)- 斜めに歩いているときは、左右と上下の大きい方の向きにする。
Mathf.Absは、マイナスを取った大きさ
- 斜めに歩いているときは、左右と上下の大きい方の向きにする。


PlayerにPlayerFacingを付けて、4つの配列にコマを入れます。
- Down Frames:slime_walk_21、22、23、22
- Left Frames:slime_walk_41、42、43、42
- Right Frames:slime_walk_61、62、63、62
- Up Frames:slime_walk_81、82、83、82
Projectウインドでコマを3枚選んで、配列の名前(Down Framesなど)の上にドラッグ&ドロップすると、3つまとめて入ります(入った順番が1 → 2 → 3になっているか、確かめてください)。そのあと+で4つ目を足して、2コマ目をもう1回入れると早いです。
再生して矢印キーで歩くと、歩く向きにスライムちゃんが向きを変えます。上に歩くと、ちゃんと後ろ姿になりますよ。
Unityには、Animator(アニメーションの状態をつなぐ仕組み)もありますが、このシリーズでは使いません。向きが4つだけなら、コマを入れかえるスクリプトの方が、何が起きているかを追いやすいからです。Animatorは12-2 アニメーションを付けよう:AnimationとAnimatorで紹介しています。
ぶつかったらぽよん


壁で止まるようにはなりましたが、ぶつかったときに何も起きないと、ちょっとさみしいですよね。そこで、壁にぶつかった瞬間に、スライムちゃんをぽよんとつぶして、元に戻します。
- 上下の壁にぶつかったら、横に広がって、縦につぶれる
- 左右の壁にぶつかったら、縦に伸びて、横につぶれる
ぶつかった向きでつぶれ方を変えると、「ぶつかった!」という手応えがはっきり出ます。
SquashOnBumpを作ろう
ScriptsフォルダにSquashOnBumpを作ります。
using System.Collections;
using UnityEngine;
// 壁にぶつかったら、ぽよんとつぶれてから元の形に戻る
public class SquashOnBump : MonoBehaviour
{
[SerializeField] private float minBumpSpeed = 2f; // これより遅くぶつかったときは、つぶれない
[SerializeField] private float squashSeconds = 0.08f; // つぶれるまでの時間
[SerializeField] private float returnSeconds = 0.2f; // 元の形に戻るまでの時間
private Vector3 baseScale;
private void Start()
{
baseScale = transform.localScale;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.relativeVelocity.magnitude < minBumpSpeed)
{
return;
}
// 横の壁なら横に、上下の壁なら縦につぶれる
Vector2 normal = collision.GetContact(0).normal;
Vector3 squashScale;
if (Mathf.Abs(normal.x) > Mathf.Abs(normal.y))
{
squashScale = Vector3.Scale(baseScale, new Vector3(0.7f, 1.25f, 1f));
}
else
{
squashScale = Vector3.Scale(baseScale, new Vector3(1.25f, 0.7f, 1f));
}
StopAllCoroutines();
StartCoroutine(Squash(squashScale));
}
private IEnumerator Squash(Vector3 squashScale)
{
yield return ChangeScale(transform.localScale, squashScale, squashSeconds);
yield return ChangeScale(squashScale, baseScale, returnSeconds);
}
// from の大きさから to の大きさへ、seconds 秒かけて変える
private IEnumerator ChangeScale(Vector3 from, Vector3 to, float seconds)
{
float time = 0f;
while (time < seconds)
{
time += Time.deltaTime;
transform.localScale = Vector3.Lerp(from, to, time / seconds);
yield return null;
}
transform.localScale = to;
}
}
OnCollisionEnter2D- Is Triggerではない当たり判定どうしが、ぶつかった瞬間に呼ばれる。前回の扉(
OnTriggerEnter2D)は「重なった」とき、こちらは「ぶつかった」とき。くわしくは6-10 衝突を検知しよう:当たり判定のイベントとタグで紹介しています
- Is Triggerではない当たり判定どうしが、ぶつかった瞬間に呼ばれる。前回の扉(
collision.relativeVelocity- ぶつかったときの速さ。壁ぞいにそっと触れただけでつぶれないように、
minBumpSpeedより遅いときは何もしない
- ぶつかったときの速さ。壁ぞいにそっと触れただけでつぶれないように、
collision.GetContact(0).normal- ぶつかった面の向き。横を向いていれば左右の壁、縦を向いていれば上下の壁
Vector3.Scale- x・y・zをそれぞれかけ算する。元の大きさ(0.8)に対して、横1.25倍・縦0.7倍のようにつぶす
ChangeScale- 前回のScreenFlashの
ChangeColorと同じ形。色の代わりに大きさを、Lerpで少しずつ変える。一度覚えた形は、いろいろな演出に使い回せます
- 前回のScreenFlashの


PlayerにSquashOnBumpを付けたら、再生して壁にぶつかってみましょう。





つぶれるのは0.08秒で一瞬、戻るのは0.2秒でゆっくり。前回のキラッと同じで、速さに差を付けるのがコツね!
完成チェック


Titleシーンを開いて再生し、最初から最後まで通して遊びます。
- 「はじめる」を押すと、生け垣の迷路のステージに切りかわる
- スライムちゃんが壁を通りぬけず、画面の外にも出ない
- 上下左右に歩くと、その向きの絵に切りかわる(上は後ろ姿)
- 壁にぶつかると、ぽよんとつぶれて元に戻る
- 扉に入ると、白く光ってからエンディングへ。「タイトルへ」でタイトルに戻る
今回も、タイトルからエンディングまで、ちゃんと遊べる形のままです。ステージが迷路になったぶん、扉にたどり着いたときのうれしさも増えました。
ビルドして遊ぼう


前回と同じように、ビルドして.exeで遊びます。
- File>Build Profilesを開いて、Buildを押す
- 前回と同じ
Build/StarGardenのフォルダを選ぶ(上書きしてOK) - 出来たStarGarden.exeを起動して、迷路を抜けて扉までたどり着けるか遊んでみる
今回はシーンを増やしていないので、Scene Listはそのままで大丈夫です。
Stage1シーンを保存(Ctrl+S)してからビルドしましょう。保存していない変更は、ビルドしたゲームに入りません。壁を置いたのに.exeでは壁が無い、というときは、まず保存を確かめてください。
あとがき
今回は、生け垣の壁をプレハブにして迷路を作り、スライムちゃんが歩く向きに合わせて絵を替えて、壁にぶつかったら「ぽよん」とつぶれるようにしました。新しく作ったスクリプトは2つだけですが、動かしたときの気持ちよさは、前回とはずいぶん違うと思います。
次回は、いよいよ星を置きます。星を全部集めないと、扉が開かないようにして、取ったときにはキラキラと「+1」が出る演出も付けますよ!



迷路の中を歩くの、ちょっとクセになってきました・・・。ぶつかるのも、わざとやりたくなりますね!



ぽよんが楽しくなったら、手応えの演出は成功ね!次は星を集めて、扉を開けにいこう!
コメント
コメント一覧 (1件)
[…] 前回:#3 壁を置いて、歩くすがたを付けよう […]