ガンズターン 公式サイト

楽しいことに、まじめです。 ——ガンズターンアプリ研究所公式サイト

Unity備忘録 #3 複数のカメラを使い分ける!

Pocket

0. 宇宙が好きな人に悪い人はいない(と思う)

お疲れ様です。ガンズターンのRyosukeです。
昨日(8/21)は、ほぼ一日甥っ子と楽しく遊んだので、あんまり進捗ありませんでした。
でも楽しかったのでまったく後悔はないです。
(ゲームセンターのメダルゲームで、甥っ子のプールしていたメダルを200枚ほど減らしてしまったことは誰にも内緒です)

あと、姉と母から、少し早めの誕生日プレゼントをもらってしまいました……。

こんなわがままばかりの放蕩息子に気を使ってくれて、とても申し訳ないと恐縮。
(でも嬉しいというジレンマ)

かっこいい服を買ってくれたので、さっそくどんどん外に着ていこうと思います。
本当にありがとう! m(_ _)m

でも、さすがに一日なんにも進捗ないのはまずかろうと思いまして、これまでにやったことをメモ程度に残しておきます。

すでにこれまでの記事( [1][2] )でも触れてますが、次回作は宇宙SFものにしようと思ってます。

で、主人公(プレーヤ)は遠宇宙を旅する孤独な宇宙飛行士なわけですが、UIを宇宙船のコクピットっぽくしたら、なんか雰囲気出るんじゃないかなー、なんて考えているわけです。

ロボットSFとかでよくみる、HUDっぽいイメージ。
……なんですけど、このへん、凝り始めるといつまでたっても終わらなくなっちゃうので、あくまで「コクピットっぽい」だけですが……。

今回は、そんな「コクピットっぽい」UIを作るために、Unity上でのカメラの扱いとかを勉強してみたわけですが、本を読んでわかっていたつもりで、実はよくわかっていなかったことなどをメモ程度にまとめてみます。

(あ、最初に断っておきますが、通常通りUIを2Dでしか作らない場合は、Canvasの「Render Mode」の設定を単に「Screen Space – Overlay」にすればよいだけの話ですので、今回の記事はあまり役に立たないかもです。UIを3Dで作りたくて、なおかつ常に最前面に表示させたいという場合には役に立つかと思います)

いつも通り、世界中のどなたか一人のご参考になれば幸いです。

1. やりたかったこと

そもそもわたしがやりたかったのは以下のことです。

  • UIとその他のオブジェクトを描画するカメラを完全に分離して、3Dで作ったUIを常に一番手前に表示するようにしたい

これ、やり方知ってる人ならすぐにできちゃうぐらい簡単なことなんですが、自分みたいにまだUnity始めたばっかりだったりするとなかなか思う通りいかなくて、意外と時間がかかってしまいました。

ここで勉強した複数のカメラを設定してそれぞれで描画対象をわけるという手法は、覚えておくと色々と便利に使えると思ったので、こうして記事にしています。

2. そもそも1つのカメラで描画できないの?

できなくはないですが、「常にUIを一番手前に表示する」というのが難しい……というか、めんどくさくなります。

失敗例

UI(両サイドのパネル)より手前にオブジェクトが表示されちゃってます。

3Dオブジェクト間の距離関係によっては、こんな風に、本来奥に見えていてほしいオブジェクトが、UIよりも手前に見えてしまうことがあるので。

3Dオブジェクトの配置を工夫すればなんとかごまかせるような気もしますが、いちいちUIとカメラの距離を考えて、その間にオブジェクトが入らないように気をつけるのもなんだかめんどくさいです。

なのでわたしは、1つのカメラに執着するよりは、カメラを複数使って、それぞれで描画対象をわけることにしました。

3. カメラを分ける方法

ざっくり手順を書くと、以下の通りです。(いつも通り文章だけで不親切ですみません)

  1. シーンに「Camera」を新規追加し、わかりやすい名前にします。(今回、わたしはUI専用のカメラを作りたかったので「UI Camera」としました)
  2. カメラをわけたいオブジェクト用に、Layerを新規追加します。(メニューバー「Edit」→「Project Settings」→「Tags & Layers」と進んで、「User Layer」に適当な名前を追加する。)
    →今回、わたしはBuiltin Layerにすでに用意されている「UI」Layerを利用しました。
  3. カメラをわけたいオブジェクトを選択して「Inspector」ビューの右上「Layer」欄で「2.」の手順で追加したLayerを選ぶ。
    →もしカメラをわけたい対象が「Canvas」である時は、「Canvas」の「Render Mode」を「Screen Space – Camera」にするとよいかと。
  4. 「Main Camera」の「Inspector」ビューにおいて「Clear Flags」を「Skybox」または「Depth Only」にして、「Depth」を「-2」にする。
  5. 同じく「Main Camera」「Inspector」ビューの「Camera」→「Culling Mask」から「2.」で追加したLayerのチェックを外す。(これでメインカメラに、カメラをわけたいオブジェクトが映らなくなります)
  6. 「1.」で追加したカメラを選択して、「Inspector」ビューの「Clear Flags」を「Depth Only」にして、「Depth」を「-1」にする。
  7. 同じく「1.」で追加したカメラの「Inspector」ビューの「Camera」→「Culling Mask」において「2.」で追加したLayer以外のチェックを全て外す。(一度「Nothing」を選んでから、対象のレイヤーだけ選ぶと楽です)

とりあえず、これでカメラを2つにわけることができ、かつ、常にメインカメラよりも新たに追加したカメラのほうが手前に表示されるようになったと思います。

4. うだうだ書かずに要点まとめると

カメラをわけたいときは、以下の4点に留意すると設定しやすいと思います。

  • わけたい数だけ、Layerを準備する。
  • カメラの「Clear Flags」を適切な設定にする。
    →重ね合わせて表示させたいカメラは「Depth Only」
    →それ以外の時は「Skybox」か「Solid Color」
  • カメラの「Culling Mask」を適切な設定にする。
    →カメラの描画対象以外の「Layer」のチェックを外す。
  • カメラの「Depth」を適切な設定にする。
    →描画の優先度が高い(手前に表示したい)カメラの方を大きなDepthに設定する。

あ、あと、些細なことですが、あとから追加したカメラに設定されている「Audio Listner」コンポーネントは、そのままにしておくと実行時に大量のWarningを吐き出すのでチェックを外しておくとよいかと思います。

5. 「Clear Flags」の各設定値について

「Clear Flags」の各設定のなんとなくの意味は以下の通りです。(正しい説明はコチラをどうぞ(公式マニュアル))

  • 「Skybox」:
    背景にSkyboxを表示させる。一番奥のオブジェクトを表示させるカメラに設定するのがよいと思います。
  • 「Solid Color」:
    背景を指定した一色(カメラの「Background Color」)で塗りつぶす。上記「Skybox」の設定されているカメラと競合した時は「Depth」が大きいほうが優先的に表示されるみたいです。
  • 「Depth Only」:
    この記事の肝となる設定です。これが設定されたカメラは、「Depth」が自分より小さなカメラの描画が全て終わった後に、その画像の上に上書きするように自分の描画対象を描画します。つまり、3D空間上の位置関係(深さ)を無視して、単純にカメラの「Depth」の値だけで描画順をコントロールできます。カメラをレイヤー的に重ね合わせて表示させたい時に重宝します。
  • 「Don’t Clear」:
    自分が描画するより前のフレームをクリアせずに、そのまま自分を描画します。(ただしこの設定がされていても、他のカメラで「Don’t Clear」以外の設定がされていたらそちらによりフレームはクリアされてしまいます)「Depth」の値に関係なく、3D空間上の位置関係によりオブジェクトの描画順が決まるみたいです。

6. というわけで、いい感じに設定できるようになりました

成功例

意図した通り、UIが一番手前に表示されるようになりました。

こんな感じで、見事にオブジェクトとカメラの位置関係に関係なく、常にUIが最前面に表示されるようになりました。

でめたし、でめたし。

あとは、もっといい感じに「UI」Layerにボタンとかテキストとか追加していけば、コクピットっぽくなるんじゃいないでしょうか。(希望的観測)

ちなみにシーンに存在する全てのカメラの「Clear Flags」を「Depth Only」にしちゃうと、Skyboxが表示されなくなるため、背景が真っ黒になっちゃいます。

そこでわたしは、Skybox専用にカメラをもう一つ追加しており、そいつの「Clear Flags」を「Skybox」に設定してます。(当然「Skybox」専用カメラに他のオブジェクトが映り込むとおかしな見栄えになるため、同時に「Culling Mask」を「Nothing」に設定してます)

こうしてSkybox専用カメラとメインカメラをわけておくと、Skyboxだけ回転させたりすることも簡単にできちゃいます。Unityすげー。

そんな感じで、複数のカメラを使いこなし、その「描画順」と「描画対象」をカンペキにコントロールできるようになると、できることの幅が大きく広がると感じました。

わたし、まだUnity始めて2週間程度の若輩者なので、今回自分で手を動かしてみてとてもいい勉強になりました。
事前に本で読んでわかってたつもりだったのに、やっぱり実際に手を動かすのと「知ってるつもり」のままでいることの間には大きな差がありますね。

というわけで、今回の記事はこの辺でお別れ。

次回は、Http通信を実装してみた件についてでも書いてみようかしらん。
(といってもとんでもなく簡単にできたので、書くことほとんどないんですけど)

また近いうち、更新します。

最後までお読みくださってありがとうございます!
ガンズターンのRyosukeでした! m(_ _)m

Pocket

コメント

  • 非常に勉強になりました。ありがとうございます。
    今後も記事を書いていただけると嬉しいです!

  • > ricebag 様
    コメントありがとうございます! & 承認遅くなりすみません〜
    すごくうれしいです!
    今後も、ちょっとずつまた記事の掲載再開しようと思いますので、何卒長い目で見てやってください。
    よろしくお願い致します〜

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

トラックバックURL: http://gunsturn.com/2015/08/22/studying_unity_003/trackback/