UE4の勉強記録

UE4の勉強の記録です。個人用です。

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 新しい機能を追加する4

f:id:kazuhironagai77:20200913205138p:plain

<前文>

Fall Guysを見て思った事

正直、私でも作れそうと思いました。しかし同時に私にはこのゲームを発想する事は出来ないとも思いました。このゲームの肝はゲーム内で障害物競争を多人数でしたら面白いはずと言うアイデアと、水平に進む事で正解に近づき、垂直に落ちる事で失敗した事に気付くという人間の本能に直結したゲーム内容です。これは思いつかないです。

しかし世の中にはFall Guysのような面白いゲームを発想出来る人もきっといるはずです。これからはそういうアイデアを持った個人が開発したゲームがAAAの何百億とかけたゲームより売れる時代が来るんでしょうね。そして先週も書きましたが日本文化は世界の中で非常に独特で、そういうアイデアが生まれやすい土壌があると思っています。この日本からゲーム一本で何百億も稼ぐ人が出てくると思います。

そう考えるとこれからの時代はゲームを作って一発当てる人生もアリかも知れません。

ゲーム好きな人は潜在的な頭の良さはピカイチだったのに、学校の勉強を全くしないで人生のレールから外れてしまった人が多いと聞きます。そういう人たちは敢えてゲームを作って一発狙った方が色んな意味で豊かな人生が歩めるじゃないでしょうか。確かにゲームエンジンを使用してゲームの制作が出来る様になるのは決して簡単ではないです。Computer Scienceの分野ではトップレベルのアメリカの大学を卒業した(卒業論文は査読付きの雑誌に掲載された)私でも正直難しいと思います。

しかし元々頭が良い人が正しい方法で勉強すれば理解出来ないレベルの難しさではないと思います。ここで大切なのは正しい方法で教える教材です。UE4に限りませんが、ゲームエンジンの使用方法やゲーム制作を教える教材は、日本語英語に限らず、それで勉強してもゲームを作れるまでには理解が深まる事はないものが多いです。

英語の勉強に例えると分かり易いですが、単語ばっかし覚えてる人がいたとします。そういう人が生の英語を聞くと一字も聞き取れなくて、英語難しい、俺には一生英語を話せるのは無理。と勘違いしてしまいます。しかし本当は、生の英語を聞き取る為には別な勉強が必要なだけです。英語をしゃべったり書いたり出来る様になるためにも別な勉強が必要です。これらの事を総合的に学べば3カ月もすればそれなりに英語で考えれるようになって、聞いたり、書いたり、しゃべったりがそれなりですが出来る様になります。

そういう人達向けにUE4の使い方を教える講座とか作ったら売れるかもしれませんね。

それでは今週の勉強を始めます。

<本文>

今週も、programming partとdesign partに分けてやって行きます。

Programming part

先週、途中で終わった戦闘中のアイテムの使用の機能を完成させます。

Design part

村の作成を続けます。

1. Programming Parts

1.1 AttackTarget()関数の見直し

f:id:kazuhironagai77:20200913205250p:plain

先週、アイテムを使用した際にこの関数を呼ばなかったから戦闘の途中で動作が止まってしまいました。

今回はこの関数の機能から調べていきます。

f:id:kazuhironagai77:20200913205323p:plain

まず、TestCombatAction()を作成しています。

f:id:kazuhironagai77:20200913205342p:plain

あれ、この作成されたTestCombatActionのBeginExecuteAction()関数を見てみると、敵に(自分の攻撃力‐敵の防御力)のダメージを与えているだけですね。

普通に攻撃した場合はこれでいいですが、魔法やItemを使用した場合は困りますね。

確か教科書に特殊攻撃をした場合の例が載っていたはずです。それを見てみましょう。

教科書の10章の6節Abilities logicを読み直すと、

f:id:kazuhironagai77:20200913205359p:plain

単に攻撃力を2倍に設定して攻撃が終わったら元に戻しているだけのようです。

しかし本来ならばこれはItem専用のTestCombatActionクラスを作成して、それを使用すべきなはずです。

のでそうしましょう。

1.2 Item専用のTestCombatActionクラスの作成

1.2.1 Item専用のTestCombatActionクラスを呼び出す関数をCombatUIWidgetクラスに作成する。

f:id:kazuhironagai77:20200913205429p:plain

f:id:kazuhironagai77:20200913205437p:plain

まず、CombatUIWidgetクラスにUseItemInCombat()関数を追加しました。この関数がItemのためのTestCombatActionを呼び出します。

このCombatUIWidgetクラスからBPクラス

f:id:kazuhironagai77:20200913205459p:plain

が作成されています。UE4C++のコードを変えるとその派生のBPに問題が起きる時があったので、今回はしっかり確認します。

まずbuildします。

f:id:kazuhironagai77:20200913205521p:plain

これは問題ありませんでした。

しかしCombatUIからこの新しく作成した関数、UseItemInCombat()を呼び出そうとしたら出来ません。

f:id:kazuhironagai77:20200913205543p:plain

うーん。何で?

念のためUE4 editor側からCompileしたら

f:id:kazuhironagai77:20200913205607p:plain

今度は出て来ました。

うーん。良く分からないですが、これ以外は特に問題なかったです。

1.2.2 UseItemInCombat()をBPから使用する。

以下に示したのが、AttackTarget()関数を呼び出しているBPで攻撃の対象を選択した時に実行されます。

f:id:kazuhironagai77:20200913205639p:plain

これ見るとAttackTargetを選択してActionPanelを隠してコメントを表示する事しかしていません。

今度は私が先週作成したItemを選択し、対象となるキャラを選択した時のコードです。

f:id:kazuhironagai77:20200913205720p:plain

ここで全部実行していました。これは間違っていましたね。ここですべき事は、

  • AttackTargetを選択して
  • ActionPanelを隠して
  • コメントを表示する

の3つだけです。これも直す必要がありますね。

取りあえず、以下のように変更しました。

f:id:kazuhironagai77:20200913205808p:plain

AttackTargetはそのまま使用していますが、対象となるキャラが自分の場合もあるのでこの辺からテストしてみます。

f:id:kazuhironagai77:20200913205831p:plain

あれ。これでも戦闘の途中で終わってしまいます。

一時間以上かかりましたがとうとう原因らしきものを見つけました。以下の部分でItemやRunを選択した時に次のノードを実行する事なく終了しています。

f:id:kazuhironagai77:20200913205850p:plain

以下のように直しました。

f:id:kazuhironagai77:20200913205909p:plain

取りあえず次のノードの繋いで試してみます。

今度は最後までいきました。

f:id:kazuhironagai77:20200913205927p:plain

ああ。びっくりしました。ずっとCombat engineのコードを追っていました。こんな簡単な所を見落としていたとは。

それでは、本来の目的のUseItemInCombat()関数をAttackTarget()関数の代わりに使用します。

といっても中身の実装を全く作成していないので中身はAttackTarget()関数をそのままコピーしました。

f:id:kazuhironagai77:20200913205948p:plain

AttackTarget()関数の代わりにUseItemInCombat()関数を使用します。

f:id:kazuhironagai77:20200913210004p:plain

普通に動きました。

ついでに使用したアイテムを保持しているitemから消します。

f:id:kazuhironagai77:20200913210021p:plain

あれ、道具が全部消えています。

f:id:kazuhironagai77:20200913210039p:plain

これRemove()関数を使用したら一個だけ消えるから…と言う事で前に直したヤツをそのまま使用しているんですが、直した時に間違えたみたいですね。

ブログを見直したら、8月2日のブログで間違った方法で直していました。

f:id:kazuhironagai77:20200913210059p:plain

成程、ThirdPersonCharacterクラスのtext配列からGameInstanceクラスのFStringのTArrayに変更したからRemove()が所持しているitemから一つだけ消去すると勘違いしたみたいですね。Removeは一種類のアイテムを全て消去するので、テストした時にそれぞれの種類のアイテムを一つだけ所持していて気が付かなかったみたいですね。

f:id:kazuhironagai77:20200913210130p:plain

こっちに戻す必要がありますね。これをまず直してしまいましょう。

1.2.3 Itemの消費バグの直し

直しました。

f:id:kazuhironagai77:20200913210152p:plain

テストします。

ダークイーサーを3個購入して戦闘で一つ使用しました。

f:id:kazuhironagai77:20200913210237p:plain

出来ているみたいですね。

ついでに通常のItem使用の場合も直しておきます。

f:id:kazuhironagai77:20200913210311p:plain

テストします。

回復薬が3つあります。一個使用します。

f:id:kazuhironagai77:20200913210328p:plain

一回Pause画面を閉じて開き直しました。

f:id:kazuhironagai77:20200913210345p:plain

回復薬が一個減っています。出来ているようです。

1.2.4 Item専用のTestCombatActionクラスの作成

時間がかかってしまいましたが今度こそ、Item専用のTestCombatActionクラスを作成します。

f:id:kazuhironagai77:20200913210411p:plain

前どうやって作成したのか忘れてしまいました。のでこれで作成します。

まず、動くのかの確認が必要なので実装部はTestCombatActionクラスと全く同じにします。

f:id:kazuhironagai77:20200913210503p:plain

そしてCombatUIWidgetクラスからTestCombatActionItemを作成します。

f:id:kazuhironagai77:20200913210523p:plain

これでTestCombatActionクラスを使用した場合と全く同じに動くはずです。

試してみます。

f:id:kazuhironagai77:20200913210543p:plain

問題なく戦闘中にItemを使用できました。

f:id:kazuhironagai77:20200913210607p:plain

使用したitemは無くなっています。

1.2.5 TestCombatActionItemの改良

取りあえず以下のように改良しました。

f:id:kazuhironagai77:20200913210634p:plain

f:id:kazuhironagai77:20200913210643p:plain

f:id:kazuhironagai77:20200913210655p:plain

f:id:kazuhironagai77:20200913210708p:plain

これでBeginExecuteAction()関数を呼ぶ前にSetItemProperty()を呼べば、Itemが変化させるMP値とHP値をTestCombatActionItemクラスにパスする事が出来ます。

それを踏まえて、UCombatUIWidgetクラスの関数を以下のように改良しました。

f:id:kazuhironagai77:20200913210737p:plain

f:id:kazuhironagai77:20200913210746p:plain

これで使用したアイテム分のHPとMPがターゲットに追加されるはずです。

テストしてみます。

先ず戦闘開始前のそれぞれのHPとMPは以下の通りです。

f:id:kazuhironagai77:20200913210815p:plain

f:id:kazuhironagai77:20200913210823p:plain

KUMOにダークイーサーを使用します。

f:id:kazuhironagai77:20200913210846p:plain

KUMOはゴブリンに攻撃され、更に自分が使用したダークイーサーの作用でHPが10減り、MPが20減るはずです。

f:id:kazuhironagai77:20200913210913p:plain

その通りの結果になりました。

今度は、イーサーをKUMOに使用してみます。

f:id:kazuhironagai77:20200913210940p:plain

KUMOはゴブリンに攻撃され、更にHPが10減りますが、使用したイーサーの作用で、MPが20増えるはずです。

f:id:kazuhironagai77:20200913211004p:plain

その通りの結果です。

こんどはKUROに回復薬を使用します。

f:id:kazuhironagai77:20200913211024p:plain

回復薬を使用したのでHPが100まで回復したのですが、その後にゴブリンに攻撃されたので10下がって90になりました。

f:id:kazuhironagai77:20200913211049p:plain

この後、ゴブリンに回復薬が効くのか試したかったのですが、KUMOが攻撃したら一撃で死んでしまいました。

のでゴブリンの種族値をいじってHPを100にしました。いかに一回KUMOが攻撃した後の図を示します。

f:id:kazuhironagai77:20200913211115p:plain

ゴブリンに回復薬を使用します。

f:id:kazuhironagai77:20200913211138p:plain

ゴブリンのHPが20回復しました。

f:id:kazuhironagai77:20200913211203p:plain

一応出来ていますね。

1.3 戦闘時のitem使用におけるコメントの直し

アイテムを使用した時のコメントがおかしいのでそれを直します。

まず、最初の部分だけ直しました。

f:id:kazuhironagai77:20200913211240p:plain

道具を選択したら、道具、選択した道具の名前、そして使用する相手が表示されます。

以下に追加したコードを示します。

CombatUIで道具ボタンをクリックした時に実行されるコードです。

f:id:kazuhironagai77:20200913211316p:plain

CombatItemウィジェットの道具の一つ(例えば回復薬)を選択した時に実行されるコードを以下に示します。

f:id:kazuhironagai77:20200913211335p:plain

TargetCharacterウィジェット内でitemを使用する相手を選択した時に実行されるコードです。

f:id:kazuhironagai77:20200913211355p:plain

それと大変なバグを一個見つけました。

攻撃ボタンを押した後、更に道具ボタンを押せます。そうすると以下に示したようなコメントが表示されてしまいます。

f:id:kazuhironagai77:20200913211447p:plain

後で直します。

次のコメントは以下のように表示されています。

f:id:kazuhironagai77:20200913211507p:plain

これが攻撃を選択した場合は、

f:id:kazuhironagai77:20200913211530p:plain

となっています。

まず、“KUMO”がゴブリンを攻撃しました。に当たる文章が表示出来る様にします。

結果から示すと以下のような文章を表示するように出来ました。

f:id:kazuhironagai77:20200913211608p:plain

f:id:kazuhironagai77:20200913211616p:plain

以下にコードを示します。

CombatItemウィジェットに追加した部分です。

f:id:kazuhironagai77:20200913211636p:plain

TargetCharacterウィジェットに追加した部分です。

f:id:kazuhironagai77:20200913211656p:plain

最後に以下の部分を直します。

f:id:kazuhironagai77:20200913211724p:plain

先程作成したTestCombatActionItemクラスのBeginExecuteAction()関数内で実行される以下の関数がこの部分のコメントに関わっています。

f:id:kazuhironagai77:20200913211744p:plain

のでC++の挙動にも注意しながら直していきます。

まず、ReportDamageHPtoRPGGameModeBase()関数は以下に示したように、GameCharacterクラスの関数で、RPGGameModeBaseクラスのReportCharacterHPisDamaged() 関数を実行します。

f:id:kazuhironagai77:20200913211816p:plain

RPGGameModeBaseクラスのReportCharacterHPisDamaged() 関数は、

f:id:kazuhironagai77:20200913211841p:plain

で、BlueprintImplementableEventを使用しているので実装部はBP側です。

そのBPにおける実装を以下のように変更しました。

f:id:kazuhironagai77:20200913211908p:plain

これならDamageHPがマイナスの場合は「ほどHPが回復しました。もしくはHPがMaxまで上がりました。」と表示されるはずです。

最後にTestCombatActionItemクラスのBeginExecuteAction()関数内の事を以下に示したように改良しました。

f:id:kazuhironagai77:20200913211938p:plain

これで、アイテムを使用してHPが回復した場合も正しく表示されるはずです。

試してみます。

KUMOに回復薬を使用しました。

f:id:kazuhironagai77:20200913212005p:plain

出来ています。今度はゴブリンに回復薬を使用しました。

f:id:kazuhironagai77:20200913212023p:plain

きちんとコメントされていますね。

成功しているみたいですね。

ただし、アイテムを使用して変化するのはHPだけではありません。MPも変化します。それに対するコメントも追加しましょう。

1.4 戦闘時のMP変化に対するコメントの追加

基本的にはHPが変化した時と同じで良いと思います。ので同じように作成していきます。

まず以下の関数と同じ働きをMPに対してする関数を作成します。

f:id:kazuhironagai77:20200913212055p:plain

GameCharacterクラスの関数なので同じクラスに作成します。

f:id:kazuhironagai77:20200913212114p:plain

クラスからRPGGameModeBaseクラスの関数、ReportCharacterMPisDamaged() をReportCharacterHPisDamaged()関数の代わりに呼びます。

f:id:kazuhironagai77:20200913212143p:plain

RPGGameModeBaseクラスからReportCharacterMPisDamaged()関数を以下に示したように宣言します。

f:id:kazuhironagai77:20200913212221p:plain

Buildします。

f:id:kazuhironagai77:20200913212240p:plain

成功したのでReportCharacterMPisDamaged()関数の実装をBPで行います。

f:id:kazuhironagai77:20200913212307p:plain

実装の内容は、ReportCharacterHPisDamaged()関数とほぼ同じです。

f:id:kazuhironagai77:20200913212326p:plain

MPの回復も表示されるようになりました。

今週はここまでにしておきます。セリフはどこかで一括で管理しないと訳わからなくなりそうです。

2. Design Parts

先週、Medieval_Kingdomの付属の村を開いたらあまりにも重すぎてPCが唸り声をあげたので村は自作する事にしました。

教科書のやり方を勉強してそれ通りに作成する方法もあるかもしれませんが、取りあえず作成してから勉強した方が学びが大きい気がします。ので適当に作成してみます。

2.1 村の作成

適当に作成しました。

f:id:kazuhironagai77:20200913212412p:plain

f:id:kazuhironagai77:20200913212421p:plain

中から見るとこんな感じです。

f:id:kazuhironagai77:20200913212438p:plain

f:id:kazuhironagai77:20200913212446p:plain

f:id:kazuhironagai77:20200913212501p:plain

3. まとめと感想

今週はこれで終わりです。