概要
開催日:2017/10/07
イベントサイト
Togetter まとめ
動画とかまとめ記事でてた
全体の感想
とにかく今年は人が多い!?
開場10分前ぐらいに行ったんだけど、既に100人以上。
去年より人は多いのでは?グッズも瞬殺。
立ち見の講演も多かった記憶。特にドラクエの講演は、もうなんか立つ場所すらないぐらい。
ゲーム業界の人間は当然多いけど、建築関係の業界や学生・インディーズで活動されている方も結構いたように感じた。
UE4 がゲームエンジンとして、本当に様々なシーンで使われるようになってきたことと、裾野が広がったことによってさらに盛り上がってきた様子がよく分かる会場風景だった。
見てきた講演
UE4の攻略方法を伝授!より効率よく楽しく学ぶための鉄則について
株式会社 Indie-us Games 代表 中村 さんもとい、alwei さんの講演。
去年の講演も聴いてとても参考になったので今回もこちらに。
今回は、技術的な内容という感じではなく、楽しみながら効率良く学ぶポイントを、関西の学校を中心に臨時講師もされていた中での経験も踏まえて発表されていた。
いかにして学生にモチベーションを維持しながら学んでもらえるのか、という話も良かったが、個人的には、特に話の後半、モチベーションをいかに維持するかに関しての話が、自分にとってもタイムリーでとても心に刺さる内容だった。
自分の場合、会社での業務で落ちてしまっていたモチベーションを、ぷちコンやってみたり、Qiita 書いてみたり、個人でも活動始めてみることでだいぶ調子がよくなってきた。それに、アウトプットを残しておくことで、モチベを維持するだけでなく、黙示録や不明瞭だった部分の再確認などにつながっていて、実は、自分へのリターンがかなり大きいということもよくわかる。そういえば、ジョン・ソンメズの「ソフトウェア開発者の人生マニュアル」にも同じようなことが書かれていたっけ。
これからも意識して楽しみながら学べるようにしていきたい。
個人的メモ
- 専門学校で教えること
- 最初から BP のような難しいことは教えない
- レベルデザインのみ。テンプレートのみでゲームを作らせる。
- 実際には BP が使えないからロジックが組めない
- 物理等を使ってうまくゲームにする学生がいた
- 考える力を身につける
- 実際には BP が使えないからロジックが組めない
- その後に簡単なロジックの BP を教える
- この組み合わせで動くゲームをいくつか
- アセットもどんどん自由に使わせる
- 最初にゲームを作らせることで、ゲームを作るのは楽しいということを体験をさせる。
- アーティスト志望 → 自分のモデルが動く、演出等も簡単 → ポートフォリオ捗る
- 企画志望 → 自分の企画ゲームを作る。楽しい → どんどん自分で作るように
- プログラマ志望には、DirectX等の基礎教える。その上でエンジンはモチベ材料。
- すべてが楽しいわけではない。なので、どうやってモチベを保つのか考える
- モチベーションドリブンラーニング
- モチベを高く維持した学習 → より楽しく効率よく学ぶことができる
- モチベを上げるための学習
- すごいサンプルを見まくる → 改造する
- UE4ランチャにあるやつ
- http://ue4resources.com
- 紹介されていたサンプルが置かれているサイト。知らなかった。
- 重力カスタムなどの面白ネタやProjectileの軌道表示などの使えるネタがある
- 上級者向け: Robo Recall Modkit
- すごい人がやってることを追う
- 人に教える
- 知識の再確認にもなる
- Web記事を書く
- 人に教えるだけでなく、自分の黙示録になる
- 誰かの役に立つ → モチベ
- コンテストやゲームジャムなどイベントに出る
- 失敗してもいいから楽しむこと
- デジゲー博・コミケなどに出す
- 手にとってもらえる、期限がある
- 学習の効率はモチベに直結
- まずは楽しいことする、失敗しても良い
- 失敗から学ぶ、多く重ねる
- すごいサンプルを見まくる → 改造する
Unreal Engineを使用した商用タイトルでのノンフォトリアルレンダリング(NPR)事例
ソレイユ株式会社、田中さんの講演。
NPR の実装に関して、N dot L などの基本的な話や、従来使われてきた手法に関しても丁寧に説明を入れつつ、今回の事例に関して解説されていた。
特に、光源計算を行なうために、(実際は 100 行程度とは言っていたが) 描画周りにエンジン改造が施されていた内容はとても深く濃い内容だった。
専用にシェーダモデルを追加し、独自の光源計算をするようにしたこと、ポストプロセスのよるアウトラインの問題に対して描画順を変更することによる対策など。
特に、ポストプロセスによるアウトライン描画に関しては、自分も以前に実装したことがあったが、これに比べると、本当に自分の実装はテキトーで中途半端で出来であったと深く反省した。時間が出来たら修正を加えてみたい。
また、照り返しによる疑似ライトといった細かな調整や、負荷軽減策として Custom ノードに全て移し替えるような荒業まで飛び出しており、ものすごい改良の努力と描画に対する意気込みを感じる素晴らしい講演だった。
個人的メモ
- マテリアルノード改造によるセルシェーディング
- 目的
- N dot L の結果をテクスチャにマッピング
- 影色を指定
- 影になりやすい、なりにくいをコントロールする
- 改造内容
- シェーディングモデルを追加(マテリアル関連のエンジンコード)
- ベースパスで新規シェーディングモデル情報の書き込み(ベースパスのシェーダコード)
- ライティングパスで独自の光源計算(ライティングパスのシェーダコード)
- マテリアルノード側で、ベースカラー、シャドウカラー、LUTのインデックス(LUTは横に N dot Lの結果マッピング、縦にパターンが選択できるようにしてある)
- NPRは一般的にフォワードのほうがやりやすいが、結果的には両方で実装が可能だった(変更点も少ない)
- 影色が指定できるというのは重要(ただ暗いだけになってしまう。色指定が入ることでアニメっぽさが増す)
- NPR の影の話
- 光源を遮ることによって生まれる影 → デプスシャドウは精度が悪い
- LightAttenuation バッファと N dot L の結果で暗い方を採用してテクスチャ参照
- のっぺりとした影色に対する対策
- 地面から照り返しを想定した疑似ライトを想定して乗算(カメラオフセット斜めしたからの方向)
- 間接光を弱めにブレンド
- アウトライン
- キャラと背景の境に輪郭線を出したい場合 → マテリアルで検出
- キャラと背景に違うシェーダモデル・その境界検出
- カスタムデプス・カスタムステンシルの使用
- ポストプロセスによるアウトライン
- キャラと背景でアルゴリズムを変える
- 法線以外にも複数のGBuffer の情報から生成する
- 距離によって、細く、薄くなる調整
- 特定の条件でから周囲のアウトラインカラーを変える
- 負荷対策で巨大なカスタムノード化(倍ぐらい早くなった)
- 目的
- マテリアルノード改造によるセルシェーディング
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
株式会社バイキング 瀬田さん、奥井さん、芹沢さん。
バイキング、マジシャンズデッドでの事例。以前、Material Management Deep Dive でもバイキングさんのお話を聞いていてとても参考になったので、今回も期待しての聴講。
開発当初、ブループリントのみで実装を進めていたが、途中でその限界に気づき、 C++ に置き換えをしていったという話。 あーこれは、なんとも親近感が湧く内容。
構造体ノードで頻繁にコピーが発生してしまう問題は、自分も気づかずによくやってしまいがち。
UE4 エディタ上のみで定義されたものを C++ に置き換えるというのも、非常に厄介。そのままでは、プロパティの設定情報が吹っ飛ぶし、C++ で新しくクラスや Enum を定義し直し → それに合わせて BP 側も修正 となるので、倍の作業をしてるような気分になる。
つらい。
「ブループリントは恋人、結婚するなら C++」 これは後世に残そう、そうしよう。
後半は、アニメーション関係。Skeletal を 1 つにしたという話でちょっと驚いた。全部 1 つでやるようなことまでは考えたことなかったけど、工夫次第でどうにかなるもんなんだなぁ。
でもこれは、特にマジシャンズデッドの場合だったからこそ、という気もする。例えば、RPG のような、色々な目的を持つキャラクターを複数制御する場合は、逆に全て 1 つに統一する方が大変だと思う。何でもかんでも 1 つにすれば幸せというわけではなく、目的が同じで AnimBP を使いまわしたい、そういう粒度でまとめるのが良い、と解釈した。
個人的メモ
- Bluerpint のみで起きた問題
- コンパイル時間ですごく待たされるようになった
- 非参照数が多い。増えるケース
- 変数で BP を指定
- Spawn Actor で BPを指定
- BP の継承
- ベースのBPが必ず被参照になる
- 3段階目の継承でも必ず1段階目のBPが被参照
- 非参照数が多い。増えるケース
- フレームレートでない
- 例えば ForEachLoop
- Pure を参照時に呼び出し + ArrayElement が呼ばれる度に呼び出し
- 構造体のBP上での受け渡しはメモリコピー
- C++ 参照渡しにすることで解決する
- 例えば ForEachLoop
- デバッグが大変
- スタックトレース追うの大変、Standalone 時でしかおきない不具合
- マージできなくて困る
- コンパイル時間ですごく待たされるようになった
- Native 化による苦労
- UPROPERTY をつけないと、GCの対象
- クラス・構造体が宣言する側でも UPROPERTY がついていないと GC対象
- 参照ツリーに注意
- nullptr によって簡単にエディタがハング
- BP の Enum, 構造体の問題。そう簡単に C++ 化できない
- BP作成ガイドラインを立てる
- デザイナとプログラマでBPをできるだけ分ける
- BPクラスはC++クラスを継承
- BPクラスを継承したBPクラスをなるべく作らない
- Blueprint は恋人、結婚するなら C++
- C++ で SpawnActor時に引数を渡す
- SpawnActorDeferred → 変数を更 → FinishSpawning
- モジュール分割
- ビルド時間短縮が狙える
- モジュール参照ルールを作った
- 上位のみへの一方通行
- 分けすぎると依存関係が複雑化、モジュール間移動が大変
- モジュール間移動 → ActiveClassRedirects (DefaultEngine.ini)
- クラス名変更にも使える
- プロジェクト運営
- SSD おすすめ、捗る
- Subversion, TortoiseSVN
- dll は Jenkinsで自動ビルドすることでコンフリクトを回避。
- プログラマはローカルでビルドするのでsvnでexclude指定
- アニメーション
- モデルが変わるとAnimGraph が共有できない
- 結論としてスケルトンを1つにする選択
- リターゲットの設定
- キャラ固有:Animation
- アニメーションで骨の位置を動かす:AnimationScale
- アニメーションで骨の位置を動かさない:Skeleton足が浮く・埋まる
- 骨構造の問題:Rootと腰の間に骨を追加してはいけない
- 膝から上・膝から下の比率が違うと足上げたときにズレる
- キャラ固有モーション
- リターゲットしなくていいモーション
- アセット毎に手動で設定
- 自動化プラグイン – アニメーションを一括インポート
- キャラ >> 性別共通 >> 共通
- アニメーションを使う時
- デフォルトの PlayAnimationは使わない
- ID を設定して再生できるようなものを自前で用意
- 骨階層変更する場合
- 共通モーションでも変えたい
- 小物持っていると不自然になる場合がある
- ブレンドで個別対応
- ステート、Action 単位でクラス
- BeginAction, EndAction
- AnimBP ステートマシンのメリット/デメリット
- 通信料が抑えられる
- キャラごとのカスタマイズが出来ない
- モンタージュ使いにくい同期はアニメーション単位
- SE、ヒット判定は可能な限り、AnimNortifyに仕込んでおく
- リザルトでキャラの指先をプレイヤーの手の動きに上書き
ドラゴンクエストXIへの道 ~The “L”oad To DragonQuestXI~
株式会社スクウェア・エニックス 紙山 さんのドラクエでのロード周りのお話。
立ち見、というか立ち見する場所もないくらい激混み。タッチぱなしのせいで、キーボード打てずメモが全然取れてなかった・・・。
冒頭、エンジン改造はできるだけしない、でもやっぱり手入れざるをえないというのは、どうしても起きてしまうので、やるならエンジンのバージョンをロックしてから、という話。
全く同意。
同意なんだけど、なかなかそういう決断ができないってこともあるのよね。
UE のバージョンアップによる機能改善はめざましいものがあって、今ある問題が次のバージョンで解決してるなんてケース結構あったりするしどうしても新しい機能や機能改善に目移りしてしてしまいがち。
エンジン改造が前提としてある場合には、こういうときこそプログラマーが主導権握って説得する必要があるんだろうな。
ロード時のストリーミングの問題とその解決までのアプローチ。加えて GC の話。全体的にエンジン内部の仕組みにフォーカスした濃い内容が多く、おいきれていなかった。
EDL ぐらいは以前聞いたことあったため具体的な中の仕組みを知る機会になったのはよかったが、プロファイラー以外のコマンド等は本当に聞き慣れないものが多かった。そのあたりちゃんとメモできてなったのが悔しい。
というか、正直にいってしまえば、自分はUEのロード周り(特に内部的な構造)に対する知識がそもそも乏しく、勉強不足だったことも大きかった。このあたりは、今後、カバーできるように努めたい。
そんな中でも、節々に印象づいたポイントもちらほら。
アセット同士の参照で芋づる式にロードが走るというのであれば、実装過程で結果的に不要になった参照とかは極力削除すべきだろうし、BeginPlay に処理を集中させないというのも最初からそれを意識した設計で作っていくことが重要だろう。
プログラマーでUE を使っているからには、もっと仕組みを把握していないといけないことがたくさんあるなと感じる。そんな講演だった。
個人的メモ
全然メモがとれてない・・・ので Togetter 等見ながら思い出しつつ・・・
- ゲームエンジンいじるのは原則禁止・・・だけど
- いじるのはバージョンロックしてから
- 出来上がってくるとレベルストリーミングの問題
- 16万アセット、アセット同士の参照で芋づる式にロード
- UE4.13でロック、ブランチ切った
- Event Driven Loader
- 昇順キャッシャー、HDDのシーク減らす
- [補足]
- EDLはUE4.15から標準で入っている。
- UE4.14は、以下の手順のようにエンジンビルドが必要。
- https://qiita.com/donbutsu17/items/ca8fbf19c1c43b3c465d
- 細かい単位でのパック
- HDDパフォーマンス高まるが、重複による容量の圧迫
- PS4では、fread 回数よりもシーク距離がネック
- UnrealPak上のファイルレイアウト。ゲーム起動オプションに -fileopenlo
- ロード時のカクツキ問題
- (当時) Epic内製でレベルストリーミングは使われていなかった
- PostLoad RegisterComponet BeginPlay などに重い処理、DumpHitchs で調べる。お手軽だが、1,2割しかわからない。
- stat startfile, stat stopfile 調べる
- こちらよりも、主にPS4開発ツールプロファイラ使った
- BeginPlay から遅延させる
- 別スレッドにする
- が、大概は無理、大抵の処理はメインスレッドからしか使えない
- 非同期読み込みはメインスレッドから
- 破棄する時も複数フレームに分散
- まだカクツキ → GC?
- 参照によってループが深くなる
- PERF_TRACK_DETAILED_ASYNC_STATS
- [後で調べた]
- ロードにかかった時間の計測をしてログに残す Define
- AsyncLoading.h に定義されていて、1 にするとロード時に以下の情報がログとしてはかれるようになる模様
- [後で調べた]
UE_LOG(LogStreaming, Display, TEXT("Detailed AddToWorld stats for '%s' - Total %6.2fms"), *Level->GetOutermost()->GetName(), TotalTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Move Actors : %6.2f ms"), MoveActorTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Shift Actors : %6.2f ms"), ShiftActorsTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Update Components : %6.2f ms"), UpdateComponentsTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Init BSP Phys : %6.2f ms"), InitBSPPhysTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Init Actor Phys : %6.2f ms"), InitActorPhysTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Init Actors : %6.2f ms"), InitActorTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Initialize : %6.2f ms"), RouteActorInitializeTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Cross Level Refs : %6.2f ms"), CrossLevelRefsTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Sort Actor List : %6.2f ms"), SortActorListTime * 1000 ); UE_LOG(LogStreaming, Display, TEXT("Perform Last Step : %6.2f ms"), SortActorListTime * 1000 );
- GC の問題 UObjectが多いと重い、UPROPERTYが多いほど重い。
- 検索対象外に逃がすコンフィグ設定を使用。デフォルトでfalse
- ConditionalBeginDestroy
- DumpBlueprint、UE4.17にはいってるらしい?コマンド
- マクロの中にマクロがあるような構造は重い
- マクロはただのコピー、関数に置き換える
- ナイトリービルド
- DDC共有は大丈夫・安全
参考:
レポートをブログに上げてくれている方のページ。思い出すのにとても参考になりました。
http://effect.hatenablog.com/entry/2017/10/08/163854
コメント