Epic では、月に一度「エピック・フライデー」という日があります。その日は、ほとんどどんなことであっても、好きなことに取り組むことができます。数ヶ月前のこと、私は、とてもシンプルな「ケーブル コンポーネント」を作りました。これは、レベルの中でぶら下げることによって、生き生きとした感じを演出するためのもので、ロープの物理を利用します。他のゲームでは数年前から見かけるエフェクトですが、私は、UE4 のプラグインとして追加することがどのくらい簡単であるのか知りたかったのです!下の画像がその出来上がりです。
シミュレーション
現実的なケーブルのシミュレーションを実行するために、私は、数回触ったことがある「ベルレ インテグレーション」というテクニックを利用しました。これは、ゲーム開発では非常に有名であり、あらゆる種類の記事が出回っています。私が最初に思い浮かぶのは、Thomas Jakobsen 氏の記事です(http://graphics.cs.cmu.edu/nsp/course/15-869/2006/papers/jakobsen.htm)。
このテクニックの考え方は、その間に「距離拘束」をともなった一連のパーティクルとしてケーブルを表現するというものです。両端にあるパーティクルは「固定」されており、両端でつながれている物といっしょに動きます。中間部にあるパーティクルは、「フリー」の状態にあり、重力の影響をうけて落下します。各ステップで、パーティクルそれぞれの速度と位置を更新し、距離拘束を満たすように動かします。ケーブルの「剛性」は、ステップごとに、距離拘束を実施するためにイテレートする回数によって制御します。
ここでは数学の話には立ち入りませんが、もし UE4 のソースコードをお持ちでしたら、UCableComponent クラスで、VerletIntegrate および SolveDistanceConstraint 関数の内部にあるコードが約 60 行にすぎないことが分かると思います。
レンダリング
パーティクルの鎖が立派に出来上がり、飛び回るようになったので、レンダリングしなければなりません。この作業は、UE4 で新たな種類のジオメトリを作成する場合のよいテストケースとなりました。実際、極めて簡単に作成できることが分かりました。私は、ケーブルのためのレンダラの代理である新たな FCableSceneProxy クラスを作る必要がありました。各フレームで、シミュレーション (TickComponent 内部のメインスレッドで実行されます) からの新たなパーティクルの位置を、SendRenderDynamicData_Concurrent 関数を使ってプロキシに渡します。レンダリングのスレッドでは、インデックスと頂点のバッファをロックおよび更新することによって、「チューブ」メッシュを作ります。各頂点について、位置、テクスチャの UV、タンジェントベースの 3 個のベクターを計算しなければなりません。X はケーブルに平行であり、Z はケーブルに対して垂直 (法線)、Y は、X と Z に対して垂直です。
面の数、チューブの半径、およびケーブルに沿って UV をタイリングする回数のプロパティをこのコンポーネントにエクスポーズします。
アタッチメント
これで、ケーブルを表示していじることができるようになったので、物に取り付けてみようとしました。アンリアル・エンジン 4 には、すでに、任意の SceneComponent を何にでもアタッチできる機能があります。そこで私は、オフセットを用いて、「終端」のパーティクルを異なるコンポーネントにアタッチできるオプションを追加しました。ケーブルの最終的な詳細情報は、以下のようになりました。
さて、これでお終いです。Cable Actor をご自分のレベルに追加して (または、Cable Component を ブループリントに追加して)、試してみることができますよ。これは UE4 のための実に素敵な追加物になりましたが、追加したいものはまだまだあります。たとえば、
- ワールドとのコリジョンを追加する
- 力や爆発などへの反応
- シミュレーションをメインスレッドで実行せずにマルチスレッド化する
- 変化がない場合に毎フレーム、インデックスバッファが再作成されないようにする
みなさんはどうですか?どんなものを追加したいですか?Twitter の @EpicJamesG で私を探してみませんか?フォーラム! 私たちのツールやチュートリアルに対するみなさんの評価は、私たちにとってとても大切なものです。