スキップしてメイン コンテンツに移動

UE4 4.22 Preview 1 のリアルタイム・レイトレーシングを動かしてみた。

UE4 Study: Action, Interaction, and Imagination.

Unreal Engine 4 で、究極のゲーム試作の記録です。
マイルストーンとして、補題:追うものと追われるもの、に取り組むための準備です。
思考と作業の記録をざっと書いた草稿です。ご感想などあれば、どうぞ。

はじめに 

Game Engine のツボの探し方を書いておきます。
最近のEngine は、広大です。ドキュメントを読んでいても、ぼんやりとするだけで、なかなかアウトプットに手が動きません。

そこで、ゲームを作るのに必要な最小限の要素を探して、その実現方法を手を動かしながら、進めていくやり方を考えます。手を動かしながらアウトプットにつながる良いやり方です。これなら、Unreal Engine だけでなく、Cry Engine (今は、Lumberyard)、Unity、Frostbite、内製、どんな環境でも、やっていけますw

Game Engine で、3つの I を実現する方法を探す(How to)

  • Input
  • Interaction
  • Interface (UI)

Input (and Output)

ゲームを遊ぶPlayer からの入力を検出する方法、それに対してPlayer をどうやって動かすか
ゲームを遊ぶPlayer からの入力に対する出力の方法、画面にどうやって描画するか
入力は、デバイス(peripheral device)を想定しています。

Interaction

相互作用の方法、Player と ゲーム世界をどうやって相互作用させるか
具体的には、衝突検出と応答(Collision and Physics), メッセージ(Event Dispatch)
e.g., レベルとの相互作用、アイテムや武器との相互作用、AI との相互作用

Interface (User Interface / HUD)

ゲームを遊ぶPlayer への情報提示をどうやって実現するか(HUD)
ゲームを遊ぶPlayer からの入力とその応答をどうやって実現するか(UI)


UE4 で、それら3つのI を実現する方法を実際に作りながら、理解していきます。
今回は、Interaction の基礎を設計実装した記録です。

Coffee break - 3 つのI をどうやって決めたか

そもそも、ビデオゲームとはなんぞや、に回帰してみると、何が重要かがわかります。

ビデオゲームとは何か

1970年代から勃興してきた、Computer を使う、まだまだ新しい遊戯です。
https://en.wikipedia.org/wiki/Pong

入力機器は、喜びの棒(Joy-Stick), マウスとキーボード、など
出力機器は、テレビ、ビデオ、ディスプレイ、スピーカー、など
Computer が、ゲームのプログラムを実行して、プレイヤーは、入力と出力のフィードバックを楽しみます。

Player - Input Devices - Computer - Output Devices - Player

という正負の feedback loop 構造で、Player は、Output に応じて、Input を変えて、五感を使って、その変化を楽しみます。これは、多変量の非線形システムとも解釈できますね。
つまり、Game loop = Interaction なわけです。(強引ですw)

Interaction の設計

閑話休題。Game loop を構築するために必要な Interaction の項目を実装します。
・UI / HUD (この記事では詳細は省略します。作り方は、参考文献 [6] をどうぞ)
・Interaction

今回は、Interaction の基礎を設計実装しました。
UE4 は、Actor がInteraction の基本単位です。
まずはItem を実装しました。
Item とは、Player (AI 含む)が触って、Player の状態を物理的に、あるいは精神的に変化させるものです。Item には、何回も使えるものと消耗するものがあります。

構造(Class)

InteractingActor - ItemActor - ConsumableItemActor - Apple

実際に in-game で使うクラスは、Class Blueprint で実現します。
Blueprint のクラスは、C++ の基底クラスを継承して実現します。
具体的には、ConsumableItemActor を継承して、Class Blueprint で、具象クラス Apple を実現しました。

図 Interaction クラス図

家庭用ゲーム機器での Real-Time Game 実装では、クラスの継承および仮想関数(virtual functions)をできるだけ使わないのが望ましいです。理由は、速度およびメモリです。
そのため、クラスではなく、列挙型で型を宣言する、などして工夫します。

しかしながら、動くもの、動かないものなど、3D 空間上のあらゆるものと相互作用できる設計にしたい場合、プロトタイプ型言語、Component Based Architecture が求められます。詳細は、参考文献 [5]をどうぞ。

今後、家庭用ゲーム機器の性能が向上していけば、実現できると思います。
今回は、次世代ゲーム機器を夢見て、理想的な構造にしましたw
(ハイエンドをやるための布石です。)

Coffee break - Blueprint を使う理由

ゲームの試作では、仕様がばりばり激しく変化します。そのため、クラスを変更して、結果がすぐ確認できる、スクリプトが適しています。UE4 では、スクリプトに相当するのが、Blueprint です。本音は、Gaffer のような、Visual Python が良いですw

振る舞い

InteractingActor は、Pawn (目に見えて触れる Geometry, Mesh を持つ) と相互作用します。
相互作用のインターフェイス
virtual void InteractingActor::Interact(APawn* InteractedPawn);

Pawn クラスを引数にとるのは、Player が3D 空間の Level で必要な情報を保持するのが、Character クラスであり、Character クラスの基底が、Pawn クラスだからです。
UE4 Gameplay Framework の都合ですw

具象クラスで、相互作用の振る舞いを実装しました。
virtual void ConsumableItemActor::Interact(APawn* InteractedPawn) override;

Level で Player (AI) が、相互作用できるアクタ (InteractingActor) を探す方法

PlayerCharacter クラス(ACharacter クラスから派生)で、毎フレーム実行する更新関数 Tick() 内で、Ray Casting して、近傍の相互作用できるアクタ(InteractingActor から派生したクラスのインスタンス)を探します。
今回は、最近傍のみとしました。発展は、空間分割です。
具体的には、下記のようなコードにしました。

void APlayerCharacter::InteractImpl(
 const FVector& viewLocation, 
 const FRotator& viewRotation) {
 // 視界内で、相互作用できるアクタを探します
 AInteractingActor* FoundInteractingActor = nullptr;
 if(FindInteractingActorInView(&FoundInteractingActor, viewLocation, viewRotation)) {
  // 相互作用アクタの種類に応じて、振る舞いが決まります
  FoundInteractingActor->Interact(this);
 }
}

スクリーンショット




図 今回の試作。Player (AI) が赤の球体(Apple とみなす)と相互作用するまで
緑の軌跡に沿って、Player は移動します。

次回は、りんごの振る舞いの多面体を考えて実装してみます。
今回は、暗黙のうちに食べるだけでしたが、投げる、焼く、育てるなどいろいろな作用が考えられます。

その他、Player が持つ銃、AI とのInteraction を設計実装してみます。

参考文献

[1] Gameplay Framework
https://docs.unrealengine.com/latest/INT/Gameplay/Framework/index.html

[2] Entry Level Guide to UE4 C++
https://wiki.unrealengine.com/Entry_Level_Guide_to_UE4_C%2B%2B

[3] Unreal Engine 4 Programming API Fundamentals
http://www.gamasutra.com/blogs/DanielAdamitskiy/20150112/233926/Unreal_Engine_4_Programming_API_Fundamentals.php

[4] りんご
https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%B3%E3%82%B4

[5] A Dynamic Component Architecture for High Performance Gameplay
http://www.insomniacgames.com/a-dynamic-component-architecture-for-high-performance-gameplay/

[6] User Interface With UMG
https://docs.unrealengine.com/latest/INT/Programming/Tutorials/UMG/index.html

コメント

このブログの人気の投稿

Houdini で2D 平面の地図から3D ポリゴンの街を生成する

Houdini, Houdini Game Development Toolset, Open Street Map (OSM) を使って、現実の地図から、街の建物を生成してみました。ノードベースは、生成変換の過程がわかるのが良いですね。 図 2D平面の地図(OSM) から、建物のみを3D ポリゴンに変換した結果 図 Open Street Map 2D 平面の地図 2D平面の地図(OSM) から建物の領域だけを抽出して、ランダムに適当な高さを与えて、3Dポリゴンに変換しています。地図に対応した等高情報(いわゆる Height Map)があれば、よりリアルな街並みになるでしょう。地上から地下までを階層的に生成するなど。 味噌 建物だけを抽出する際、OSM 地図データのアノテーションを使い、建物以外を抽出して削除しています。幾何情報だけでなく、意味情報を使っています。 実践としては、そういうやりかた(戦術)は、筋が良いと思います。とはいえ、地図にアノテーションが存在しない状況もあるので、幾何情報と現実の何らかの情報から3D ポリゴン生成する頑健な手法を考えておきたいところです。 課題 3D ポリゴン生成時の法線の向き 現行は、入力情報が二次元しかないので、3D ポリゴン生成時に、頂点法線が反転してしまう領域があり、そのような領域を抽出して、法線を反転して強制的に修正しています。研究的な視点だと、その等高情報を画像から推定して生成する、のは面白いと思います。 3Dポリゴン化した建物へのテクスチャマッピング(UV 座標) 3D ポリゴン化した建物の用途は、レベルデザインでのグレーボクシングと構造の把握程度までとしておきます。グラフィクスも考慮する最終レベルでは、事前にテクスチャマッピングした High Level of Detail の建物に置き換えます。 道路など建物以外のポリゴン化 建物は凸形状なので、ポリゴンの押し出し(Extrude)で容易に3D 化できました。 道路は、曲線もあります。碁盤の目である京都の街並みになら、やりやすいかも(笑) 階層化 地上から地下までをレイヤー化して、街をプロシージャル生成します。 よりリアルで自然な街並みを生成するには 長期の時間経過、自然現象

Falcor で遊ぶ。導入編。NVIDIA Real-Time Rendering Framework

はじめに NVIDIA が公開した  Falcor Real-Time Rendering Framework  で遊んでみました。 Denoising 1spp Path Tracing, Foveated Rendering など、技術研究プロジェクトで使われたフレームワークです。DirectX12 / Vulkan に対して薄い抽象化レイヤを提供しています。オープンソースで、実験的な機能をさくさくとRAD 実装するのに使えると思い、触ってみました。今回は、フレームワークのビルドとサンプルを起動するまでの、導入メモです。 図 HDR のテスト 特徴 物理ベースのシェーディングシステム DirectX12 と Vulkan の薄い抽象化レイヤ 現代的グラフィクス技術のモジュール化されたライブラリ OpenVR を使ったステレオレンダリング カメラ、光源、メッシュのパスアニメーション ビデオキャプチャ FBX, OBJ などを含む一般的な3D アセットファイルフォーマット対応 シーンエディタで各種オブジェクトのオーサリング可能 NVIDIA のGPU でなくても、動作します。今回は、Intel Iris Plus です。 Ray Tracing など、CUDA を使う機能は、そのままでは使えないかもしれません。 Radeon Ray か、Embree か、OpenCL に置き換える、というライフワークが生まれますw 今回の動作環境 Visual Studio 2015, Windows 10 SDK 10.0.15063.0 です。 Microsoft New Surface Pro Core-i7, 16GB RAM, Iris Plus です。 step 1. GitHub から ソースコード入手 https://github.com/NVIDIAGameWorks/Falcor step 2. Falcor とサンプルのビルド 2.1. README を参照します。 Visual Studio 2015, Windows 10 SDK 10.0.14393.795 こちらの環境は、10.0.15063.0 です。 各自の環境に合わせて、プロジェクトのSDK 設定を変更してく

いきなり!Ray Tracing on Houdini VEX 2

Ray を可視化してみました。 可視化 図 Pinhole Camera から、Teapot へのRay と Reflection Ray を VEX で可視化 解像度比較 図 左 32 texels (primitives), 右 256 texels (primitives) ネットワーク 図 Simple Ray Tracer Wrangle 出力先は、screen です。 シーンは、sceneGeometry です。 今回は、Utah Teapot のみです。 manyLights は、光源へのポインタです。 morishgieGI は、大域照明(実験)へのポインタです。 raytraceWrangle が、Ray Tracing を実行するOperator です。 VEX コードの格納先です。 Ray 可視化 VEX コード raytraceWrangle で、ray がシーン内のジオメトリと交差した際、 ray の点とプリミティブを生成しています。 追加削除が、簡単に動的にできるのは、VEX スクリプトの強みですね。 // ray を可視化する 点とプリミティブを生成 // geoself(): 出力先(screen) int newPt0 = addpoint(geoself(), rayOrigin); int newPt1 = addpoint(geoself(), hit); addprim(geoself(),"poly", newPt0, newPt1); // reflection ray を可視化する点とプリミティブを生成 vector r = reflect(rayDir, surfaceNormal); int newPt2 = addpoint(geoself(), hit + r); addprim(geoself(), "poly", newPt1, newPt2); 追記:addpoint() や addprim() の第一引数は、geometry handle です。 現在の geometry に出力する場合は、geoself() を使いましょう。 現在の geometr