UE4の勉強記録

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

「Unreal Engine4.xを使用してRPGを作成する」の3章の3.4を勉強する part 5

<前文>

f:id:kazuhironagai77:20190707235030p:plain

<本文>

<目的>

3章3節の5、ターン制の戦闘(turn based combat)の5、UMGによる戦闘UI(Combat UI with UMG)を勉強します。やっと簡単になったのかなと思ったらSlateモジュールなどを使用して作成するみたいですね。これは結構ハードルが高いかもしれませんね。

<方法と結果>

<Step.0>

前回まで使用していたCh2をそのまま今回も使用します。

<Step.1>

教科書に、

まず〔プロジェクト名〕.Build.csを開き、コンストラクターの最初の行に"UMG", "Slate", "SlateCore"を追加します。

とありました。しかし私のプロジェクトのCh2.Build.csファイルには、

f:id:kazuhironagai77:20190707235134p:plain

があります。これをアンコメントした方が良いような気がします。この場合PrivateDependencyModuleNames()関数で実装される事になるので最初の行に追加した場合のPublicDependencyModuleNames()関数で実装した場合と厳密には違いますがどちらが正しいのでしょうか?

まず、サンプルコードを見てみます。

f:id:kazuhironagai77:20190707235213p:plain

サンプルコードではPrivateDependencyModuleNames()関数をアンコメントせずにPublicDependencyModuleNames()関数に追加していますね。

ウーン。前にPrivateDependencyModuleNames()関数とPublicDependencyModuleNames()関数の違いについて勉強したのですが忘れてしまったのでもう一度復習してから決定します。このサイトに、PrivateDependencyModuleNames()関数とPublicDependencyModuleNames()関数の違いについての解説があります。

f:id:kazuhironagai77:20190707235243p:plain

この解説によると、

PublicDependencyModuleNames()関数Public Privateフォルダーの両方が利用出来る。

PrivateDependencyModuleNames()関数Privateフォルダーのみが利用出来る。

とあります。ただしこの後の解説で普通のプラグインはPublicのフォルダー内にはインターフェイスしか入っていないのでPrivateのフォルダーのみにアクセス出来るPrivateDependencyModuleNames()関数で良いとあります。

成程。分かりました。モジュールを使用するに当たってそのモジュール内にある関数がもしPublicフォルダーにしか存在しないならそのモジュールはPublicDependencyModuleNames()関数を使用しなければなりませんが、それ以外はPrivateDependencyModuleNames()関数でいいと言う事ですね。

しかしこれは逆に言えば全てにPublicDependencyModuleNames()関数を使用すれば良いとも言えます。大は小を兼ねる。ですね。

色々考えましたが、今回はサンプルコードと同じにします。

f:id:kazuhironagai77:20190707235648p:plain

"UMG", "Slate", "SlateCore"をPublicDependencyModuleNames()関数に追加しました。

<Step.2>

次にRPG.hファイルに以下のコードを追加します。

f:id:kazuhironagai77:20190707235723p:plain

教科書のRPG.hファイルは私のCh2.hファイルなので、Ch2.hファイルに追加します。

f:id:kazuhironagai77:20190707235744p:plain

サンプルコードにはEngine.hファイルもインクルードされていたのでついでに追加しました。

ビルドします。

f:id:kazuhironagai77:20190707235805p:plain

かなり時間がかかりましたが成功しました。

<Step.3>

次に戦闘UIのための基礎クラスを作成します。名前はCombatUIWidgetです。UserWidgetクラスから作成します。Source/RPG/UIフォルダー内に作成します。

まず、UIのフォルダーから作成します。UIフォルダーはSourceフォルダー内のCh2フォルダー内に作成します。

まずvisual studioのsolution explorer内のsolutions and foldersをクリックします。

f:id:kazuhironagai77:20190707235834p:plain

実際のファイルが保存されているフォルダーが表示されますので、そこにUIフォルダーを追加します。

f:id:kazuhironagai77:20190707235855p:plain

次にCombatUIWidgetクラスを作成します。まずC++ウィザードをUE4エディターから起動させて親クラスにUserWidgetを選択します。

f:id:kazuhironagai77:20190707235923p:plain

Pathには先程作成したUIフォルダーを指定します。

f:id:kazuhironagai77:20190707235954p:plain

作成しました。

UE4エディターではこんな感じで表示されています。

f:id:kazuhironagai77:20190708000017p:plain

Visual Studioのsolution explorer内では以下のように表示されています。

f:id:kazuhironagai77:20190708000040p:plain

それでは教科書通りにコードを追加していきます。

f:id:kazuhironagai77:20190708000103p:plain

f:id:kazuhironagai77:20190708000114p:plain

追加しました。

AddPlayerCharacterPanel()関数とAddEnemyCharacterPanel()関数は、キャラクターへのポインターを獲得する事とそのキャラクターのためのウィジェットを作成する事を行うための関数だそうです。

試しにビルドしたところ成功しました。

<Step.4>

CombatUIWidgetを親クラスとするCombatUIと名付けたWidget BlueprintをContent/Blueprints/UIフォルダー内に作成します。

以下に教科書に書かれている手順を示します。

  1. まずUE4エディターからContent/Blueprints内にUIと名付けた新しいフォルダーを作成します。
  2. 次にそのフォルダー内にCombatUIと名付けたWidget Blueprintを作成します。
  3. そしてそのBPを開きFile|Reparent Blueprintに行きCombatUIWidgetを選択します。

後から親クラスを変更するみたいです。この方法は初めてです。教科書に書かれている通りにやって行きましょう。

f:id:kazuhironagai77:20190708000213p:plain

まずフォルダーUIをContent/BP内に作成しました。これは簡単ですね。

次にWidget BlueprintをUser Interfaceから選択します。

f:id:kazuhironagai77:20190708000235p:plain

名前をCombatUIと名付けます。

f:id:kazuhironagai77:20190708000306p:plain

そしてそのBPを開きFile|Reparent Blueprintに行きCombatUIWidgetを選択します。

f:id:kazuhironagai77:20190708000347p:plain

CombatUIWidgetがありませんね。

うーん。とコードと教科書を見直していたらStep.3でCombatUIWidgetと名付けるところをMyUserWidgetのままにしていました。

f:id:kazuhironagai77:20190708000411p:plain

こんな凡ミスを犯すなんて!と思いましたが、やってしまったものはしょうがないのでこれを直します。直す方法ですが色々考えたのですが最初からやり直すのが一番速そうです。のでMyUserWidgetを消してCombatUIWidgetを作り直します。

まずMyUserWidgetを消します。ここで思ったのですがUE4C++における正しいファイルの消し方の手順みたいのはないのでしょうか?ちょっと調べて見ます。

ありました。

このサイトによると

f:id:kazuhironagai77:20190708000445p:plain

となってました。ただしこの回答をした人も俺はこのやり方で問題なく出来ているけど。みたいなあまり自信のない書き方でした。Binariesファイルだけ消去する理由は何故なんでしょうか?どうせなら必要なファイル以外は全て消してやり直した方が安心出来ると思うのですが?それに4. Run GenerateProjectFiles.batするよりもuprojectファイルを実行した方がいい気がします。ので私が勝手にUE4C++におけるC++クラスファイルの消去の仕方を作り直しました。

  1. Visual StudioUE4エディターを閉じる。
  2. Soruceファイル内の削除したいhファイルとcppファイルを削除する。
  3. .vs, Binaries, Intermediate, Saved, そして.slnフォルダーを消します。(必要なフォルダー以外は全て削除します。)
  4. .uprojectを実行します。
  5. .uprojectを右クリックしてGenerate visual studioを選択して新しいVisual studio solutionを作成する

多分これの方がいいでしょう。やって行きます。

f:id:kazuhironagai77:20190708000518p:plain

念のためにプロジェクトのコピーをしておきます。

f:id:kazuhironagai77:20190708000540p:plain

MyUserWidget.hとMyUserWidget.cppファイルを消します。

f:id:kazuhironagai77:20190708000609p:plain

.vs, Binaries, Intermediate, Saved, そして.slnフォルダーを消します。

.projectをクリックします。

f:id:kazuhironagai77:20190708000632p:plain

はいを選択します。

f:id:kazuhironagai77:20190708000652p:plain

ビルドが終わるまで待ちます。ビルドが終わるとUE4エディターが自動的に開かれれるので、MyUserWidgetがない事を確認して閉じます。

f:id:kazuhironagai77:20190708000801p:plain

.uprojectを右クリックしてGenerate visual studio…を選択します。

f:id:kazuhironagai77:20190708000827p:plain

.slnが作成されました。

Epic launcherからCh2を開きます。そしてUE4エディターからvisual studio を開きます。

f:id:kazuhironagai77:20190708000852p:plain

見事にMyUserWidgetが消えています。

当然ですがビルドとしても成功します。

f:id:kazuhironagai77:20190708000919p:plain

ただGameModeの設定がNoneになっているのですが前からこうだったのか覚えていません。

f:id:kazuhironagai77:20190708000939p:plain

ちょっと不安が残りますが続きをやって行きましょう。

Step.3をやり直します。Source/RPG/UIフォルダー内にCombatUIWidgetクラスをUserWidgetクラスから作成します。

f:id:kazuhironagai77:20190708001001p:plain

今度は間違えずに名付けます。

f:id:kazuhironagai77:20190708001021p:plain

今度こそ間違えなく出来ました。

f:id:kazuhironagai77:20190708001044p:plain

コードを追加していきます。

f:id:kazuhironagai77:20190708001113p:plain

f:id:kazuhironagai77:20190708001124p:plain

ここでビルドしてみると成功しました。

これで要らないMyUserWidgetクラスを消去して必要なCombatUIWidgetクラスを追加出来たはずです。

CombatUIをもう一度開いて見ます

f:id:kazuhironagai77:20190708001149p:plain

今度はCombatUIWidgetがありました。

CombatUIWidgetを選択します。

<Step.5>

教科書に

Designerインターフェイス内で、二つのHorizontal Box widgetを作成します。

それぞれの名前をenemyPartyStatusplayerPartyStatusにします。

この二つは敵とプレイヤーのそれぞれの現状の状態を示すための子のwidgetを保持します。

とありました。

f:id:kazuhironagai77:20190708001232p:plain

作りました。

それぞれのboxのIs Variableがenableになってる事を確認します。

f:id:kazuhironagai77:20190708001251p:plain

之の事でしょうか?違うような気もしますが、他に見当たらないので良いとします。両方のboxを確認しました。

enemyPartyStatusから位置を調節します。

f:id:kazuhironagai77:20190708001319p:plain

Anchorから黄色で囲ったヤツを選択します。

f:id:kazuhironagai77:20190708001356p:plain

教科書に指定された値を入力します。

playerPartyStatusも同様に位置を調節します。

f:id:kazuhironagai77:20190708001417p:plain

以下に示したように教科書に示されている図とほぼ同じように出来ました。

f:id:kazuhironagai77:20190708001501p:plain

<Step.6>

次にプレイヤーと敵のキャラクターの状態を表示するwidgetを作成します。最初に基礎になるウィジェットを作成します。

BaseCharacterCombatPanelと言う名前のWidget Blueprintを作成します。

MyBlueprintタブ、CharacterTargetそしてObject ReferenceのカテゴリーからGameCaracter変数を選択する事で新しい変数を追加します。

と教科書に書かれていました。

f:id:kazuhironagai77:20190708001541p:plain

Widget Blueprintを作成しBaseCharacterCombatPanelと名付けました。

BaseCharacterCombatPanelをクリックしてBPエディターを開きます。

BPエディターが開いたら右上にあるGraphをクリックして表示をグラフに変更します。

f:id:kazuhironagai77:20190708001606p:plain

BPエディターの左側にあるMyBlueprintからVariablesの+をクリックして新しい変数を追加します。

f:id:kazuhironagai77:20190708001626p:plain

新しく追加された変数を選択してDetailをみるとvariable TypeがBooleanになっているのでこれをGameCaracterに変更します。

f:id:kazuhironagai77:20190708001646p:plain

Object typesからGame Characterを選択し、更にObject Referenceを選択しました。

f:id:kazuhironagai77:20190708001716p:plain

これで合っていると思うんですがCharacterTargetが何なのか分かりませんね。念のためにサンプルコードを起動(UE4.12で起動)してチェックしてみます。

f:id:kazuhironagai77:20190708001758p:plain

CharacterTargetはこの変数の名前でした。

f:id:kazuhironagai77:20190708001933p:plain

教科書には以下のように書かれていたのですが、

f:id:kazuhironagai77:20190708001953p:plain

新しい変数、CharacterTarget、と読めばまあCharacterTargetが新しい変数の名前を指していると読めなくはないですね。

後、GameCharacterの右隣にルービックキューブみたいなのが表示されていますが、サンプルコードの方はarrayになっているの?

f:id:kazuhironagai77:20190708002020p:plain

これって確か古いUE4のバージョンと新しいバージョンでは表示方法が違っていたはずです。のでarrayになってはいないはずです。

はい。これでここまでは一応出来ました。次に行きます。

<Step.7>

新しいWidget Blueprintを作成します。名前はPlayerCharacterCombatPanelとします。

新しいBlueprintの親にBaseCharacterCombatPanelを指定します。

とありました。

f:id:kazuhironagai77:20190708002148p:plain

まずWidget Blueprintを作成し名前をPlayerCharacterCombatPanelに変更しました。

f:id:kazuhironagai77:20190708002217p:plain

更にBaseCharacterCombatPanelを親に指定し直しました。

<Step.8>

次に教科書では以下の作業を追加するように述べています。

デザイナーインターフェイスから、三つのテキストウィジェットを追加します。

一つ目のラベルはキャラクターの名前、

もう一つはキャラクターのHP

そして三番目はキャラクターのMPです。

スクリーンの左下に配置されるようにします。

そして我々が作成したCombat widget内のplayerPartyStatusboxのサイズである高さ200ピクセル内に収まるようにします。

やって行きます。

f:id:kazuhironagai77:20190708002326p:plain

f:id:kazuhironagai77:20190708002334p:plain

出来ました。

それぞれのTextBoxのdetailでSize To Contentをチェックします。

f:id:kazuhironagai77:20190708002411p:plain

これらのそれぞれのウィジェットのために新しいバインドを作成します。DetailsパネルにあるTextインプットの隣のBindをクリックしてください。

f:id:kazuhironagai77:20190708002433p:plain

f:id:kazuhironagai77:20190708002440p:plain

しました。

<Step.9>

次にテキストブロックを生成するためのブループリント関数を作成します。

教科書に一例としてHPを連結する方法が紹介されています。

  1. このグリッド内のオープンエリア内を右クリックし、Get Character Targetを探します。探したらそれをクリックします。
  2. このノードのアウトプットピンを引っ張り、Variables|Character Info下にあるGetHPを選択します。
  3. 新しいFormat textノードを作成します。そのテキストをHP: {HP}と設定します。そしてGetHPのアウトプットをFormat Textノードのインプットに接続します。
  4. 最後にFormat TextノードのアウトプットをReturnノードのreturnに接続します。

このまま実行します。

f:id:kazuhironagai77:20190708002524p:plain

1.で紹介された方法でCharacter Targetを収得しました。

f:id:kazuhironagai77:20190708002632p:plain

同様に2.で紹介された方法でCharacter Target のHPのノードを収得しました。

3.で紹介されているFormat textノードが何なのか不明ですね。サンプルコードを実行して確認してみます。

f:id:kazuhironagai77:20190708002658p:plain

こうなっていました。となるとFormat textというノードがあるようですね。

f:id:kazuhironagai77:20190708002725p:plain

こうなりました。サンプルコードと違いFormat Textはintをintとして受け入れています。取りあえずこのままで行きます。

最後に

f:id:kazuhironagai77:20190708002758p:plain

Format textのresultとReturn Nodeのreturn valueを連結します。

これをPlayerCharacterCombatPanel BPのNameとMPも同様に行い、更にEnemyCharacterCombatPanelBPも同様に作成して下さいとあります。

分かりました。それではやって行きましょう。

PlayerCharacterCombatPanel BPName

f:id:kazuhironagai77:20190708002825p:plain

こんな感じで作成しました。念のため、サンプルコードの方も見てみます。

f:id:kazuhironagai77:20190708002852p:plain

まあ大体一緒ですね。

PlayerCharacterCombatPanel BPMP

次はMPを作成します。

f:id:kazuhironagai77:20190708002927p:plain

こんな感じになりました。

EnemyCharacterCombatPanelBP

EnemyCharacterCombatPanelBPをPlayerCharacterCombatPanelBPと同様に作成します。

f:id:kazuhironagai77:20190708002948p:plain

f:id:kazuhironagai77:20190708002956p:plain

f:id:kazuhironagai77:20190708003004p:plain

f:id:kazuhironagai77:20190708003018p:plain

f:id:kazuhironagai77:20190708003027p:plain

しました。

EnemyCharacterCombatPanel BPName

f:id:kazuhironagai77:20190708003050p:plain

こんな感じに出来ました。

EnemyCharacterCombatPanel BPHP

f:id:kazuhironagai77:20190708003110p:plain

PlayerCharacterCombatPanelBPのHPと同じですね。

<Step.10>

やっと我々はプレイヤーと敵のウィジェットを持つ事になりました。

CombatUIのブループリント内でAddPlayerCharacterPanel関数とAddEnemyCharacterPanel関数を実装しましょう。

と教科書に書かれていますのでやりましょう。

まず最初に、キャラクターステータスのウィジェットを発生するためにヘルパーブループリント関数を作成します。

この新しい関数をSpawnCharacterWidgetと名付けます。そして以下のパラメーターをインプットに追加します。

  • Target Character (of type Game Character Reference)
  • Target Panel (of type Panel Widget Reference)
  • Class (of type Base Character Combat Panel Class)

とありますのでCombatUIブループリントからやっていきます。

f:id:kazuhironagai77:20190708003207p:plain

を開き、関数を追加します。

f:id:kazuhironagai77:20190708003226p:plain

そのパラメーターを

f:id:kazuhironagai77:20190708003248p:plain

教科書通りに使用としたら最後のパラメーターのタイプであるBase Character Combat Panel Classがありませんでした。これってCombatUIの隣にあるWidgetの事ですよね。

f:id:kazuhironagai77:20190708003308p:plain

うーん。どうやってこれをインクルードするのでしょうか?

取りあえずコンパイルしてみます。

f:id:kazuhironagai77:20190708003338p:plain

あれ出来たみたいです。

一応サンプルコードで確認してみます。以下にサンプルコードのSpawnCharacterWidget関数のインプットを示します。

f:id:kazuhironagai77:20190708003400p:plain

うん。合ってそうです。

<Step.11>

Step.10でSpawnCharacterWidget関数のインプットまで作成しました。Step.11ではSpawnCharacterWidget関数を実装します。

  1. Create Widgetを使用して与えられたクラスの新しいウィジェットを作成します。
  2. 新しいウィジェットBaseCharacterCombatPanelタイプにキャストします。
  3. Character Targetの結果をTargetCharacterのインプットにセットします。
  4. TargetPanelのインプットとして新しいウィジェットを追加します。

と実装の手順が説明されていますのでその通りに作成します。

f:id:kazuhironagai77:20190708003438p:plain

出来ました。出来ましたがCast to BaseCharacterCombatPanelノードの所で、オブジェクトは既にBaseCharacterCombatPanelであるのでキャストする必要はありませんと警告が出ています。

念のためサンプルコードをチェックすると

f:id:kazuhironagai77:20190708003509p:plain

サンプルコードは何の警告も出ていませんでした。

後、手順3はBaseCharacterCombatPanelオブジェクトの変数Character Targetの値をSpawnCharacterWidget関数のインプットであるTarget Panelでセットします。と言う意味でした。

それならSet the Target Character input to the Character Target of the Base Character Combat Panelというべきじゃね。と思ってるのですがどうでしょうか?

<Step.12>

今度はCombatUIのブループリントのイベントグラフ内で作業します。

右クリックしてEventAddPlayerCharacterPanelEventAddEnemyCharacterPanelイベントを追加します。

これらをそれぞれSpawnCharacterWidgetノードに連結して、そのtargetのアウトプットをTargetCharacterのインプットと連結します。

そして適切なパネル変数をTarget Panelインプットに連結します。

f:id:kazuhironagai77:20190708003603p:plain

ここまでは出来ました。Target Panelに連結する変数Enemy Party StatusとPlayer Party Statusが見つかりません。勝手に作っていいのでしょうか。サンプルコードで確認してみます。

f:id:kazuhironagai77:20190708003629p:plain

お。変数にしっかり定義されてます。これは?

f:id:kazuhironagai77:20190708003654p:plain

Detailをみるとこの変数のタイプはHorizontal Boxになっています。もしかして

f:id:kazuhironagai77:20190708003718p:plain

デザイナーモードに戻ってenemyPartyStatusを確認してみると変数にするにチェックが付いていました。これですね。

f:id:kazuhironagai77:20190708003752p:plain

f:id:kazuhironagai77:20190708003800p:plain

チェックをつけてEnemy Party StatusとPlayer Party Statusを変数化します。

f:id:kazuhironagai77:20190708003823p:plain

グラフモードに戻るとEnemy Party StatusとPlayer Party Statusが変数として表示されています。

f:id:kazuhironagai77:20190708003848p:plain

今度こそ出来ました。

<Step.13>

  • とうとう戦闘の最初に我々のゲームモードからこのUIフォームを発生しさらに戦闘の最後にそれを破壊する事が出来る様になりました。
  • RPGGamModeのヘッダー内で、UCombatUIWidgetcombatUIのために発生するクラスにポインターを追加します。
  • (そうする事で我々はウィジェットブループリントを選択します。そのウィジェットブループリントは我々のCombatUIWidgetクラスから継承しています。)
  • これらはPublicであるべきです。

と書かれていました。

f:id:kazuhironagai77:20190708003931p:plain

f:id:kazuhironagai77:20190708003939p:plain

教科書の指定通りにコードをRPGGamMode.hに追加しました。追加した二つの変数は教科書の指示通りにPublicに追加しました。

<Step.14>

RPGGamModeのTestCombat()関数の最後に以下に示すように、このウィジェットの新しいインスタンスを発生させます。

とありました。

f:id:kazuhironagai77:20190708004017p:plain

ので丸コピーで教科書のコードをRPGGamModeのTestCombat()関数の最後に追加しました。

f:id:kazuhironagai77:20190708004049p:plain

最初のコードの意味は明白ですね。Step.13で宣言した変数、CombatUIInstanceの初期化を実装しています。

f:id:kazuhironagai77:20190708004112p:plain

2番目は何をやっているのでしょうか?

AddViewport()関数ってどっかで聞いたことがある関数ですね。

うーん。思い出しました。ブループリントでWidgetを表示する時に使用する関数です。

f:id:kazuhironagai77:20190708004136p:plain

となるとここでウィジェットを表示するわけですね。

f:id:kazuhironagai77:20190708004159p:plain

となるとこの部分のコードの意味はもう明白ですね。マウスのカーソルを表示すると言う意味ですね。

f:id:kazuhironagai77:20190708004221p:plain

同様なブループリントのノードがありますね。

f:id:kazuhironagai77:20190708004241p:plain

このForループが分からない所があるのですがそれはちょっと置いておいてAddPlayerCharacterPanel()関数から見ていきます。

f:id:kazuhironagai77:20190708004309p:plain

AddPlayerCharacterPanel()関数が呼ばれるとCombatUIWidgetのEvent Graphにある上記のイベントが実行されます。TargetはgameInstance->PartyMembers[i]なのでいつものプレイヤーのデータが送られるのは分かります。

しかしPlayer Party Statusは単なるボックスなのでこれを送る意味があまり分かりません。

f:id:kazuhironagai77:20190708004330p:plain

この先にあるSpawnCharacterWidget()関数内の実装をみてもPlayer Party Statusを指すTarget PanelはAdd Child()関数に直接パスされていて一寸意味が分からなくなってしまっています。この辺は考察でしっかり考えてみたいと思います。

f:id:kazuhironagai77:20190708004405p:plain

これはウィジェットを作成し、ビューポートにそれを追加し、マウスカーソルを追加し、そしてAddPlayerCharacterPanel()関数とAddEnemyCharacterPanel()関数を全てのプレイヤーと敵にそれぞれ追加します。

とあります。この「全てのプレイヤーと敵にそれぞれ追加します。」の部分ですがこれはForループの部分を指していると思われるのですが、これを行ってしまうとすべてのplayerのメンバーと敵のメンバーのステイタスのウィジェットが一遍に開いてしまうのではないでしょうか?ここも分からない部分です。

が取りあえず先に行きます。

<Step.15>

  • 戦闘が終了した後、ビューポートからウィジェットを取り除きます。
  • そしてレファレンスをnullにセットします(のでガーベージコレクションされます)。
  • Tick関数は以下の様になります。

と教科書にありました。以下の部分のコードをコピーしましょう。

f:id:kazuhironagai77:20190708004523p:plain

実際にコピーしたのは上記の部分だけでした。教科書の最初の解説をそのままコードにしただけですね。

<Step.16>

  • この時点で、コンパイル出来ます。
  • しかしコンバットをテストしたらゲームはクラッシュします。
  • なぜからcombatUIをあなたがhで作成したCombatUIClassとして使用するためにDefaultRPGGameModeクラスのdefaultをセットする必要があるからです。

とありました。と言う事はビルドは出来ると言う事ですね。試してみます。

f:id:kazuhironagai77:20190708004558p:plain

成功しました。

f:id:kazuhironagai77:20190708004620p:plain

defaultRPGGameModeクラスのCombatUIClassの設定をCombatUIに変更しました。

これで全部出来たはずです。テストしてみます。

f:id:kazuhironagai77:20190708004646p:plain

速すぎでスクリーンショットが全部は取れないですが教科書の説明と同じ結果が表示されました。

<考察>

今週は量が多くて時間が無くなってしまいました。ので考察は来週します。