テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】新しい物理演算、Unity Physicsについて

f:id:tsubaki_t1:20190420231232g:plain

Unity Physicsについて紹介します。

Unity Physicsとは?

Unity Physicsは、ECS上で物理演算を動かす為の追加機能です。この物理演算は過去Unityが使用してきた実績と安心のPhysXではなく、完全に新しくC#で作り直した物理演算になります。

Physicsの役割としては下の二通り。

  • 空間を探索して衝突等を探索する(接触判定、線形判定)
  • オブジェクトを実際に動かす(重力、バウンド、摩擦等)

f:id:tsubaki_t1:20190420215138j:plain

Unity Physicsはステートやキャッシュを行わず、複雑な衝突計算に対応しない代わりに軽量です。

また直前の状況に惑わされずその場その場で計算を行うという関係上、ネットワークといった事前状況がバラバラのゲームに向いていると言えるかもしれません。特にゲームでColliderを使用しているけど当たり判定しか使用していないといったケースでは、コチラのほうが良いと言えるのかもしれません。

従来のようなステート有りの物理演算向けとして、内部挙動をUnity PhysicsとHavok Pluginで切り替える事が出来るみたいです。 Havok Pluginでは複雑な状態を管理するのに向いているとの事。まだHavok Pluginはまだ公開されていません。

f:id:tsubaki_t1:20190420220552j:plain

なお現行のPhysXベースのColliderとUnity PhysicsのColliderは接触しません。Unity Physicsを使用する場合は他の全てのColliderをUnity Physics向けに変換する必要が出ます。

事前準備

導入環境はこちら

  • Unity 2019.1f2
  • Unity Physics preview1 0.0.2
  • Hybrid Renderer preview10 0.0.1

f:id:tsubaki_t1:20190420221316j:plain

Hybrid Rendererは実際には無くても良いのですが、描画関連を記述するのが面倒くさいので、Hybrid Rendererパッケージを導入します。*1

とりあえずシーンを用意

まずは、Roll a Ballよろしく板と玉を用意して、玉にRigidbodyを設定します。

再生すると下のように玉が坂を転がります。まだPhysXを使用している状態です。

f:id:tsubaki_t1:20190420222657g:plain

Unity Physicsに移行

Unity Physicsに移行します。

  • SphererにConvert To Entityを追加します。
  • PlaneにConvert To Entityを追加します。

これでSphereとPlaneオブジェクトは GameObjectからECSベースのUnity Physicsに変換 されます。

f:id:tsubaki_t1:20190420222954j:plain

f:id:tsubaki_t1:20190420223148j:plain

変換後は下のように、幾つかのComponentDataに変換されています。Entityを操作する場合はRigidbodyではなく下のコンポーネントを云々する必要がある点に注意してください。

f:id:tsubaki_t1:20190420225154j:plain

また動的にオブジェクトを増やす場合は下の記事を参考に。

tsubakit1.hateblo.jp

ステージのような大量の当たり判定のある物を一気にロード

Convert To Entityを使うのは悪くないのですが、これだと実行時に下のようなフローが入って勿体無い気もします。

  1. シーンをロード
  2. GameObjectをデシリアライズ
  3. Componentをデシリアライズ
  4. ComponentDataを生成
  5. GameObjectの破棄
  6. Convert To Entityの数だけ繰り返す

なのでサブシーンとして一気にデシリアライズしてしまいます。

  • 「とりあえずシーンを用意」の状態からスタート
  • SphererとPlaneを選択して右クリック
  • New SubScene from Selectionを選択
  • SubSceneコンポーネントのCloseを押す

これでステージ上のGameObjectがEntityに変換され、デシリアライズをほぼ挟まずにロード出来るようになります。

f:id:tsubaki_t1:20190420224852g:plain

新しく増えた設定を使いたい

Unity PhysicsはSubSceneやConvertToEntityでGameObjectのRigidbodyから変換するフローが用意されていますが、独自のコンポーネントも用意されています。

まず○○Collider系は、全てPhysicsShapeに統合されています。ねんがんの形状「Plane」も追加されているので、割と良いです

f:id:tsubaki_t1:20190420225530p:plain

Rigidbodyは`PhysicsBodyになります。

f:id:tsubaki_t1:20190420230215j:plain

パフォーマンス

PhysXと比べてどう?というのは機能の方向性が違うのでフェアな比較方法が思いつかなくてアレですが、非常に分かりやすい注意点として「エディターで動かすと遅い」というのがあります。

DOTS系は総じてそうなのですが、このUnity Physicsも同じくエディターで動かすと非常に遅く、IL2CPPでビルドすると化けます。 また実行直後(というかBurstのコンパイルが完了していない間*2)は更に遅いです。

コード制御関係

次で。

関連

Unity Physicsについての説明。意外とエグいと思ったのは自分だけではないと思いたい

www.youtube.com

紹介の公式ブログ

blogs.unity3d.com

nakamura001.hatenablog.com

*1:壊れてると思ったら古いAPIだった

*2:Burstはエディターで実行時に非同期でコードをコンパイルする。何故かキャッシュしてくれない

【Unity】Denoiseを使用してライトマップのベイク時間を劇的に抑える

Unity 2019.1で追加されたDenoiseを使ってみます

Denoiseでライトマップのノイズを除去

Progressive Lightmapperはレイトレースベースのライトマッパーです。そのサンプリング数が高い場合は非常に正しくライトマップがベイクされるのですが、非常に時間がかかります。一方、サンプリング数を減らす事でベイクの時間は大幅に向上しますが、ライトマップはノイズだらけになります。

時間が無限にあるならばサンプル数は多い方が良いですが、実際にはある程度のバランスを取る必要があります。

タイプ 効果
サンプル数が多い ベイクに時間がかかるが、ノイズは少なく正しく表示される
サンプル数が少ない ベイク時間は短いが、ノイズが表示される

f:id:tsubaki_t1:20190416225721j:plain

f:id:tsubaki_t1:20190416225753j:plain

以前はこの問題を、ノイズにフィルターをかけることでボカしていました。これはある程度の効果がありますが、やはりサンプル数が非常に低い場合は見た目が悪くなります。

f:id:tsubaki_t1:20190416230839j:plain

Unity 2019.1ではさらにノイズ除去というテクノロジーを追加することで、より少ないサンプリングでも綺麗に表示出来るようになったという感じみたいです。

下のライトマップは、サンプル数は最低でベイク時間が殆ど無いにも関わらず、それなりに綺麗に表示されています。勿論、よく見ると違和感のある部分はあるので使うかどうかは相談となるでしょうが、それでもサンプル数を減らすという選択肢は取りやすくなりそうです。

f:id:tsubaki_t1:20190416225732j:plain

Optix AI Denoiser

Optix AI DenoiserはNvidia機械学習ベースのノイズ除去システムみたいです。論文はコチラ

動作のためにNvidiaGPUを積んだWindowsのマシンが必要です。

developer.nvidia.com

使ってみる

実際に使ってみます。…といっても、Unity 2019.1では特に何もしなくても使えるならDenoiserが有効になります。

例えば Window > Renderer > LightmapDirect SampleIndirect SamplesEnvironment Sampleの数を劇的に下げてベイクしてみます。

項目 変更前 変更後
Direct Samples 32 1
Indirect Samples 512 8
Environment Samples 256 8

これでベイク時間が超短縮されます。

f:id:tsubaki_t1:20190416231959j:plain

Denoiserの有効・無効は、現在はFilterの項目に含まれます。初期設定では Autoで有効になっていますが、無効にしたい等の場合はFilterの設定を Advanceに変更すれば設定が可能になります。

f:id:tsubaki_t1:20190416232324j:plain

なおUnity 2019.1ではProgressive LightmapperのCPUのみで使用可能、2019.2からGPUにも対応するっぽいです。

感想

ライトマップのベイクに40分とか1時間とかかかっていたのが、本当に5秒とか30秒レベルで終わる割にソレナリに綺麗なので、非常に楽しいです。

とりあえずUnity 2019.1からはライトマップを焼く時にはSampleを減らす系の作業が入りそうな(…プロジェクト生成時に初期設定を手前に作らせろという意見も無きにしもあらず。何故かLightmapの設定はPreset使えないんですよね…)

関連

ライトマップをGPUで焼こうぜって手法。事前準備はありますが焼き始めるとかなり早いです

tsubakit1.hateblo.jp

Preset

tsubakit1.hateblo.jp

2019.1リリースノート

blogs.unity3d.com

【Unity】LWRPで、壁で遮られて見えないキャラクターをシルエット表示するのが超簡単にできた

f:id:tsubaki_t1:20190415213647j:plain

壁で遮られて場所が分からないキャラクターのシルエットを表示するアプローチを、LWRPでノーコーディングで実現出来たので紹介します。

壁に隠れてキャラクターが見えない問題

今回Survival Shooterのステージだけを差し替えてみる的なのを試した所、ステージ手前のオブジェクトがキャラクターを隠してしまい、何処に敵がいるのかを見つけられなくなりました。お陰で理不尽にゲームの難易度が上がり、思ったほど面白くなくなるといった事がありました。

f:id:tsubaki_t1:20190415213803j:plain

このカメラ問題の回答は色々と模索されています。例えば手前の壁を透明にする。他にもカメラの位置を上に持っていく(Cinemachine の Clear Shot)、向きは自由に変えられるので見えなくなるのは自分のせい等。今回はLWRPで面白い回避方法がGDCで紹介されていたので、それを試してみます。

Custom Forward Renderでシルエットを描画してみる

LWRP 5.7から、 Custom Forward Render を使用出来るようになりました。これで特定のレイヤー(or 描画タイプ・シェーダーパス)に所属するモデルの描画をオーバーライドしたり、描画するタイミングを変更したり複数回描画するといった事が実現出来るみたいです。

今回はソレを利用して、シーン上に表示されているプレイヤーと敵キャラクターのシルエット表示をやってみます。

f:id:tsubaki_t1:20190415214846g:plain

今回やる理屈は、下のような内容です。

  • Playerのレイヤーに所属するオブジェクトの、壁より奥(塗るピクセルのZ値がZバッファより大きい)の部分を、マテリアルをオーバーライドして塗る
  • Playerのレイヤーに所属するオブジェクトの、壁より手前(塗るピクセルのZ値がZバッファより小さい)の部分を、普通に描画する

f:id:tsubaki_t1:20190416011400g:plain

手順1:Custom Forward Rendeのセットアップ

最初にCustom Forward Rendeをセットアップします。

  1. Assets -> Create -> Rendering -> Lightweight Render Pipeline -> Forward Renderで、Forward Render Assetを作成
  2. LWRP AssetのGeneral -> Renderer TypeCustomに変更
  3. LWRP AssetのGeneral -> Dataに、先ほど作成したForward Render Assetを設定

f:id:tsubaki_t1:20190415221348j:plain

f:id:tsubaki_t1:20190415221358j:plain

手順2:Characterレイヤーに所属するモデルが壁の裏に回った時にシルエットを表示する

f:id:tsubaki_t1:20190415222613j:plain

上のように、キャラクターのシルエットを表示します。

  1. Forward Render AssetRender Features+ボタンを押しRender Objectを選択
  2. Filters -> Layer MaskPlayerを選択
  3. OverridesMaterialをシルエット表示用のマテリアルに変更
  4. OverridesDepthにチェックを入れ、Depth TestGreater(大きい)に変更

これで、塗るピクセルより手前にZ値が書かれている場合(モデルがある場合)、Overridesで指定したマテリアルで描画されます。

f:id:tsubaki_t1:20190416233550g:plain

f:id:tsubaki_t1:20190415222923j:plain

ただし、今の設定だと「Playerが遮蔽した物もシルエットとして表示」されてしまっています。例えば下の画像のように、壁からのシルエットだけでなく銃のシルエット、そして他のPlayerからのシルエットも表示されてしまっていて、余り良くないです。

f:id:tsubaki_t1:20190415223544j:plain

手順3:シルエット描画後にキャラクターを表示する

シルエットの描画後にキャラクターを表示するように変更します。

まず、Forward Render Assetの設定を変更して「Characterのレイヤーが設定されているモデルを、標準では描画しない」ようにします。 下の設定を行うと、Forward Render Assetで描画した分のみ表示されるようになります。

  1. Forward Render AssetDefault Layer MaskからCharacterを抜く

f:id:tsubaki_t1:20190415224029j:plain

次にシルエットを描画した後に明示的にCharacterレイヤーのモデルを表示します。

  1. Forward Render AssetRender Features+ボタンを押しRender Objectを選択
  2. Filters -> Layer MaskPlayerを選択

これで、ステンシル描画後にキャラクターが描画されるので、キャラクターが期待通りに表示されます。ついでにキャラクター同士が被った場合もシルエットになりません。

f:id:tsubaki_t1:20190415224826j:plain

なお、コレを応用するとプレイヤーと敵の色違いのシルエットとかも出せます。手順2で敵用のシルエットを描画して、手順3で描画する対象に敵も含めるだけ。

f:id:tsubaki_t1:20190415230013j:plain

特許

この割と海外のゲームでよく見る「壁の向こうのキャラクターのシルエットを表示する」表現は、特許が既に登録されています。ご利用は計画的に

j-platpat

関連

www.youtube.com

2Dで、シルエットではなく手前のステージを消すタイプ

tsubakit1.hateblo.jp

【Unity】新しいステルス系チュートリアル「John Lemon's Haunted Jaunt(ジョン・レモンのお化け屋敷)」

f:id:tsubaki_t1:20190413222752p:plain

ステルスゲーム系の新しいチュートリアル「John Lemon's Haunted Jaunt」が追加されました。

Unity Learnにて公開しています。

John Lemon's Haunted Jauntというゲーム

John Lemon's Haunted Jauntは、簡単に言えば脱出ゲームです。

ルールは非常に単純です。

  • ジョンはお化け屋敷にいる
  • お化け(動き回るタイプと、周辺を見るだけのタイプが居る)の視点を回避する
  • ゴールに到達するとゲームクリア
  • お化けに見つかるとゲームオーバー

Stealthであったような「アイテム回収」や「NavMeshで敵が追跡してくる」といったアクションはオミットされ、単純に巡回するお化けを回避するだけのゲームです。

f:id:tsubaki_t1:20190413223132j:plain

チュートリアル

チュートリアルは下のページから確認出来ます。英語なので、翻訳すると良いです。

learn.unity.com

f:id:tsubaki_t1:20190413223828j:plain

チュートリアルの内容は「セットアップ済みのプロジェクトをどうやって構築するか」といった内容で、オブジェクトの配置やセットアップといった項目、ステージ作成やゲーム構築といった諸々の部分が排除された、この手順通り作ったら動かせるといった内容でした。

Unityの操作方法を理解するといった点では分かりやすいかなという印象です。ただ、このチュートリアルを通しても自分のゲームは作れないかもしれません。

タイトル 内容
Setting up 3D Beginner Unityの概要です。UnityEditorのインターフェースについての説明が含まれます
The Player Character: Part 1 キャラクターの配置やアニメーションの設定、あとPrefabについてです
The Player Character: Part 2 キャラクターをスクリプトで動かす方法の紹介です
The Environment ステージのライティング設定とNavMeshの設定についてです
The Camera CinemachineとPostProcessingStackの説明です
Ending the Game ゲームクリア処理と、UIについての説明です
Enemies, Part 1: Static Observers 動かない敵(ガーゴイル)の作り方です。キャラクターの発見処理等とゲームオーバーが含まれます
Enemies, Part 2: Dynamic Observers 動き回る敵(ゴースト)の作り方です。NavmeshとWaypointによる移動についてです
Audio 音楽や歩行時の足音の再生方法、影響範囲等についての紹介です。
Build, Run, Distribute ゲームのビルド手順についての紹介です。

スクリーンショット

主人公のJohn君。意外と表情が豊かです。ToonShaderを使用しています。

John君はGeneric Avatarを使用している上にRootMotoinを使用した移動なので、モデルをサクッと差し替えられない点に注意です。

f:id:tsubaki_t1:20190413230619j:plain
主人公のJohn君。ビビリ

動き回るゴーストは、半透明のエッジのも表示シェーダーを使用しています。

f:id:tsubaki_t1:20190413230918j:plain
動き回るゴースト

ガーゴイル君、意外とモーションが可愛い。

f:id:tsubaki_t1:20190413230951j:plain
自宅警備員ガーゴイル

出口は明るく表示されています。

f:id:tsubaki_t1:20190413231046j:plain
出口

ステージはパーツごとに分割されており、並べ替えがやりやすくなっています。ただフロアは完全にメッシュを持ってきているので、フロアのレイアウトだけは変更出来ません。やるならProBuilderで作るとか色々する必要があります。

f:id:tsubaki_t1:20190413232111j:plain
ステージの並べ替え

f:id:tsubaki_t1:20190413232304j:plain
ステージのレイアウト

館の周辺はボリュームフォグっぽい表現で塗られています。ゲームからは見ることは出来ません。

f:id:tsubaki_t1:20190413232222j:plain
ボリュームフォグっぽい表現