UE4の勉強記録

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

「Unreal Engine4.xを使用してRPGを作成する」の7章、ゴールド、アイテム、そして店 (Gold, Items, and a Shop)を勉強する。

<前文>

f:id:kazuhironagai77:20190804200002p:plain

<本文>

<目的>

7章、ゴールド、アイテム、そして店 (Gold, Items, and a Shop)を勉強します。

  • NPCを店主として使用します。
  • ユーザーが買えるアイテムを表示します。
  • ユーザーはアイテムを買うための通貨が必要です。
  • 以下のトピックをこの章ではカバーします。
    1. ゴールドのインスタンスをゲットする事とセットする事
    2. アイテムのデータ
    3. 店のスクリーンのフレームワーク
    4. アイテムのボタンのフレームワーク
    5. アイテムのデータのリンク

とありました。どんどんやって行きましょう。

<方法と結果>

<Step.0>

まず、サンプルコードのChapter7を解凍します。

f:id:kazuhironagai77:20190901192850p:plain

普通に解凍出来ました。先週、間違ってビデオカードのドライバーを消してしまい、危うくPCが壊れるくらいCPUの温度が上昇した事があったのですが、UE4には何の影響もなさそうですね。

前回と同じように、Ch2を使用してやっていきます。

<Step.1>

ゴールドのインスタンスをゲットする事とセットする事(Setting and getting gold instances)

  1. まずショッピングのインターフェイスを作成します。ショップボタンを通して、店内でアイテムを買うための通貨を引き出せるようにします。
  2. ゴールドは戦闘の終わりに敵が落とすようにします。ので敵のデータのプレイヤーが得る事の出来るゴールドのデータが必要です。
  3. 4, Pause Menu Frameworkでゴールドのプレイスホルダーを持つポーズメニューを作成しました。のでゴールドをこのポーズメニューに追加しましょう。

はい。

ゴールドのプロパティをFEnemyInfo.hに追加します。

教科書に書かれている通りに追加します。

f:id:kazuhironagai77:20190901192931p:plain

しました。

  • 次に我々のゲームキャラクターのゴールドプロパティ(Gold property)を作成します。
  • hFEnemyInfo.hと同じように作成します。

f:id:kazuhironagai77:20190901193015p:plain

はい。追加しました。

<Step.2>

GameCharacter.cpp 内でEnemyInfoでセットした値と同じ値のGoldの返し値をセットします。

まず、教科書の説明通りにCreateGameCharacter(FEnemyInfo* enemyInfo…関数内でGoldに値をアサイン(assign)します。

f:id:kazuhironagai77:20190901193150p:plain

<Step.3>

  • 何時ゴールドを追加するか選ばなけらばなりません。
  • コンバットからにします。
  • hを開き、バトルで獲得した全てのゴールドを保持するためのgold変数を作成します。

f:id:kazuhironagai77:20190901193242p:plain

作成しました。

<Step.4>

  • 次のステップはエンジンにいつゴールドをプレイヤーに渡すのかをエンジンに告げる事です。
  • cppを開き、勝利をチェックするために3Exploration and Combatで作成したループまでスクロールします。
  • そこにGold を宣言します。
  • そして0をセットします。

f:id:kazuhironagai77:20190901193319p:plain

はい。変数Goldを追加し0で初期化しました。

<Step.5>

  • もしプレイヤーが勝利しないで戦闘をする必要がある場合戦闘で得られるゴールドは0にセットされます。
  • 次に、全ての殺した敵からゴールドを集めます。のでループ内でそれぞれの敵のゴールドをGold変数に足していきます。

f:id:kazuhironagai77:20190901193359p:plain

となりました。

<Step.6>

  • ループが終了した後に、敵のパーティが全滅したかどうかをチェックする必要があります。
  • もし敵のパーティが全滅した場合は戦闘に勝利したので、ループで足したゴールドを獲得します。
  • 獲得したゴールドは単純にGoldTotalに追加されます。

f:id:kazuhironagai77:20190901193440p:plain

追加しました。

<Step.7>

  • 次にする事はゴールドをゲームデータに追加する事です。
  • もっと詳しく言えばゴールドをhに追加する事です。

f:id:kazuhironagai77:20190901193544p:plain

しました。

<Step.8>

  • 次に、勝利の条件とゲームオーバーの論理を作成したcppファイルに行ってGameGoldインスタンスを作成します。
  • 勝利の条件内にgameInstanceを呼ぶURPGGInstanceへのポインターを作成します。
  • そしてそれをGetGameInstanceへキャストしてイコールします。

一寸、英文が何を言いたいのか分からない部分がありましたが、コードを見ながらやって行けば大丈夫でしょう。

f:id:kazuhironagai77:20190901193642p:plain

これを作成する事を説明していたみたいですね。

説明通りにRPGGameMode.cppを開いて戦闘の勝利の箇所に上記のコードを追加します。

f:id:kazuhironagai77:20190901193700p:plain

しました。

<Step.9>

このGameInstanceを使用して戦闘から得たトータルゴールドをGameGoldに追加します。

f:id:kazuhironagai77:20190901193735p:plain

しました。

<Step.10>

この時点でコンパイルするか確認して下さい。

はい。

f:id:kazuhironagai77:20190901193819p:plain

成功しました。

<Step.11>

  • 敵のデータテーブルからそれぞれの敵のキャラクターのゴールドの価値を調節出来るようになりました。
  • 敵のデータテーブルを見るとGoldの列がみれるはずです。
  • Goldの列に好きな値を追加してデータテーブルをセーブしてください。

データテーブルのEnemiesを開いて見ると以下に示すように確かにGoldが追加されています。Goldの値を10に変更しセーブしました。(ついでにMHPの値も2に変更しました。)

f:id:kazuhironagai77:20190901193903p:plain

<Step.12>

  • もしプレイヤーが戦闘で買ったら手に入る金に変換されたリアルな価値が敵の情報に付いています。
  • 次にポーズメニューそのGoldを表示する必要があります。

ポーズメニューのGoldにGameInstanceのGameGoldが表示されるように以下に示すようにブループリントを組みました。

f:id:kazuhironagai77:20190901193936p:plain

以下に示す教科書の参考と全く同じです。問題ないですね。

f:id:kazuhironagai77:20190901194003p:plain

<Step.13>

アイテムのデータ(Item data)

  • お店を作成する前にもう一つ作成しなければならない物があります。アイテムです。
  • データテーブルを使用してアイテムの状態とインベントリーを管理するのが一番楽です。
  • なので、まず、前に作成したCharacterInfoの構造体に似た、新しいC++のFTableRowBaseの構造体を作成します。
  • hとItemData.cppと呼びます。

まず、FTableRowBase 構造体を親に持つItemsData.hとItemData.cppをSource | RPG | Dataのフォルダー内に、CharacterInfoの構造体を作成した時と同じように作成してください。とあります。

もう作り方忘れちゃったよ。と思いましたが、良く考えたら自分のブログに詳しいCharacterInfoの構造体の作成手順が残っているはずです。2019-05-19のブログにCharacterInfoの構造体の作成方法が書かれていました。

読んだら、Dataフォルダーは作成しないでCharacterInfoの構造体の構造体を作成していますね。ちょっと教科書のやり方とは違いますが2019-05-19のブログのやり方で作成します。

f:id:kazuhironagai77:20190901194104p:plain

まず、C++の親にObjectを選択します。

f:id:kazuhironagai77:20190901194122p:plain

名前をItemsDataにします。PathはDataフォルダーを作成していないので、そのままです。

以下に示したようにItemsData.hが出来ました。

f:id:kazuhironagai77:20190901194142p:plain

教科書の説明に基づいて以下に示すように変数を宣言しました。

f:id:kazuhironagai77:20190901194210p:plain

f:id:kazuhironagai77:20190901194219p:plain

ビルドしてみます。

f:id:kazuhironagai77:20190901194236p:plain

あっけなく成功してたと思ったらクラッシュしました。

Ch2プロジェクトをもう一度開いてビルドしましたが

f:id:kazuhironagai77:20190901194309p:plain

問題ないみたいです。今度はクラッシュもしません。2019-05-19のブログにも最初にCharacterInfoを作成した時にクラッシュしたと書かれていました。

2019-05-19のブログではVSをリフレッシュしたと書いていたので、一応VSをリフレッシュしておきます。

自画自賛になりますが、2019-05-19のブログのおかげでItemsData.hを簡単に作成する事が出来ました。やっぱりブログに記録しておくことは大事ですね。

<Step.14>

ItemsDataから店のためのデータテーブルを作成します。

Items_Shopと名付けます。

f:id:kazuhironagai77:20190901194350p:plain

アイテムとしてpotionを作成します。

f:id:kazuhironagai77:20190901194418p:plain

<Step.15>

店のスクリーンのフレームワーク(The shop screen framework)

店のスクリーンのフレームワークとは一体何でしょうかね。全く分からないですね。まず教科書を読んでみます。

  • 前章でダイアログボックスを店主のために作成しました。ダイアログボックスの一つにShopボタンを作成しました。
  • そのボタンをクリックするとショップメニューが開きます。
  • まず、このショップメニューを作成しましょう。

どうやらショップメニューの事のようですね。それではやって行きます。

Content | Blueprints | UI | NPCフォルダーにShopと言う名前の新しいウィジェットブループリントを作成します。

f:id:kazuhironagai77:20190901194535p:plain

f:id:kazuhironagai77:20190901194544p:plain

出来ましたが、位置は滅茶苦茶ですね。ウーン。何か特別なやり方があるのでしょうか。今回はウィジェットの数が少ないので一個ずつ手動で直していきます。

f:id:kazuhironagai77:20190901194609p:plain

直しました。

<Step.17>

次にPause_InventoryウィジェットブループリントからScrollBox_InventoryTitle_Inventoryをコピーペイストします。

f:id:kazuhironagai77:20190901194649p:plain

f:id:kazuhironagai77:20190901194658p:plain

ShopウィジェットブループリントにPause_InventoryウィジェットブループリントのScrollBox_InventoryとTitle_Inventoryを追加しました。

  • InventoryをShopに変更します。

f:id:kazuhironagai77:20190901194748p:plain

<Step.18>

f:id:kazuhironagai77:20190901194840p:plain

しました。

テストします。

f:id:kazuhironagai77:20190901194912p:plain

Shopをクリックします。

f:id:kazuhironagai77:20190901194935p:plain

Shopブループリントが開きました。

開きましたがExitボタンを押しても閉じません。

取りあえずこの問題は無視して教科書の指示に従って進めます。最後までこのExitボタンを直さない場合はその時に自分で直します。

<Step.19>

Gold数を画面に表示出来る様にします。

f:id:kazuhironagai77:20190901195011p:plain

しました。

f:id:kazuhironagai77:20190901195038p:plain

今度はGoldの値が表示されています。

<Step.20>

次にButton_Exitの機能を追加します。

ここでExitボタンの機能を追加するのですね。

f:id:kazuhironagai77:20190901195111p:plain

これだけで良かったのでしょうか?マウスのカーソルとかの後処理なんかいらないのでしょうか?

<Step.21>

アイテムボタンのフレームワーク(The item button framework)

今度はアイテムボタンのウィジェットを作成するのでしょうか?

  • アイテムをこのShopにリンクする前に、アイテムを店内に配置するためのフレームワークを作成する必要があります。
  • まず、店主が売っているそれぞれのアイテムのためのボタンを作成したいです。
  • ただしNPCらがスケールの違うアイテムを持つ事が出来るようなスケーラブルなインターフェイスを作成するためには、そのアイテムのテキスト/説明のためのデファルトな値を持つ一個のボタンを持つスクロールボックスフレームワークを作成するほうが賢いです。
  • そうする事で、店主が持つ沢山のアイテムのためのボタンを動的に描き、更にそれぞれのボタンのテキストを動的に描く事が出来ます。

うん。大体そうみたいですね。

まずItemと言う名前のウィジェットブループリントを作成します。

f:id:kazuhironagai77:20190901195220p:plain

作成しました。

その後の指示に従ってItem内にボタンを作成します。

f:id:kazuhironagai77:20190901195252p:plain

f:id:kazuhironagai77:20190901195259p:plain

Canvasを削除してボタンを追加しました。

f:id:kazuhironagai77:20190901195317p:plain

ボタン内のテキストにテキストタイプの変数であるItemをバインドしました。

<Step.22>

アイテムのデータのリンク(Linking the item data)

  • アイテムボタンフレームワークを使用してアイテムデータと店をリンクします。
  • そのために、アイテムボタンフレームワークを使用してItem_Shopのデータテーブル内のそれぞれのアイテムを表示するための機能を追加します。

もう教科書に書かれたままに作成しました。

f:id:kazuhironagai77:20190901195415p:plain

ちょっと良く分からない箇所もありますが、多分大丈夫でしょう。(これだとアイテムの名前しかパスしていないように思えます。)

テストしてみます。

f:id:kazuhironagai77:20190901195432p:plain

綺麗にPositionが表示されました。

これだけでは、勿体ないのでetherを作成して試してみます。

f:id:kazuhironagai77:20190901195459p:plain

f:id:kazuhironagai77:20190901195505p:plain

綺麗に表示されましたね。

<考察>

UEC++とは関係ないですが、ウィジェットブループリントから他のウィジェットブループリントを呼ぶ技術はカッコイイのでその辺を考察してみたいです。

f:id:kazuhironagai77:20190901195543p:plain

まず、AddChildノードを使用しています。これがウィジェットブループリントから他のウィジェットブループリントを呼ぶためのノードですね。Targetに親ウィジェットブループリント内の子ウィジェットブループリントを表示したいウィジェット(この場合ScrollBox_Inventory)が接続されています。Contentの方は、子ウィジェットブループリントが接続されています。子ウィジェットブループリントのインスタンスはCreateWidgetノードで作成されています。

どうやってボタンのテキストに値をパスしているのか?と思ったら、以下に示すように予めItemと言う名の変数を作成していました。

f:id:kazuhironagai77:20190901195621p:plain

<感想など>

もう簡単な章しか残っていないと思っていたら7章は結構ボリュームがありました。勉強のし甲斐がありました。