Unityでヨッシーアイランドのタイトルのアレを再現してみよう

5 min read読了の目安(約5100字

当記事はUnity #2 Advent Calendar 2020 11日目の記事となっております。

https://qiita.com/advent-calendar/2020/unity2

はじめに

皆さまはヨッシーアイランドをプレイしたことはありますでしょうか?
プレイしたことある方も、プレイしたことが無い方も以下の動画の初めの部分をまずはご覧ください。

ヨッシーアイランドのタイトル画面では2Dのオブジェクトがあたかも3D空間にあるような表現が使用されています。
通常のスーパーファミコン上ではこのような表現は行えないのですが、ヨッシーアイランドのロムはスーパーFXチップという特殊なチップを搭載しており、そのチップの演算能力によってあのようなタイトル演出を実現しておりました。

今回はそんなヨッシーアイランドのタイトル演出をUnity上で再現してみました。

実装成果物

以下のツイート内動画をご覧ください。

使用した画像素材

今回の実装の際に使用した画像素材は全て自作となっております。
実際に当記事の内容を試してみたりする際にご自由にどうぞ。
その他の用途で用いる際には一言ツイッターの方にご連絡お願い致します。





実装

今回作成するものの方針として、以下のような点が挙げられます。

  • ドット絵表現
  • 2Dなのに3Dっぽい表現

これらを実現するために以下のように実装を行いました。

ドット絵表現

ドット絵表現の項目内で記載する内容につきましては、以下のUnity Blog内の記事にて詳しく書かれています。
気になる点等がございましたらこちらをご覧ください。

https://blogs.unity3d.com/jp/2019/03/13/2d-pixel-perfect-how-to-set-up-your-unity-project-for-retro-8-bits-games/

スプライトのインポート設定

各スプライトのインポート時には以下のように設定を行いました。

当記事内の画像素材を使用する際にはPixel Per Unitの値を16とし、PivotをBottomに設定しておいてください。

Filter ModeがBilinear等の補完が入ってしまう設定であると、ドット絵がボヤけてしまうという問題があります。
そのため、補完なしであるPoint(no filter)に設定してあげる必要があります。
また、Compressionが有効であると、圧縮された結果
一部のドットの色味が変わってしまう
ことがあります。
そのため、圧縮が行われないNoneを設定してあげる必要があります。

カメラの設定

カメラのオブジェクトにPixel Perfect Cameraコンポーネントをアタッチし、以下のように設定を行いました。

当記事内の画像素材を使用する際にはAssets Pixel Per Unitの値を16としてください。

Upscale Render Textureを適用してあげることによってピクセルパーフェクトな状態を維持しつつ、解像度に合わせたスケーリングが行われるようになります。
また、スプライトの回転・移動・拡大縮小を行った際にもピクセルパーフェクトな状態を維持した状態になります。
Reference Resolutionに関しましては、今回のゲーム画面を16:9の比率の解像度で作成したため、
Upscale Render Textureを設定したことによって行われる自動スケーリングが問題なく行われる16:9の比率の解像度を指定してあります。

2Dなのに3Dっぽい表現

事前準備

Edit-> Project Settings -> Tags and Layersを開き、以下のようにSorting Layerを追加しました。

スプライトの設定

ヒエラルキー上のスプライトについて、以下の二種類に区分した上で説明を行っていきます。

  • Field
    地面となるスプライトです。
  • Entity
    地面の上に存在するスプライトです。
Field

以下のように設定を行いました。

今回、FieldにはSprite Shapeを用いました。
試しに作ってみようと思っている方はSprite Shapeでなくとも、Tilemapでも普通のSpriteでも問題ありません。

FieldはXZ平面と平行であるようにするためにTransformのRotationのX軸の値を90[deg] としました。
また、Fieldは常にEntityの下に描画されるようにするためにSorting LayerはFieldを設定しました。
Fieldは先ほど設定したSorting Layer上での順序において、Entityよりも優先度が下であるため常に下に描画されることが保証されます。

Entity

以下のように設定を行いました。

Entityは常にFieldの上に描画されるようにするためにSorting LayerはEntityを設定しました。
また、FieldがXZ平面と平行であるため、画面上の位置の調整についてはTransformのPositionのX軸, Z軸の値を変更することで行います。

BillboardObject

二種類のスプライトには共通してBillboardObjectを持たせています。
このスクリプトをアタッチすると、スプライトが常にカメラの方を向く機能を追加することができます。

スクリプトとしては、以下のような実装となっています。

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

public class BillboardObject : MonoBehaviour
{
    [SerializeField]
    Camera _targetCamera;

    private void Start()
    {
        if (_targetCamera == null)
        {
            _targetCamera = Camera.main;
        }
    }

    private void LateUpdate()
    {
        transform.rotation = _targetCamera.transform.rotation;
    }
}

このスクリプトは、_targetCameraとして与えたCameraの方向を向く機能を提供しています。
もし、対象となるカメラを与えていない場合には、現在のScene中のMainCameraタグがついているカメラを自動で対象とするようになっています。

このスクリプトがアタッチされたオブジェクトは、LateUpdateのタイミングで対象のカメラのRotationと自身のRotationの値を同期するようにしています。
これは、Updateで行われるであろうカメラTransform情報の更新の後で値が同期されるようにするためにLateUpdateを用いています。
Unityにおける内部イベントの実行順序に関しては、以下の公式マニュアル内をご覧ください。

https://docs.unity3d.com/ja/2018.4/Manual/ExecutionOrder.html

おわりに

今回、ヨッシーアイランドのタイトルのアレを再現するための実装内容について書かせて頂きました。
この記事を見た皆様もぜひレトロ風なゲームを作りましょう!!

もし、なにかご連絡等がございましたらツイッターの方にお願い致します。

https://twitter.com/unisannino

おまけ

今回作成したフィールドの上でキャラクターを操作して歩かせてみました。