Unityで一部のレイヤーだけピクセルパーフェクトにしてみた

この記事は Unity Advent Calendar 2020 10日目の記事です。

 

最近『ボクノシメイ』というドット絵アドベンチャーゲームを作っているのですが、いろいろ表現を試している中で「一部のレイヤー(オブジェクト)のみピクセルパーフェクトにしたい」という状況がありました。

そのときに試行錯誤して実現した方法をまとめました。

 

先に方針と欠点をまとめると

今回は以下のものを一切使いません

  • PixelPerfectCamera
  • カメラスタッキング
  • 自作シェーダー/マテリアル

ほとんどの環境で、かつシェーダー知識がなくても簡単にできる方法です。

 

先に方法を簡単にまとめると、このようになります。

 

ただし、この方法ではピクセルパーフェクトにしたレイヤーが必ず前面に表示されるという欠点もあります。

自分の需要には合っていたのですが、用途は限られるかもしれません。

 

環境

Unity2019.4.8f1を使用しています。

レンダーパイプラインはURP(Universal Render Pipeline)のForward Rendererで使用していますが、2D RendererやBuilt-inレンダーパイプラインでも確認済みです。
(2D Rendererでは現状カメラスタッキングが使えないのですが、そのようなPixelPerfectCameraとの併用ができない状況で実現したかったというのが本来の目的でした)

 

Built-inレンダーパイプラインの場合は項目名が若干違ったりするので、適宜読み替えてください。

 

そもそもピクセルパーフェクトとは?

Web業界でも「ピクセルパーフェクト」という言葉は使われているそうですが、ここでいう「ピクセルパーフェクト」というのは「ある解像度のピクセルに必ず則って画面を表示する」という意味です。

 

 

斜めの線や長方形ピクセルが存在しない、右側のような表示をピクセルパーフェクトと言います。

ドット絵のゲームではよく使用されています。

 

一部のみピクセルパーフェクトにする方法

それでは本題。

 

今回はモデルのサンプルとして、こちらの無料アセットを使用しました。

 

デモシーンを少し改変して、このような見た目に。

 

今回は左下のテントをピクセルパーフェクトにしたいと思います。

 

RenderTextureを作成する

まずはRenderTextureを作成します。

Projectビューで右クリック → Create → RenderTexture で適当に名前をつけて作成。

 

作成したRenderTextureのインスペクタを開き、以下のように設定します。

  • SizeをPixelPerfectにしたい解像度にする
  • Anti-aliasingをNoneにする
  • FilterModeをPointにする

 

RawImageを作成する

次に、RenderTextureを表示するRawImageを作成します。

Hierarchyビューで右クリック → UI → RawImage でCanvasとRawImageを作成。

 

作成したRawImageを画面全体に広げ、RawImageコンポーネントのTextureに先ほど作成したRenderTextureを指定します。

投影用カメラを作成する

RenderTextureに投影するためのカメラを作成します。

既存のMainCameraを複製してPixelCameraとし、MainCameraの子オブジェクトにします。
(MainCameraと一緒に移動させるため)

 

AudioListenerコンポーネントはシーンに複数存在できないので、PixelCameraに付いているAudioListenerは削除しておきます。

 

PixelCameraのCameraコンポーネントを以下のように設定します。

  • Anti-aliasingをNoneにする
  • Priorityを0以上にする
  • TargetTextureに先ほど作成したRenderTextureを指定する

 

ここまですると、画面全体がRenderTextureの解像度で表示されます。

 

画面全体がピクセルパーフェクトになりました!

(ここまでなら、PixelPerfectCameraを使えば簡単に実現できます)

 

レイヤーを設定する

最後に、ピクセルパーフェクトにしたいレイヤーを分けます。

 

エディタ右上の Layers → Edit Layers… からTags&Layersを開き、ピクセルパーフェクト用のレイヤーを作成します。

今回は「Pixel」という名前のレイヤーを作成しました。

 

次に、ピクセルパーフェクトにしたいオブジェクトのレイヤーをPixelレイヤーに変更します。

今回はテントをPixelレイヤーに指定しました。

 

そして、MainCameraのCameraコンポーネントにあるCullingMaskからPixelレイヤーを外し、逆にPixelCameraのCullingMaskはPixelレイヤーのみにします。

 

これを行うことで、見事テントのみをピクセルパーフェクトにすることができました!

 

いろいろ試してみる

テントを動かしてみたり(火事)

 

火のレイヤーをPixelに変更すれば、パーティクルももちろんピクセルパーフェクトになります。

 

欠点

ピクセルパーフェクトにしたオブジェクトはCanvas上に表示しているので、必ず前面に表示されるというのが欠点としてあります。

上の動画でも草が背面に隠れていたり、奥に移動しても丸太の前面に表示されていたりするのが分かるかと思います。

 

CanvasのRenderModeによってある程度は調整できますが、元のオブジェクト順そのままという訳にはなかなかいかなそうです。

 

まとめ

PixelPerfectCamera、カメラスタッキング、自作シェーダー/マテリアルは一切使わず、一部のレイヤー(オブジェクト)のみをピクセルパーフェクトにする方法をまとめました。

 

この方法であれば、カメラスタッキングが現状使えない2D Rendererでも実現でき、マテリアルの変更も必要ありません。

 

ただし欠点として、ピクセルパーフェクトにしたオブジェクトがCanvas上に表示されるため、工夫をしないと前面に表示されてしまいます。

 

 

ちなみに自分がしたかった表現はこんな感じです。
(RenderTextureのAnti-aliasingは「2 samples」にして少しぼかしています)

 

pixivFANBOXでもちょっとした技術とかを発信していきたいと考えているので、もしご興味あればフォローお願いします。(当分は全て無料記事です)

ゆーじ|pixivFANBOX
ドット絵謎解きアドベンチャーゲーム『ボクノシメイ』を開発しながら、小さなゲームも並行して作ったりしています。---App/GameDeveloperiOS/Androidアプリを中心に個人でゲーム開発をしています。これまで25本以上のゲームをリリースし、受賞やストアフィーチャーも経験させていただきました。---▽Twi...

コメント