【Unity入門⑮】歩行に合わせて背景をスクロールさせよう!

Unity2D入門シリーズ

こんにちは!夜の街2Dアクションゲームを制作中の怪獣です🦖

今回は歩行に合わせて背景画像をスクロールさせる方法 を解説します!

背景があるだけでよりゲームらしさがグッと増して、世界観が一気に広がりますよね!
ただ背景を用意するだけではプレイヤーが移動した際に背景画像が置いてきぼりになってしまうので、
歩行に合わせて背景をスクロールさせるようにします!


この記事でやること

✅ 背景オブジェクトを作る
✅ 背景スクロール用スクリプトを作る
✅ プレイヤーの動きに合わせて背景を動かす

① 背景オブジェクトを作成する

背景画像をHierarchy上に配置していきます!

背景画像を配置する

1.Hierarchyに背景画像をドラッグする

2.各背景の名前を変更します

(ここではSky、Cloud、Mountainにします。)



Sorting Layer を追加する

2Dゲームでは、
画像の表示の前後関係は Sorting Layer で管理します。

■ Sorting Layer を作る手順

  1. 背景オブジェクトを選択
  2. Inspector → SpriteRenderer
  3. Sorting Layer → Add Sorting Layer…

すると以下画面が開きます。
+ボタンクリックし、新しいレイヤー名BG(background)を追加します。
追加したレイヤーを一番上に持ってきて、Layer0になるようにします。

レイヤーは上にあるほど「奥」の扱いになります。
今回は背景画像なので、一番奥に設定します!

追加したら、それぞれの背景オブジェクト全てに(Sky、Cloud、Mountain、Mountain2)のSorting LayerにBGを設定します。

Sorting Layer :BG


レイヤーの描画順番を設定する

このままだと背景の描画順が同じレベルになっており、全て表示が出来ていないので、
お絵描きソフトのレイヤー機能のように、画像の描画順番を設定します!

以下のように設定します。
■レイヤー順
①← レイヤーが手前 レイヤーが奥→④

①山
 ∟②山2
  ∟③雲
   ∟④空

  • Sky
    • Order in Layer:-4
  • Cloud
    • Order in Layer:-3
  • Mountain
    • Order in Layer:-2
  • Mountain2
    • Order in Layer:-1

背景の位置を調整する

Inspector の Transform を以下のように調整します。

  • Position:(0, 0, 0)(まずは0でOK)
  • Scale:必要に応じて調整(背景が画面に合うように)

②背景の子オブジェクトを作成(左側用・右側用)

①で背景を作成した状態のままだと、画像の端っこに移動した際に背景が足りなくて見切れてしまうため、更に拡大していきます。
ここで、①で作った親の背景オブジェクトに対して、子オブジェクトを作成します。
背景オブジェクトの下に 左右の背景 を子として持たせておくことで、後で「無限スクロール」に拡張しやすくなります。

2-1. Left / Right に背景画像を複製する

①で作成した背景を親オブジェクトとし、親に対して子オブジェクトを複製します。

■Skyオブジェクトの作成例

  1. いまシーン上にあるSkyオブジェクトをコピペして、
    Skyオブジェクト配下に子として2つ複製する
  2. 片方を Left、もう片方を Right と命名
  3. Left
    • Postion:40に変更(※各自の画像サイズに要調整)
  4. Right
    • Postion:40に変更(※各自の画像サイズに要調整)

こうすることで、 左右に背景が拡張されます!
また、親オブジェクトからコピペして貼り付けることで、①で設定したSorting Layer Order in Layerの設定を引き継いだ状態にすることができます✨

Leftの設定

Rightの設定

■設定後のScene画面↓

同じように、Sky、Cloud、Mountain、Mountain2も子として複製します。

③背景スクロール用スクリプトを作成

  1. Projectビューで右クリック
  2. Create → C# Script
  3. 名前を BackgroundScroller.csにします

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BackgroundScroller : MonoBehaviour
{
    // Range:最小値と最大値を決めれる
    [SerializeField, Header("視差効果"), Range(0, 1)]
    private float _parallaxEffect;

    private GameObject _camera;
    private float _length;
    private float _startPosX;

    // Start is called before the first frame update
    void Start()
    {
        _startPosX = transform.position.x;
        // 画像の横幅のサイズを取得
        _length = GetComponent<SpriteRenderer>().bounds.size.x;
        _camera = Camera.main.gameObject;

    }

    // Unity上のメソッド
    // 設定した一定時間で実行されるメソッド
    private void FixedUpdate()
    {
        _Parallax();
    }

    private void _Parallax()
    {
        // カメラとの距離を代入
        float temp = _camera.transform.position.x * (1 - _parallaxEffect);
        float dist = _camera.transform.position.x * _parallaxEffect;

        transform.position = new Vector3(_startPosX + dist, transform.position.y, transform.position.z);

        // カメラとの距離が画像の横幅分離れたら位置をカメラの座標に移動させることで
        // 画像が途切れずにループしているように見える
        if (temp > _startPosX + _length)
        {
            _startPosX += _length;
        }
        else if (temp < _startPosX - _length)
        {
            _startPosX -= _length;
        }
    }
}

各処理の説明:なにをしている?

[SerializeField, Header("視差効果"), Range(0, 1)]
private float _parallaxEffect;
  • SerializeField:Unity上のInspectorで数値をいじれるようにします
  • Header:Inspector上に見出しを出す
  • Range(0,1):スライダーで 0〜1 の範囲で調整できるようにする

✅ これにより「背景がどれくらいカメラについてくるか(視差)」をスライダーで調整できます。


Start() で初期値を準備

_startPosX = transform.position.x;
_length = GetComponent<SpriteRenderer>().bounds.size.x;
_camera = Camera.main.gameObject;

_startPosX

背景の「基準となる開始位置X」です。
あとでループ処理で、この基準を 横幅分ずらすのに使います。

_length

SpriteRenderer.bounds.size.x背景画像の“ワールド上の横幅” を取得します。

重要:ここで取っているのは「ピクセル数」ではなく
Unity空間(ワールド座標)の幅です。
(Pixels Per Unit の設定により値は変わります)

_camera

Camera.main は「MainCameraタグが付いたカメラ」を取ってきます。
背景は カメラの位置を基準に動くので参照が必要です。


FixedUpdate() で一定間隔で実行

private void FixedUpdate()
{
    _Parallax();
}

FixedUpdate一定時間ごとに呼ばれる更新関数です。
(主に物理計算のタイミング)

このコードでは背景移動を FixedUpdate に載せています。

背景は物理ではないので、一般的には LateUpdate でもOKです。
ただ「カメラがRigidbodyで動く」などの場合は FixedUpdate 運用もアリです。


_Parallax() が本体(視差+ループ)

カメラ位置から2つの値を作る

float temp = _camera.transform.position.x * (1 - _parallaxEffect);
float dist = _camera.transform.position.x * _parallaxEffect;

ここが最重要です。

  • dist背景を動かす量(視差ぶん)
  • tempループ判定に使う量

_parallaxEffect が 0.3 なら、

  • dist = カメラX * 0.3(背景はカメラの30%だけ動く)
  • temp = カメラX * 0.7(残り側の値)

という形になります。


背景を実際に動かす

transform.position = new Vector3(_startPosX + dist, transform.position.y, transform.position.z);

背景のX座標を

  • 開始位置 _startPosX
  • 視差分 dist

で決めています。

つまり、

✅ カメラが右に動く
✅ 背景も右に動くけど、_parallaxEffect が小さいほどゆっくり
→ 「奥行きがある」ように見える


画像が途切れない“無限ループ”判定

if (temp > _startPosX + _length)
{
    _startPosX += _length;
}
else if (temp < _startPosX - _length)
{
    _startPosX -= _length;
}

ここは「背景がカメラから一定距離離れたら、基準位置を横幅分ずらす」処理です。

  • カメラが進み続けると、背景はいつか端が見えてしまう
  • そこで、背景の“基準位置” _startPosX横幅 _length 分だけ移動
  • 結果、背景が途切れずループしているように見えます

この「基準位置をずらす」方式は、見た目が自然で便利です。


④ Unity上で設定する

「Sky、Cloud、Mountain、Mountain2」 をまとめて選択し、Add Componentをクリックし③で作成したBackgroundScroller.csを適用します。


動作確認

➡️背景が歩行に合わせて少しずつ移動しているのが分かりますね‼️


まとめ

最後まで読んでいただきありがとうございました。
この記事が少しでもゲーム制作のお役に立てたらうれしいです🦖

今回やったこと:

✔ 背景オブジェクト作成
✔ スクリプト作成
✔ プレイヤーの動きに合わせてスクロール

これだけでゲームの完成度が一気に上がります!

コメント

タイトルとURLをコピーしました