[Unity] 雪に残る足跡表現とパーティクルを使った積雪表現

Pocket

前回の記事はアサシンクリード3の技術解説記事を元に、出来る範囲で見た目再現できそうなところを作ってみました。今回はディスプレイスメントマッピングを使って(前回も少し試してみましたが)足跡の表現、パーティクルを使った降雪の表現、パーティクル衝突判定を使った積雪の表現に挑戦していきます。

 

 

 

環境

Unity 5.0.0f4

 

地面の準備

今回使用するディスプレイスメントマッピングというのは頂点を動かしてデコボコを表現するので、綺麗に表現するとなるとそれなりの頂点数が必要になります。なのでShader側で頂点数を増やせる機能「テッセレーション」を使っていきます。(実行できる環境が狭まると思いますが)

何はともあれPlaneを作成。

snow2_plane

Unity公式のヘルプからテッセレーション機能付きのShaderのコードをコピーしてShaderを作成します。

作成したShaderを使うマテリアルを作成します。Shaderは作成したものをセット。サンプルそのままなのでCustom/Tessellation Sampleを選択。プレビュー画面で既に頂点が移動している!

snow2_material

Planeのマテリアルへ適応。テッセレーションが適応されて分割された。Unityってすごいなー、と関心。

snow2_set_material

Base(RGB)、Disp Textureはすべて単色のテクスチャーを用意してセットしておきます。Normalmapは使用しない。

snow2_material2

これで地面が準備完了。

 

パーティクルで降雪表現

とりあえずはパーティクルで降雪っぽく見えるようにしてみます。こちらの「その1 Unityのパーティクル「Shuriken」」を見ながら雪っぽくなるように調整しました。

調整箇所は

  • Start Speed
  • Max Particles
  • Emission/Rate
  • Shape/Shape(Box)
  • Collision(Check On)
  • Collision/Bounce
  • Collision/Lifetime Loss
  • Collision/Collision Quality

を画面を見ながら大体で入力。

snow2_particle

 

パーティクルの衝突判定

Collision Module(公式サイト)

MonoBehaviour.OnParticleCollision(GameObject)(公式サイト)

の2つを見ながらパーティクルの衝突判定を覚える。

パーティクルのCollision設定は下図の通り。World + Send Collision Message を変更。

snow2_particle_collision_setting

下記のスクリプトを地面のPlaneに追加して、パーティクルの衝突判定が取れるかチェック。

テスト実行してみて、コンソールに何か出力されればOK。

 

パーティクルの衝突判定からの積雪処理

まずはパーティクルが地面に当たった所の情報をスクリプトで取得します。先ほどのスクリプトに付け加えていきます。

実行するとパーティクルが当たった位置、向きなどが出力されます。

※このOnParticleCollisionですが、パーティクルの設定によってはStartメソッドより前に呼ばれることがあります。メンバー変数をStartメソッドで初期化している場合は、初期化前に呼ばれることがあることを前提にコードを書く必要があるかも。

 

次に積雪処理用のコードを追加します。積雪処理はディスプレイスメントマッピング用テクスチャーの値を増加することで表現します。

ヒット位置からテクスチャーUV値を取得し、その部分のテクスチャー値を増加させています。あまり積もっても嫌なので、最大値以上は増やさないようにしておきました。

実行するとちょっとだけ地面が上に変形します。

accumulateSnow

いまいち見難い。なのでShaderをコピーしてディスプレイメントテクスチャの値から色を付けるようにしました。

accumulateSnow2

ぽつぽつと何かが変化しているのが判りますが、目が痛い・・・。

大げさに雪が積もるようにしているので3分~5分で結構積もります。

snow2_add

 

足跡用の当たり判定

次は足跡用の処理を作ります。足跡を付ける処理のトリガーとして、足跡コライダーを準備します。サイズは10cmの可愛らしいサイズに。(サイズに合わせた足跡付けようかと思っていたのですが力尽きたのであまり関係なし。)

※画像ではRigidbodyのFreeze Positionにチェックを付いていませんが、すべてチェックONにしておく必要がある。

snow2_foot

地面は既にメッシュコライダーが付いているはずで、あとはOnCollisionEnterメソッドで足跡コライダーが来るまで待っていればよいです。

 

足跡の表現

足跡もディスプレイスメントマッピング用テクスチャーの値を変更することで表現します。少し面倒な処理になりそうな足の向き、大きさなどは考えないことにします。これもFootprintスクリプトに追加していきます。

エディタ上で足跡コライダー付のGameObjectを地面まで動かしてみて、関数が呼ばれれば成功。

 

キャラクターの動きに適応させる

まだUnityのエディタ上でしか効果を確認できないので十字キーで歩き回るキャラクターを用意し、それに合わせて足跡が付くようにしていきます。こちらの記事「第 1 回・Unity / Mecanimでユニティちゃんを歩かせる」を参考にユニティちゃんを動かせるようにします。アニメーションに関しては、ほぼ未勉強なので詳細は書けません。今後勉強予定。

動かせるようになったら、足跡コライダー付のGameObjectをユニティちゃんの足裏に付けます。

snow2_footcollider

地面にヒットするように少し下側にコライダーが出るようにしました。

歩かせると足跡付くよ。

snow2_footprint

最終的なソースコードはこちらになりました。

 

デモ

ついにUnity Web PlayerがChrome 42から動かなくなったようなので、WebGL版を出力したのですがいまいち動かせない・・・。

 

まとめ

CPUの処理(テクスチャー作成) → GPU転送(Texture.Apply) → GPUで描画(Shader)のサイクルを当たり判定発生ごと処理を行っていて現実的ではないですね。各当たり判定を取ったあとRayを飛ばしているのも負荷高そうですし。

ゲームで使う場合はGPU内で完結するような処理の流れを作るのが一般的なのかな?なんて思いました。

例えば、足跡なんかは足跡用3Dモデルを準備、足跡の位置にモデルを並べてあとはディスプレイスメントマップ生成用シェーダーでレンダリングすると専用テクスチャーが出来上がる(地面から上方向を見上げて、足までのDepthテクスチャーみたいなやつ)、みたいなね。GPUへの転送データ量が「テクスチャーデータ量 > 3Dモデルのデータ量」だと思うので。

想像ですよ、想像。

 

ユニティちゃんライセンス

ユニティちゃんライセンス

このコンテンツは、『ユニティちゃんライセンス』で提供されています

Pocket

希木小鳥

Diablo1でハクスラの世界に。今はPath of Exileをプレイ中。長くやっていてもNoob属性は常に付いている。そのくらい行き当たりばったり。オタクになれないゲーマー。

You may also like...