23.5K Views
November 08, 21
スライド概要
講演アーカイブ:
https://www.youtube.com/watch?v=KALS1WSakKk&list=PLr_Cbd4sUDTyMGAtfqRojwzFxkVXuU-_L&index=2
講演内容:
UE4を学びながら小規模チームでプロトタイプを制作する方法と、パブリッシャー協賛の元どのようにアーリーアクセスリリースまで至ったのか、私たちが得た経験と直面した問題についてご紹介します。いつか自分で個人ゲームを作りたいと思っている方も、既に個人でゲームを出したことがある方も、インディーゲームの開発に興味がある方はぜひご視聴ください。
講演者:
ラドニフ 由子 (Vallynne デザイナー)
ラドニフ イリヤ (Ubisoft Osaka株式会社 テクニカルデザイナー)
UNREAL FEST EXTREME 2021 WINTER公式サイト:
https://unrealengine.jp/unrealfest/extreme2021winter/
#uefest
Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/
少人数と低予算で賢く開発! 超野心的なインディーRPGの挑戦 By ラドニフ 由子/デザイナー/Vallynne ラドニフ イリヤ/テクニカルデザイナー/Ubisoft Osaka株式会社
自己紹介 ラドニフ 由子 本業はwebデザイナー。 ゲーム好きが高じて「Shores Unknown」という 個人制作ゲームの開発チームに参加し、イメージビジュアル制作 の他、Blenderを用いたキャラクターモデリングを担当する。 ゲーム業界は全くの未経験ながら、現在では設定や配置などとい ったプランナーの役割も担う。
自己紹介 ラドニフ イリヤ ゲームプランナー歴10年。 2016年にロシアから来日。 2017年に「Shores Unknown」という個人製作RPGの プロジェクトを立ち上げ、試行錯誤しながらUE4で開発する。 現在はUbisoft Osaka株式会社のテクニカルデザイナーを勤める。
「Shores Unknown」とは • • • • • • ローポリで描かれたターンベースの戦略RPG The Last Remnant, Baldur’s Gate, Planescape: Tormentにインスパイアされた プレイ時間 約20~30時間(ver0.8では約15時間まで) 英語の原文 単語 10万+ 2017年3月からプロトタイプ製作 2021年2月からSteam Early Accessへ
Vallynne: チーム構成 • 多国籍、多文化、全員インディーズ (個人事業) • 4つのタイムゾーン • 現在のコアチーム構成: レベルデザイン Anton ストーリー フリーランス(一時的契約) Yuiko George キャラクターデザイン Claudi Max 音楽 ゲームデザイン、 スクリプティング シナリオライター 2名 レベルデザイナー 2名 3DPropのモデリング 2名 2Dアーチスト 3名 3Dキャラクターデザイナー・アニメーター UIデザイナー 1名 QA 1名 3名
管理 • • • • • Google Docsがメイン(仕様もデータシートも) タスク管理:Asana チャット:Telegram + Discord コール:あまりしないが、Discord インディーズなのでできるだけ 無料ツールを選ぶが、必要な場合は 有料ツールのライセンスを購入
タイムライン 2017春 1人 • UE4(4.13)を学びながらバトルシステムを設計 • 3ProngGamingさんに感謝 (https://www.youtube.com/watch?v=aipoAphfAN8)
タイムライン 2017夏 2人 • レベルデザイナーの知人の協力を得て、Marketplaceから アセットを購入し、少しゲームっぽい状態へ • Synty StudiosのPolygonシリーズ
タイムライン 2017冬 3人 • 「ストーリーがあればもっと面白くなるんじゃないか?」 • シナリオライターの知人の協力を得て、「Project Shore」と いう1時間ぐらい遊べるpublic alphaを出す
タイムライン 2018 5人+ • Public alphaのおかげでpublisher会社と契約 • 全キャラクターをオリジナルデザインに変更 • 買ったアセットが無駄にならないように、テイストは揃える
C++とBlueprint • UE4を学び始めた当初Blueprintのみを使用していたため、 ロジックは90%BPで実装 • Parent classes、Data structuresなど、ゲームのコアに関わ るものは主にC++ • BPのstructも結構ある!
RPGのシステム 探索 戦闘 • • • • • • ダメージ・回復 アビリティー AI ストーリー 移動 アイテム ギミック キャラ育成 • • • 選択肢 カットシーン ロジックフラグ • • • 装備 ステータス レベル
キャラクター • バトル・ストーリーに様々なキャラクターが登場 • キャラクターは大きく2つの種類に分かれている 探索キャラクター Exploration AI Interaction with player (dialogues) Idle activities Cinematic logic 共通機能 Visuals Movement バトルキャラクター Battle AI Action logic Level up Combat logic (damage and healing)
キャラクターのアナトミー • Character=CharacterData + CharacterStatics • CharacterData – 動的であり、セーブデータに保存される(キャラクタ ーのレベル、習得したアビリティ、装備等) • CharacterStatics – 静的であるため、セーブデータに保存されない (キャラクターのモデル、色、声等) • CharacterDataはCharacterStaticのIDを含む • Unrealでは2つのDataTableとしてデータを保管
キャラクター作りを効率的に 1.Blender3Dでモデルを作って、パーツ に分ける 「Shores Unknown」では、各キャラクターはいくつかの パーツから作られている。 基本的にはいくつかの使いまわせる上半身、下半身、頭、ひ げ、髪の毛などのモデルを用意して、上手く組み合わせてい る。 使いまわし用のモデルを多く用意することで、個性的なNPC キャラクターの量産が可能となった。 ※主要キャラクターに関しては専用パーツを用意。特徴を持 たせることでNPCと差別化している。
キャラクター作りを効率的に 2.BlenderでAutoRigProとVoxel Heat Diffuse Skinningという2つのプラグインによりリギング+ スキニング 手動での調整が必要な場合もあるが、作業量は大幅に削減された。 AutoRigProのおかげで、数クリックでMannequinのskeletonに合うリグ が作成され、BlenderからUE4にエクスポートできるように。 AutoRigPro - https://blendermarket.com/products/auto-rig-pro Voxel Heat Diffuse Skinning https://www.blendermarket.com/products/voxel-heat-diffuseskinning AutoRigProについての詳細(日本語):https://okra.blog/archives/5789
キャラクター作りを効率的に 3.UE4でのパーツの細かい設定: PhysicsAsset、Cloth、LOD設定など キャラクターの見た目を自然にするため、服や長い 髪の毛などのなびく部分にはUE4のClothing機能を 用いている。 なびく部分のみ別パーツとして作成することで、 cloth weightsの設定も容易に。また、メッシュに頂 点が少ないとClothのパフォーマンスコストが減少す るので、パーツ作成時はその点にも留意した。 ClothingはLOD0にしか適用されないので、LODを使 うことによりClothingのコストを制限した。複数の メッシュに同じLOD設定を使うためにLODSettings のアセットを用意した。
キャラクター作りを効率的に 4.設定されたパーツをキャラクタ ーに組み合わせる CharacterGeneratorのBlueprintを用意した。 Editor Scriptingを使って、Blueprintだけで作れる もの(C++不要)。 パーツと色を設定し、任意の名前でCharacterStatic のDataTableにエクスポートできる。 全パーツがSkeletalMeshとして作られるので、 BaseMeshに他のパーツの動きを同期させるため MasterPoseComponentの機能を使用した。
キャラクター作りを効率的に 5.CharacterGeneratorでランダムな 組み合わせの作成も可能 作成したメッシュをグループ分けすることにより、 1クリックで新しいキャラクターが生み出せる。 作成後の調整も可能。変更はリアルタイムで表示される。 また、既にDataTableに保管されているCharacterStatic を読み出す→調整する→保存するというパターンもできる。
おすすめのPlugin紹介 DataTableに関連するEditor Scriptingを楽にできる。BlueprintからDataTableに列を追加や、 DataTableを自動的に保存する機能を加える優秀なプラグイン。 https://www.unrealengine.com/marketplace/en-US/product/datatable-procedural-update-plugin
キャラクター作りを効率的に • この方法により膨大な数のキャラクターを作成 • ユニークなCharacterStatic 700以上
注意点 ハード参照 • ある時点でNintendo Switchへの移植を試したが、 レベルをロードするたびにOut of memoryでクラ ッシュを繰り返していた • 色々調べて気づいた:CharacterStaticsに保管され ているキャラクターのアセットはハード参照されて いる • • Memory SizeをSizeMapツールで調べた • 他も無駄にメモリーを使っていたところがあったが、 これは一番見落としていた点だった ロードする際、全てのキャラクターのモデルをメモ リーにロードしている(約500MB)
注意点 ハード参照 解決策 • ハード参照からソフト参照に切り替えることで、 CharacterStaticsの重さが500MBから7MBまで減少 • ソフト参照を楽に使うために、C++で簡単な AssetManagerを実装 • 「Shores Unknown」は、レベルロードする時にフェ ードがかかっている。アセットを同期ロードしてFPS が落ちても気づきにくいので、AsyncLoadを使わない。 簡単にAssetをゲットできる機能のみ。
戦闘システムの紹介 5人 VS ザ・ワールド • 命令フェーズ:キャラクターの次の行動をきめる • • • 選ぶのはアビリティとターゲットのみ。 使えるアビリティはターゲットによって変化(例:味方→サポート等、敵→攻撃) 行動フェーズ:キャラクターたちは素早さの高い順 に命令を実行に移す(動きは自動) • • 戦闘は特別なマップではなく、探索と同じマップで行われる アビリティを使えば使うほど、 キャラクターが強くなり、新しい アビリティがアンロックされる
戦闘システムの紹介 • 各アビリティには特別なアニメーションと効果がある • ステータス(バフやデバフ)を付与するアビリティもある
アビリティ • UE4のgameplay ability systemを使わず、自作システムを採用している。Blueprintの知識があ まりない人でも、簡単に新しいアビリティを作れるようにすることを目標にした。 • ParentAbilityというクラスを作って、このクラスに どんなアビリティでも使える機能を実装(アニメーション、キャラの移動、 使い終わった時のDispatcher等) • • ParentAbilityから継承した4つのメインクラスを作った: DamageBase→敵にダメージを与える攻撃 HealingBase→味方のHPを回復 PassiveBase→対象に常に何かのステータスを与える DecurseBase→かかっている悪いステータスを解除する この4つから継承して、全てのアビリティをBPで実装 (例えば:複数の敵にダメージを与える等) AAbility (C++ Class) ParentAbility (BP) DamageBase PassiveBase HealingBase DecurseBase
アビリティ キャラクターはアビリティを使うときに、そのアビリティのク ラスのアクタをスポーンする
アビリティ 特徴 「Shores Unknown」はターンベースゲームで、プレイヤーはキャラク ターを直接コントロールすることはない。プレイヤーが与えたコマンドに 従ってキャラたちは自動的に行動するが、バトルフィールド上の動きは乱 戦の雰囲気を生み出す演出にすぎない。
アビリティ 特徴 バトル中の行動はキャラクターのステータスによって決定される。たとえ ば、攻撃の命中は、アビリティBPで計算され、その結果によってターゲ ットにヒット・ブロック・回避のアニメーションをプレイさせている。
アビリティ 特徴 例外もある:弓から放った矢が敵に命中した場合、必ず体のどこかに当た り、その後オブジェクトが残るようにしたかった。そのために、専用の ArrowBPを作って、ProjectileMovementのcomponentによりターゲット にホーミングする機能を実装した。
ステータス • アビリティのアクタは使い終わったら破棄される • バフやデバフなどのステータスを付与するアビリティは、破棄されても ステータスの効果が残る • ステータスもアクタであり、効果時間などを自分で制御する
ステータス • • • ステータスのロジックに様々なEvent Dispatcherが使われている 例えばキャラクターがダメージを受けると効果を発動するステータスがある さらに「Proc」として新しいアビリティを呼び出すステータスも存在している CharacterBPで実装 されたEvent Dispatcherは ダメージを受けると コールされる ステータスのBPでは オーナーキャラクタ ーのDamage Taken にイベントが結合さ れている
ダイアログ 住人達との対話は世界の命運を大きく左右する
ダイアログシステム プラグインを使おうと思っていたが、 UE4↔Excelのワークフローがネックとなり システムを自作した • 目標①:UE4を一切使わずにテキストが書ける • 目標②:テキストをゲームのロジックとアニメーションに簡単に 繋げる • 目標③:Baldur’s GateやDivinity: Original Sinと同じく、 ダイアログの中でプレイヤーに選択肢を与えて、ノンリニアなス トーリーを作れる
ダイアログの構造 • • BPでDialogueManagerのアクタとDialogueStructを用意 • レベルに配置されているキャラクターにRootDlgID(この キャラと話せば再生するダイアログの第一列の TableRowName)を指定 • ヘルパーファンクションも作った: これを使えばレベルスクリプトから ダイアログを再生するも可能に • IDを手打ちする必要があるので注意が 必要。間違えるとバグが発生するが、QAのおかげでなん とかなりました Structをベースにして「DialogueData」という DataTableを作成。ゲームに使用するダイアログは全て ここに保存されている
ダイアログマネージャー • DialogueManagerのアクタはレベルロードの時にスポーン され、常に存在している • DialogueManagerは会話の間に、ゲームフローのコントロ ールを握って、ダイアログの流れとダイアログによってレベ ルに起きるイベントを制御する • DialogueDataのNextNodeIDsというフィールドをパースし、 次に再生できる会話のノードを決める • また、DialogueDataの列にSetFlags、CheckFlags、 SetIntFlags、CheckIntFlagsというフィールドがある。 ノードを再生した際に指定したロジックフラグをセットし、 このノードを再生するための条件が揃っているかをチェック する • SequencerAnimationの再生もできる!
Sequencer Animationについて 全てのカットシーンはSequencer Animationにより実現されている • • ダイアログからでも、レベルスクリプトからでも再生できる • キャラアクタのIsCinematicフラグをOnにすれば、 移動もアニメーションもSequencerに制御される マップに配置されているキャラたちをそのまま使用できる(Cinematic専用のキャラは 不要)
アニメションアセットをどこに? • マーケットプレイスで購入し、 UE4のAdditive Layer Trackにより編集 • • AnimBPでProcedural Animation作成 アウトソーサーに頼む
ロジックフラグ 「Shores Unknown」には、他のRPGと同じく、複数のメインクエストとサイドクエスト が存在する。それぞれのクエストの進行状況とプレイヤーの選択肢によって、 ゲームの世界のステートが常に変わっていく。 例えば: • • • キャラクターが動いたり、現れたり、消えたりする バトルがはじまる 新しいロケーションが開放される このようなステートはグローバルなため、別のレベルに移動した時でもどこかに保存する 必要がある。ゲームをセーブする時にセーブデータに書き込まないといけない。 これらをロジックフラグという変数として、PersistentであるGameInstanceに入れた。
ロジックフラグの実装(1) C++で2つのフラグのUStructを作成し、GameInstanceにUPROPERTYとして宣言
ロジックフラグの実装(2) • • ALevelScriptActorから継承される専用のLevelScriptActorを実装 • GameInstanceのClassで、OnFlagUpdatedとOnStateUpdatedという2つの Delegateを宣言し、LevelScriptのClassでそれらに上のイベントを結合する • BPのFunction Libraryでフラグの セット・ゲットの機能を実装し、 他のBPから気軽に使えるようにする BlueprintImplementableEventとして2つのファンクションを指定
ロジックフラグの実装(3) これでデザイナー達はフラグの変化によって、 LevelScriptの BPで色んなゲームイベントを実装できる。 レベルスクリプトではレベルに配置されているアクタを簡単に参照できるのでさらに便利。
データテーブルを使いやすく • 当初は全てのデータテーブルのRowName を手打ちしていた • 手間がかかる上にヒューマンエラー発生の 心配もあったので、RowNameをEnumの ような扱いにできないかを検討 • Historiaさんのおかげで解決方法を発見。 仕事は数倍早くなった。 ありがとうございます! 詳しくはこの記事をぜひご覧ください: https://historia.co.jp/archives/12411/
RPGはデータばかりではない! レベルデザイン編
世界とロケーション • オープンワールドではないため、 複数のロケーション(Level)に分 かれてる • ーつの屋外のロケーションは最大 で40000x40000ユニット (400x400m) • LevelTransporterのアクタによ り、別のロケーションに移動でき る
様々なロケーションがある!
レベルストリーミング • 同じレベルにジオメトリもトリガーもキャラ も入れると、最適化も編集も大変になってし まう • そのために、UE4のLevel Streamingを活用し て、「Persistent」と呼ばれるメインレベルに 複数のサブレベルを入れて、アクタを整理し た • 例えば、「Static」のサブに静的なオブジェク ト(メッシュやブロッカー)を置く • クエストのロジックを分けるためにも サブレベルを使用
レベルを賢く使いまわす! ストリーミングのおかげで、共通したサブレベルを使いまわしながらバリ エーションを作れる。レベルの数を無理に増やす必要がなくなった。 光と天気のプリセットの交換 条件によってジオメトリも変化
ストリーミングもデータドリブンに • 初期はストーリーの進行に応じて、レベルストリーミングを レベルスクリプトで行っていた • しかし、次第にどのレベルがどこにロード・アンロードされ るかわからなくなってしまった • 解決法として、プレイヤーステートのロジックフラグにより 自動的にサブレベルをストリーミングするシステムを作った • レベルをロードするタイミングで、LevelStreamingData というデータテーブルでロードされているPersistent Level を検索。そのレベルとフラグの条件に合っている サブレベルの配列を取得し、自動的にストリーミングする
「Low poly, high fidelity」 • 厳密に言えば、「low poly」ではなく、「flat shaded」のほうが正しい。 結構ハイポリのモデルもある • Scalability=Epicでは、シーンによって大体1~3百万trianglesが表示される
ランドスケープ UE4のランドスケープは使用しなかった。ローポリにする方法はいくつかあるが、ポリゴ ンの形をコントロールできないので、どうしてもスタイルに合わなかった。 Blenderでローポリのベースメッシュを作る (場合によってこのステップもスキップ) 中~大サイズのモジュラータイプ のアセットでレベルの形を作る Foliageツールで樹木、草、小石など を配置して、手動で微調整を行う
ランドスケープ 注意点 • LODを忘れずに設定。High polyメッシュには必ず、low polyの場合でもレベルで多用するメ ッシュには設定しておくと良い • Culling Volumeを使って小さいメッシュを距離により非表示にする(ポップアップの原因に なるのでやり過ぎないように) • • Foliageツールで小さいオブジェクト(草や小石)にCull Distanceを設定 特に平らな広いレベルでは、カメラの視野角に大きいオブジェクト(Occluder)がないと、遠 くは見えるが最適化しにくくなる場合がある。常にstat unitをOnにしておこう
メッシュをマージすべき? • Merge Actorsツールにより、複数のメッシュを一つに合成し、Draw Callの数を減少 できる(現代のPCでは2,3千があってもあまり気にならないが、PCに比べてCPUス ペックが低い環境ではネックになるので注意) • 特にSplineMeshでDraw Callの数は一気に上がると気づいた このようなSplineMeshは、 数百のDraw Callがかかるこ ともあった。 ーつのメッシュにマージすれ ば、その数は大幅に減少する。 注意! 町の道路みたいな大きいスプ ラインメッシュや、モジュラ ータイプなパーツから作られ た建物をマージすると、 Cullingも効かなくなるし、か かるメモリーも増えるし、 4.22に追加されたAutoinstancingの機能も使えなく なる。 マージ前のほうが軽いことが ある! Actor Mergingについて簡単な説明: https://historia.co.jp/archives/2329/
光と影 コストが高いが、 可動ライトのみを使っている 可動ディレクショナルライト1つ (Shadows On)+可動スカイライト(Shadows On) ディレクショナルライトのDistance Field Shadows → On DF Shadowsがあるかないかによって、遠い オブジェクトの印象が大きく変わる Project SettingsでGenerate Mesh Distance FieldsをOnにすることを忘れずに! (プラットフォームにより、対応していない こともあるので注意)
スカイライトの魔法 Directional Lightの黒い影をもっと自然に Cast Shadows+DFAOでイメージの深さ 多少コストがかかる。1080pでGeforceGTX1060では上のシーンのCast Shadows = Onの Skylightは~0.88ms。可動ライトに比較すると低いが、GPU Profilerを使った確認を忘れずに。
次のステップ • • • • • • アーリーアクセスの終わり 2022のQ2に目指している UE4.25から4.27までアップグレード ストーリー 3章と4章 ローカライズ!日本語も Nintendo Switchでリリース 2022にUE5へ?
ご視聴ありがとうございました!