【Unity/2D】Flappy Bird風ゲームを作ってみる話 #9 ゲームの背景を作る

記事をご覧いただき、誠にありがとうございます。

投稿主の無能です。

前回は、ゲームオーバーの処理を実装しました。

今回は、ゲームの背景を作っていきたいと思います。

背景の画像を探す

まずは背景の画像を探します。

今回は背景を動かして、躍動感を付けたいと思います。

そのため、背景がループしてもあまり違和感を覚えない画像を使用します。

今回は青空と虹の画像を二枚重ねて、青空に虹が掛かったような見え方にしていきます。



※二次配布に該当するため、リンク先からダウンロードしてください
※イラストACの利用にはアカウントが必要です

青空の画像は.jpegで良いですが、虹の画像は.pngでダウンロードしてください。

.png形式の画像だと背景が透過されるので、画像が重なっても虹の部分以外は透過して、青空の画像が見えます。

他の良い組み合わせが見付かったら、自由に選んで大丈夫です。
今回は青空と虹の組み合わせで説明します。

ダウンロードが終わったら、Unityへインポートします。

Unityでの作業

画像のインポート

次にUnityに画像をインポートします。

めたんや土管の画像と同じSpritesフォルダにインポートしてリネームします。

画像をSpritesフォルダにインポートする

インポートした画像をリネーム

インポートしたら、一枚ずつ設定を変更します。

画像のInspectorビューの中程の下辺りにWrap Modeという項目があり、デフォルトではClampになっています。

Wrap Mode

ここをClampではなく、ドロップダウンメニューからRepeatにします。

ドロップダウンメニューからRepeatを選択

後は忘れずにApplyボタンで変更を適用します。

Applyボタンで変更を適用

ではもう一枚の画像も同様の手順で変更してください。

Wrap ModeのClampだと、画像はその場に固定される設定です。

そのため、画像を動かしたりすると、画像の端がぐいーっと表示が引き延ばされたようになります。

そこでRepeatに変更すると、例えば画像の右端に到達すると、左端が再度表示されます。

一枚の画像を丸めて筒状にして、画像の表面の端同士をくっつけたようなイメージです。
画像の筒を回すと、途切れずに画像が見えるようになりますね。

画像の表示方法で躓いたときは、Wrap Modeの変更を一つの手段として選択肢に残しておくと解決できる場合があります。

では画像を表示させるオブジェクトを用意しましょう。

オブジェクトを用意する

用意するオブジェクトですが、3D Object > Quadというオブジェクトを使用します。

2Dのゲームなのに3Dのオブジェクトを使う理由は、マテリアルを使って画像を表示することと、Quadがオブジェクトとして軽量だからということ、そしてオブジェクトなので、自由に画像の順序を決められることが理由です。

やっていく内に何となく言いたいことが掴めると思います。

では親オブジェクトとなる空のオブジェクトを作成して「BackGrounds」という名前にします。

座標がずれていたら0にします。

空のオブジェクトを作成して「BackGrounds」とする

BackGroundsの子オブジェクトとしてQuadを作成します。

3D Object > Quadを作成

名前を「Back」にします。

名前を「Back」にする

ではQuadを用意したので、このQuadに設定するためのマテリアルを作成します。

マテリアルを作成

まずはProjectビューに新たに「Materials」フォルダを作成します。

Projectビューに「Materials」フォルダを作成

Materialsフォルダの中に入って、Materialを作成し、名前を「Back」にします。

Materialを作成

名前を「Back」にする

これでQuadオブジェクトのBackに設定するマテリアルが出来ました。

画像をマテリアルに設定

ではBackマテリアルに青空の画像を設定します。

BackマテリアルのInspectorビューを見ると、一番上にDiffuseという項目があります。

このDiffuseの右端の四角に表示させたい画像を設定します。

右端の四角に表示させたい画像を設定する

右下にある小さなSelectボタンを押し、目的の画像を選択します。

Backマテリアルなので青空に画像になります。

青空の画像を選択

これでDiffuseに青空の画像が設定できました。

Diffuseに青空の画像が設定できた

Materialを複製して設定

今度はBackマテリアルを複製して「Front」にリネームします。

Backマテリアルを複製して「Front」にリネーム

Frontマテリアルは虹の画像を設定します。

虹の画像を設定

これでMaterialの準備が出来たので、BackのQuadオブジェクトを複製して、こちらも「Front」にリネームします。

BackのQuadオブジェクトを複製して「Front」にリネーム

Quadにマテリアルを設定

ではQuadオブジェクトにマテリアルを設定します。

Mesh Rendererの中にMaterialsという項目があり、閉じられているので表示します。

Mesh RendererのMaterials

ここにBackのQuadオブジェクトならBackマテリアルを、FrontのQuadオブジェクトならFrontマテリアルを設定します。

BackのQuadオブジェクト

FrontのQuadオブジェクト

これでマテリアルが設定できました。

Quadオブジェクトの設定

ではQuadオブジェクトの設定をしていきましょう。

まずQuadオブジェクトの表示の順番ですが、Positionのzが大きくなるほど、カメラから遠ざかっていきます。

ですので、青空のBackを2、虹のFrontを1にしてやると、青空に虹が掛かったように見えます。

後はQuadオブジェクトの大きさですが、Scaleで変更します。
大きさはお好みで調整してください。

BackのTransform

FrontのTransform

青空に虹が掛かったように表示できた

ここまでの手順で自由にマテリアルを重ねることができるので、もっと重ねたい場合は自由に追加してください。

ではスクリプトを書いていきます。

スクリプトでマテリアルを動かす

ではスクリプトを書いて、マテリアルを動かしてみたいと思います。

ここら辺も2Dシューティングをやった方なら既出の内容になります。

では新たにスクリプトを作成し、名前を「BGController」にします。

新たにスクリプトを作成し名前を「BGController」にする

作成したスクリプトを、QuadオブジェクトのBack・Front双方にアタッチします。

QuadオブジェクトのBack・Front双方にアタッチ

ではスクリプトを書いていきましょう。

BGController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BGController : MonoBehaviour
{
    #region Var-Scroll
    [Header("背景のスクロール速度")]
    [SerializeField] float scrollSpeed = 1f;
    [Header("横方向の背景移動")]
    [SerializeField] scrollDirection_X direction_X;
    [Header("縦方向の背景移動")]
    [SerializeField] scrollDirectiom_Y direction_Y;
    #endregion

    #region Var-FollowTargetObject
    [Header("動きを追従するオブジェクト")]
    [SerializeField] GameObject followObject;
    [Header("指定のオブジェクトの動きに併せて背景を動かす")]
    [SerializeField] bool objectFollow = false;
    [Header("指定のオブジェクトの動きに追従する割合")]
    [SerializeField] float objectMove = 1f;
    #endregion

    #region Var-Internal
    Vector2 offset;                                             // オフセット
    Renderer material;                                          // マテリアルのレンダラー
    const float scrollMax = 1f;                                 // スクロールの最大値
    const string mainTex = "_MainTex";                          // _MainTextの文字列
    #endregion

    #region Var-internal
    enum scrollDirection_X                                      // 背景移動(X方向)
    {
        NoMove = 0, LeftToRight = -1, RightToLeft = 1           // 動き無し,左→右,右→左
    }
    enum scrollDirectiom_Y                                      // 背景移動(Y方向)
    {
        NoMove = 0, BottomToUpper = -1, UpperToBottom = 1       // 動き無し,下→上,上→下
    }
    #endregion

    #region Start
    void Start()
    {
        // マテリアルのレンダラーを取得
        material = GetComponent();
    }
    #endregion

    #region Update
    void Update()
    {
        // 追従フラグがfalseの場合
        if (!objectFollow)
        {
            // objectMoveを0にする
            objectMove = 0;
        }
        // ゲーム内時間で0からscrollMax(1)になり、0に戻って繰り返す
        float _scrollX = Mathf.Repeat(Time.time * scrollSpeed * (int)direction_X, scrollMax),
              _scrollY = Mathf.Repeat(Time.time * scrollSpeed * (int)direction_Y, scrollMax);
        // 追跡するオブジェクトの位置を取得
        float _movePointX = followObject.transform.position.x,
              _movePointY = followObject.transform.position.y;
        // オフセットを作成
        offset = new Vector2(_scrollX + _movePointX * objectMove,     // x
                             _scrollY + _movePointY * objectMove);    // y
        // マテリアルにオフセットを設定
        material.sharedMaterial.SetTextureOffset(mainTex, offset);
    }
    #endregion

}
では見ていきましょう。

メンバ変数

まず背景のスクロール速度として、floatのscrollSpeedになります。

この変数に与えた値が画像の流れる速さになります。

そして横の背景移動のdirection_Xになります。

このdirection_XはUnityのInspectorビューで選択できるようにするので、後述の説明と合わせると理解してもらえるかと思います。

direction_Yも同じなので、ここでの説明は割愛します。

次は動きを追従するオブジェクトを入れます。
GameObjectのfollowObjectです。

ここに動きを追従するオブジェクトを入れて、背景が移動する量と追従オブジェクトの移動量を足し合わせて、背景がその分移動する機能になります。

次は追従オブジェクトの動きに合わせて、追従オブジェクトが動いた分だけ背景を動かすかどうかのフラグでboolのobjectFollowです。

このチェックがあれば、背景はプレイヤーの動いた分だけ動くようになるし、チェックが無ければ設定した分だけを移動します。

次に、指定のオブジェクトの動きに追従する割合となるfloatのobjectMoveになります。

objectMoveの数値が大きいほど、指定のオブジェクトを動かした時の背景の動きが大きくなります。

次は内部処理用の変数になります。

まずオフセットになるVector2のoffsetです。

次にマテリアルのレンダラーとなるRendererのmaterialです。

次はスクロールの最大値となる、定数のfloatのscrollMaxです。

次は定数の文字列で、_MainTexという文字列のstringのmainTexです。

最後に列挙型の変数enumになります。

列挙型というのは、簡単に言えば数字に名前を付けて格納する配列のようなものです。

イメージで例えると、スーパーの野菜コーナーに並べられた野菜だと考えてください。
こっちのほうれん草は〇円、トマトは〇円と言った感じで、野菜の名前があって、そこには値段が書いてあります。

野菜の名前がenumで列挙する名前で、名前毎に値段が付けられてあるようなイメージです。

列挙型のscrollDiretionのX・Yは、それぞれ横・縦の背景の動かす方向を決める変数です。

scrollDiretion_Xは横方向で、移動無しのNoMoveが0、左から右への移動となるLeftToRightが-1、右から左への移動となるRightToLeftが1になっています。

scrollDiretion_Yは縦方向で、移動無しのNoMoveが0、下から上の移動となるBottomToUpperが-1、上から下への移動となるUpperToBottomが1になっています。

そしてこのscrollDiretionを扱うのが、先程のdirectionのX・Yになります。

何故こんな書き方にしたのかというと、これでdirectionのX・Yがドロップダウンリストになるからです。

ドロップダウンリストにはscrollDiretionで設定した値の名前が入ります。

これで背景が移動する方向を選択して設定することができます。

Start関数

次はStart関数です。

ここではマテリアルのレンダラーを取得します。

Start関数は以上です。

Update関数

次はUpdate関数です。

はじめに追従する指定のオブジェクトが無い場合は、指定のオブジェクトの動きに追従する割合を0にします。

次はfloatのscrollのX・Yを作成し、Mathf.Repeatで最小値から最大値のscrolllMax(1)までの範囲を繰り返します。

次にfloatのmovePointのX・Yを作成し、追従する指定のオブジェクトの位置を取得します。

そして作成したscrollとmovePoint、objectMoveを使ってオフセットを作ります。

そして作成したオフセットを、マテリアルのオフセットに設定します。

ここで指定している_MainTexですが、マテリアルのInspectorビューのShaderの右側にあるEditボタンでShaderの中を確認すると、_MainTexが使われていることが確認できます。

Shaderの右側のEditボタンを押す

_MainTexが確認できる

簡単に言うと、DiffuseのOffsetを変更しています。

DiffuseのOffsetを変更している

スクリプトの内容は以上です。

では動作確認前の準備をしていきます。

動作確認前の準備

では動作確認前の準備をしていきます。

QuadオブジェクトのInspectorビューに追加された項目を設定します。

無能は画像の通りに設定しましたが、動きを見て自由に設定してください。

Backの設定

Frontの設定

これで設定が出来ました。

動作確認

では動作確認してみましょう。

画像の通りに設定すると、背景が右から左へゆっくりと移動することが確認できます。

そして背景が左端に到達すると、背景が右端からスクロールします。

背景がゆっくりと移動し端に到達するとスクロールする

これで動く背景が実装出来ました。

まとめ

今回は
  • 背景の画像を探してダウンロードした
  • QuadオブジェクトとMaterialを用意し、Materialに画像を設定した
  • スクリプトを書いて、動く背景を実装した
という事をやりました。

次回は、音が無いと寂しいので、BGMとジャンプする時のSEを付けていきたいと思います。

では、また次回!

コメント