アセット触ってみたシリーズ:ゆがんだ世界の表現!「Curved World」

みなさんは定番ジャンルのカジュアルゲーム開発に挑戦したことはありますか?定番といえるゲームはいくつかありますが、その中でも「ランゲーム」はルールの明快さと比較的作りやすい構造から、ゲーム開発講座のチュートリアルでもよく利用されるテーマです。
定番ジャンルの場合は、プレイヤーの目を引くために特徴となる要素が必要です。似たようなゲームの中でも目立っていくために、攻めたデザインのイラストやモデリングで魅せていくのも一つの作戦ですが、技術的に面白い演出を加えるアプローチもアリでしょう。
今回は、球体のようにゆがんだ世界や、映画『インセプション』にように地面が内側へゆがんだ世界の表現を簡単に作ることができるアセット「Curved World」をご紹介します。/p>
モデルデータの「ゆがませ」を瞬時に実現、「Curved World」
Vacuum Shadersというチームが開発したこちらのアセットは、「カメラに映る物体を一定方向に湾曲させることができる」アセットです。早速サンプルデータを見てみましょう。
アセットをインポートした後でAssets/VacuumShaders/Curved World/Example Scenes/1. Classic Runner.scene を開きます。
このサンプルはローポリの車が道路の向こうからプレイヤーの方に向かって走ってくるランゲームになっています。(ちなみにこのサンプルデータはシンプルなランゲームの教材としても非常に分かりやすい作りです。)
サンプルゲームの初期設定では円筒状のステージの上を延々と走っていくような世界設定になっています。実際には分割された道路のパーツを奥から表示させて、カメラの手前側に来たところで消す…という手法で無限に続く道路を表現しています。
地形のゆがませ方は、シーンにある「Curved World Controller」スクリプトで変更できます。
X Axis Bend Sizeは縦方向のゆがみです。これがマイナスの値は球状の変形、プラスの場合は内側にゆがみます。
Y Axis Bend Sizeは横方向のゆがみを設定します。
本アセットはイメージエフェクトではなく、メッシュにゆがむ効果を与えるものです。シーン内の特定のシェーダーを利用したメッシュ全てにゆがみの効果を付与します。先ほどのスクリーンショットでも、道路だけでなく向かってくる車もゆがんでいることが分かると思います。
サンプルをモバイルで動作させてみる
シーンの中でゆがませ方を制御しているスクリプトはC#スクリプトではなく、DLLファイルで構成されています。アセットストア上では「モバイル対応」とありますので、サンプルシーンをAndroidでビルドしてみました。
Androidでも無事に動作しました!ミッドレンジSoC(Snapdragon 650)の端末で60FPSが安定して出ています。
FPSが出ている理由にはサンプル自体のデータが軽いという要因もありますが、PCのエディタ上で「Curved World」機能のオンオフを行ってみても、フレームレートに大きな変化は見られませんでした。処理速度に大きくインパクトを与えるアセットではないようです。
自作のモデルデータをゆがませてみる
それでは、ゼロからこのアセットを適用する手順にトライしてみましょう。まずは適当なモデルをシーン内に置きます。今回はテストとして「おでん」のポリゴンモデルを用意しました。(何故おでんなのかは後で判明します。)
(だれがどう見てもおでん)
まず新規GameObjectをヒエラルキー内に設置し、Component -> VacuumShaders -> Curved World -> ControllerからControllerコンポーネントをアタッチします。
Controllerは、Curved Worldを使う場合に必ずシーン中に常駐させるスクリプトです。この時点では、サンプルシーンのようにパラメーターを変更してみても特に何も起きません。ゆがませたいメッシュのマテリアルに、専用のシェーダーを設定する必要があります。
マテリアルを選択した状態でShaderのプルダウンメニューから VacuumShaders -> CUrved World -> Unlitを今回は選択します。
この状態でControllerのパラメーターを変更すると、モデルにゆがみが適用されます。ところが….。
お分かりいただけるでしょうか。おでんの具材から、棒のモデルが飛び出してしまっています。
「Curved World」には、テッセレーションのような ポリゴンを自動分割する機能はありません。 なめらかにゆがませたい場合はモデリングの時点でしっかり分割させておく必要があるでしょう。
棒のモデルは3分割しかしていなかったため、カクついてしまい飛びだしてしまったというわけです。モデリングツール側で棒のパーツの分割数を増加させてやることで、棒が具を突き抜けずなめらかな変形をさせることができます。
「Curved World」を使ってゆがませる効果を出したい場合は、モデルの分割数を上げて、変形が破たんしないように調整するとよいでしょう。
ゆがみに関する描画範囲の調整
本アセットは、カメラの範囲内入っているオブジェクトに対してゆがみ効果を付与するため、描画される範囲(view frustum、視錐台)の外にあるオブジェクトには適用されません。すなわちカメラとの位置関係によっては、本来はゆがみエフェクトが適用されて視野内に入るはずのオブジェクトが描画されない可能性があります。この問題に対して「Curved World」では2種類の解決方法を提示しています。
Eagle Eye
オブジェクトを描画するかしないかのカリング判定前にカメラのField of viewを上書きし、描画対象のオブジェクトを広くとるオプションです。カメラにアタッチして使います。
ヒエラルキーでカメラを選択した状態で、Component -> VacuumShaders -> Curved World -> Eagle Eye追加します。
この範囲を広げれば広げるほど描画範囲が広くなりますが、反面、処理が重くなります。
Mesh Bounds Corrector script
メッシュを持つオブジェクトに対してMesh Boundsを一時的に拡大し、カリング対象にされないよう設定するスクリプトです。こちらはMesh Rendererがアタッチされたゲームオブジェクトに追加します。Eagle Eyeと同様、Componentメニューから追加できます。
オブジェクトごとに設定できる反面、Mesh Boundsにかかわるほかの処理で不具合が出る可能性があるのと、対象のオブジェクトが多い場合は管理に工夫が必要そうです。
使用できるシェーダーの管理
ゆがみ効果を与えるためにはシェーダーを置き換える、というお話をしましたが、初期設定ではCurved Worldで使用できるシェーダーの種類はあまり多くありません。
このアセットは、あまり使用頻度の高くないシェーダーを.unitypackage形式で退避させており、必要に応じてインポートできる機構を備えています。
プロジェクトにシェーダーが多いとプラットフォーム切り替え時にコンパイルが走り、それに時間がかることがあります。このアセットはそのような事情を予想して作られているようです。
まとめ
画面をゆがませる効果なので、処理負荷や適用手順について一抹の不安があったのですが、「Curved World」は導入が非常に簡単で、使い手のこともよく考えられたアセットであるといえます。ランゲーム以外にも、アクションゲームや育てゲーなど、さまざまなジャンルで活用できそうです。あなたの作っているオリジナルの世界観に見た目のインパクトを加える「Curved World」、ぜひご検討ください。
この記事を書いた人
一條貴彰株式会社ヘッドハイ 代表取締役
ゲーム作家・Game DevRel。小規模ゲーム開発者がもっと活躍できる世の中作りを目指して、ゲーム開発ツール・サービス専門のDeveloper Relation事業を行っています。ゲーム作家としての代表作は『Back in 1995』(Steam)。