ネリスさん備忘録

主にUE4の備忘録を残すよ!

【UE5】アイテム取得表示Widgetを作成しよう【Widget】

要するにこれを作る

アイテムを入手した時にニュっと生えてきてシュっと退場するやつ。

続きを読む

【UE4/UE5】3D人さんのポストプロセスの覚え書き

自分向けのためざっくり

個人的にサンプルの01,03,07,09が使いやすいと感じた

VRM4Uでインポートしたモデルについてはマテリアルの設定をちゃんとしないとこのポストプロセスにうまく合わないため調整が必要

 

【UE4】アンリアルエンジンにおけるMOD実装・対応について ①【備忘録】

最近では珍しくもないMODの実装について、自分なりにまとめることにした。
方法の記載は確かにあるけど、情報源が足りない…
というか「作る」情報はあっても、ゲーム内でそれを引き出して扱う情報が足りないと思う。

 

なのでUEにおけるMODとはどういうものか説明を残しておきたい。

※この記事はゲーム本体を完成させパッケージ化できていることを前提にしてるのでご了承を。

 

記事にする実装内容は大きく分けて5つ
ただし長いので分割する予定。今回は1~2当たりの内容となる

  • MODを作成するには
  • MODをゲームで適応させるには
  • Steamワークショップ対応①MODのアップロード
  • Steamワークショップ対応②MODのインストール
  • インストールしたMODの削除について

実装までの前置きが長いので不要な人は序盤を飛ばしても大丈夫です

 

目次

 

前置き:MODとは?

①「MOD」ってなんぞや?

これを見ているゲーム開発者にはわざわざ言うまでもないが、Modificationの略であり、ゲームの改造を行うためのデータの事を指す。

ゲームのキャラを書き換える、パラメータを変更する、新しいシステムを導入するなど、Steam等のPCゲーマーには身近な存在である。
特に日本人的には海外製ゲームを日本語化するMODは特にありがたいので重宝している。

MODでトーマスが人気なのはよくわからんけど…

当然だが、ゲームの改造という性質上MODを適応した場合に関しては開発側はサポートすることは無い。MOD開発者のほうに聞いてねということになる。
MOD適応下でのゲームのバグまで調査してたらキリがない…

このMODだが、制作側に来た場合には「ユーザーが作成したコンテンツ」
UGC(User Generated Contents)

と呼ばれる事が多い。というか公式側は基本的にこの名称を使っている事が多いため、検索する場合はこちらの名称で調べたほうが正しい情報にたどり着きやすい

MODで検索かけてもせいぜい作り方とか、作ってる時のパッケージでのバグとか、どちらかといえばユーザーとしての情報ばかりが出てくるのが厄介なところ。

知りたいのは作り方ではなくゲーム本体側の実装なんだけどなぁ。となりがち…

 

②そもそもUEにおけるMODって何を指すのか?

簡単に言うとゲームの素材などが入っている拡張子が.pakのファイルのこと
そしてその中でも
プラグインコンテンツをパッケージ化したもの
をMODとして扱う

ゲームをパッケージ化した人なら知っていると思うが、パッケージ化されたフォルダの中にはコンテンツが含まれている.pakという拡張子を持つファイルが存在する。
「Content/Pak/○○.pak」みたいなやつ。

←こいつね

ゲーム起動時に「Content/Pak/」以下に存在するファイルをすべて読み込んで使うため、ここに.pakファイルを置くだけでその中のデータが適応されることになる。
(拡張子が違っても読み込みは正常に行われるから書き換えて.modとかでもいい)

ただし追加したMODである.pakファイルが読み込まれると言っても、ゲーム本体側は本来存在しないデータであるためSpawnしたりレベルを移動したりできないのが実際のところである。
Developmentでパッケージ化するなどしてコンソールコマンドからMap移動等するなどすればMODが適応されたMapで遊べたりはするが、それはちょっと違うよねってなる。

やはりShippingでパッケージ化されたゲーム本体がMODのデータを動的に混ぜることができる対応がベストだろう。

MODの下準備

まずはゲーム本体の適応などは考えずに
MODデータを作りパッケージ化するところまでを実行していく。

プラグインコンテンツの作成

前述したとおりMODとはプラグインをパッケージ化したものなのでまずはプラグインを作る。

まずは編集→プラグインを選択してプラグイン一覧を表示する

右下の「新しいプラグインを選択してプラグイン作成ウィンドウを表示する

「コンテンツのみ」を選択し、MODに使うプラグイン名を指定する
この名前は後に使うため、わかりやすいものにすること。

これでプラグインのフォルダが完成。
もし見えない場合はコンテンツブラウザの右下にある「表示オプション」から
プラグインコンテンツを表示」を選択して探そう

基本的にここで作成したプラグインコンテンツのフォルダ内のものが
そのままMODとしてゲームに認識される事になる。

逆に言うと、MODのコンテンツはそのフォルダ内で完結している、或いはゲーム本体のデータを利用していないとパッケージ化した際にデータが足りなくなるため注意が必要。
MODのMapや装備なんかを自分のアセットを使って作ったけど、フォルダ内に入れ忘れた結果適応した時に何もでなかったりエラーを吐いたりする。

MODのパッケージ化

参考にした動画をそのまま貼っちゃう…。
設定内容は動画のものに従い、余計な設定はしない方が賢明。

UE4でMOD対応ゲームを作る その2 - なんとなく日誌

プロジェクトランチャーを使いゲームのパッケージ化を行い、
そのあとでプラグインのパッケージ化を行うことで.Pakファイルが作成される。

必ずゲーム本体のパッケージ化を行った後にプラグインのパッケージを行う必要があるので注意。

 

ちなみに、ゲーム本体のパッケージ化について
こちらの方法は関係がないので横着しないこと。
ちゃんとプロジェクトランチャーでパッケージ化しよう。

 

成功すれば

Plugins\MyMOD\Saved\StagedBuilds\WindowsNoEditor\MODTest\Plugins\MyMOD\Content\Paks\WindowsNoEditor\

の中に.pakのファイルが生成されているはず。
とても深い場所に生成されるから探すのが面倒。

これが事実上のMODファイルとなる
ファイル名は機能に影響がないので自由に書き換えてOK

パッケージ化したファイルを指定したフォルダに配置する

パッケージ化したMODは適当に名前を変えて
パッケージ化したゲーム本体のContent/Paksフォルダ以下に置けばOK
これだけで起動時に作成したMODが読み込まれる

MODをゲーム内で使うためには?

※ここからはC++での作業が必須となるので注意

ゲーム起動後に特定のパッケージ内のデータを取得できるようにする

.pakを置くだけで起動時に読み込まれるとはいえ、ゲーム本体はMODのデータのことを知らないためそのままではゲームに影響を与える事ができない。
そのため、ゲーム側にMODがある場合の動作を組み込む必要がある。
(コンソールコマンドでMODの中のMAPに対してOpenLevelするなどの方法はあるが、邪道の類なので今回は除外する)

 

今回はGameInstanceにMOD内のクラスを引き出せるようにする処理を追加する。
まずC++クラスの追加からGameInstanceのベースクラスを作成する。
もしすでにベースクラスを作っているのであればそれを使う。



まずはScanUGC関数を宣言して

 

cpp側にEngine/ObjectLibraryをincludeしたうえで
以下の処理を記述する

この処理でmyMODという名前のプラグインで作られたMODの中身を取得できるようにした。

準備は整ったのでこのMyGameInstanceを継承したGameInstanceを作成して
プロジェクトに設定する

プロジェクト設定>マップ&モードのGameInstanceメニュー内から変更できる

 

その後Init時にScanUGCを呼び出すことでプラグイン(MOD)が読み込まれる

そしてGetAssetRegistryノードからGetAssetbyPathノードを繋いで以下の図のようにすればMODアセットが配列として取得できる。

ただ、このままだとクラスとして扱えないためアセットデータをクラスに変換する処理C++で記載する
まずはヘッダにGetClassfromAssetData関数を追加

中身はこんな感じに、アセットデータが持つパスからクラスを取得してそれを返す内容

あとはこれを使ってクラスを取得してCastすればアセットデータの中の任意のクラスを引き出すことができる。

やれる人ならクラスが取れれば後はなんとでもできそうではある。

①既存アイテムに追加する方法:例

※アイテムの管理などをデータテーブルで行っていることを前提としての話

データテーブルの代わりになるものを作る。

データテーブルは構造体をキーで管理しているため、その気になればMAP型で再現ができる。MAP型の扱いに関しては別で覚えてほしい。


とりあえずこんな感じでアイテムデータテーブルのようなものを作成。

GameInstanceのメンバ変数としてこんなものを作る。
これが今回のDataTableの代わり

まずはこの配列を元々のデータテーブルで埋める

これによって、Findノードを使うことでデータテーブルとほぼ同等の扱いができるようになった。

つまり、ここにデータを足していくだけでアイテムリストの追加が可能になる
こんな感じに、アイテム追加用クラスを用意してやり、それがMODデータ内にあればCastに成功するためアイテムの追加が完了する

先述した通りデータテーブルと同様の振る舞いが可能なのでGetDatatableRowノードを置き換えてやればMODアイテムが自動的に増やせる
自分はこんな感じにインターフェースを作成し任意の場所からアクセスできるようにしたりしている。

あとはMODアイテムを含んで販売する商人を置いたり、ドロップアイテムとするなりすればゲーム内にMODアイテムが導入できる。
アイテム以外でも敵の種類なども同様。


②既存クラスを置き換える方法:例

クラスの置き換えができるようにする

ざっくり言うと元々のクラスをキーとして、MODクラスを返す関数を作り
そのSpawn処理の前に割り込ませることで特定のクラスをMODクラスに置き換えてしまうという手法。

ただちょっと長くなりすぎているので一旦ここで公開してしまう。
賢い人は今の説明でも何をすればいいかを理解してくれる…はず。

 

つづく。

lunanelis.hatenablog.com

 

【UE5】GameplayAbilitySystemを使ったコンボ攻撃通知の実装【GAS】

いい感じのコンボシステムができたので備忘録的にかきかき

 

以前にもGASについて書いてるからこっちも参照してね

【UE5】GamePlayAbilitySystemによるコンボ攻撃の実装とそれに利用する小ネタ 前編【GAS】 - ネリスさん備忘録

【UE5】GamePlayAbilitySystemによるコンボ攻撃の実装とそれに利用する小ネタ 後編【GAS】 - ネリスさん備忘録

 

基本的なコンボのつなぎは上記の通りなので割愛。

  • 前置き
  • 当たり判定表示用のAnimNotifyStateを作成する
  • 通知を受け取り攻撃判定を発生させる処理をAbilityに実装する
  • Abilityに渡したいデータの構造体を作成する
  • 渡したいデータの構造体を持つObjectクラスを作成する
  • Abilityにデータを渡す
  • Abilityが受け取ったデータを使い当たり判定を生成する
  • まとめ

前置き

具体的に言うと、Montage内で攻撃判定のサイズ、効果時間等を指定できるというもの
その気になれば当たり判定の形状、ダメージ量、当たり判定のなんかまでMontage内でコントロールできるし、好きなデータをAbilityに渡すことができる。

アビリティ側を徹底したらMontageを増やすだけでアクションを追加できると思う。

そもそも、こういう仕組みを作ろうと思ったのは、たり判定生成の処理があまりにも冗長で、扱いにくいものだったためである。


↑のような方法で攻撃判定を実装していたが、連撃だとか違う種類のダメージを与えようとすると通知時に設定したNotifyNameでSwitchして当たり判定を生成する処理がその回数分増殖していくのは見るに堪えない…

そこで、使いまわしをしつつパラメータをMontage側で指定することで
Ability側の処理を一つだけで済むように改修したのがコレ。
このブロックだけで何度でも当たり判定を生成できるため、Ability側の処理がスッキリする。
ベースクラスにマクロや関数で実装してしまえば当たり判定生成の処理はノード1個置くだけで終わりというレベルにまでできるだろう。

BaseDamageは試験的に直接値を入れてるだけなので、これもMontage側で指定できるよ

 

続きを読む

【UE5】Niagaraのお勉強。【Niagara】

【UE5】Niagara Tutorial:敵へ向かう弾を発射する 【ゲーム制作】【VOICEVOX 春日部つむぎ】 - YouTube

というわけで、長らく触れてこなかったNiagaraを勉強する…

なんか触ってなかったのよね。

Voiceroidの解説は肉声が嫌いな人間にとってすごい助かるんよ

続きを読む

【UE5】GamePlayAbilitySystemによるコンボ攻撃の実装とそれに利用する小ネタ おまけ【MotionWarping】

実質的にこの記事の続き

lunanelis.hatenablog.com



コンボ攻撃はできたから、ダッシュ攻撃を実装する

MotionWarpingを使って、前説明したAnimNotifyStateのようなものを作り
その区間中にRootMotionのように移動量を付与できるというもの

公式はこちら

docs.unrealengine.com

 

 

続きを読む