UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する Inventory Systemの改善part2

<前文>

f:id:kazuhironagai77:20200119205409p:plain

先週、英語の話を書いたので今週も英語について書きます。最近、英訳してくれと頼まれた文章の中に「それはオブジェクトにx軸周りの45度の回転を加えます。」みたいな文章があったのですが、

It rotates an object 45 degrees around the x axis.

と訳しました。しかし結構学術的な文章の一文だったので訳ももっと厳密にする必要があるかもと思い、後で調べました。そしたら勿論上記のような書き方をしている文章も多く見つかりましたが、それ以外にも以下の書き方をしている場合も見つかりました。

  1. It rotates an object by 45 degrees around the x axis.
  2. It rotates an object 45 degrees about the x axis.
  3. It rotates an object around the x axis 45 degrees.

1番目の例はbyを45 degreesの前に使用しています。まずどっちが正しいのかが分からないです。両方正しいとしたらそれぞれのニュアンスの違いが分からないです。エンジニアと普通の人で意味が違う場合があるのかも分からないです。イギリス英語とアメリカ英語で違うかもしれないがそれも分からないです。全く分からなかったです。

2番目の例はaroundの代わりにaboutを使用しています。これは割かし分かりました。まず昔はaroundは間違いでaboutが正解だったのですが、現在はどっちも正解と見なしているそうです。ただし数学では厳密な定義があるのはaboutのみで論文にはaroundを使用すべきではないと言う意見もありました。さらに自転する時はabout、公転する時はaroundのイメージがあると証言する人もいました。コンピュターサイエンスではaroundを使用するのが主流のようでした。

3番目の例も1番目の例と同じでほとんど分からなかったです。

結論は、結局分かりませんでした。と情けない結果になってしまいました。

まあ、しょうがないですね。

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

<本文>

今週もinventory systemの改善を行います。

道具の要素にイメージの追加

無料でインストールしたInventory Systemではそれぞれの道具にイメージの要素がありました。

f:id:kazuhironagai77:20200119205615p:plain

Building an RPG with Unreal 4.x の道具にもイメージの要素を追加したいと思います。

Inventory systemを開くと道具のイメージにはTexture2Dクラスが使用されています。

f:id:kazuhironagai77:20200119205839p:plain

ここに公式のAPIがありました。

f:id:kazuhironagai77:20200119205903p:plain

こいつをItemData.hに追加します。

f:id:kazuhironagai77:20200119205922p:plain

f:id:kazuhironagai77:20200119205931p:plain

ビルドします。

エラーになりました。理由は以下の通りです。

f:id:kazuhironagai77:20200119210024p:plain
直しました。

f:id:kazuhironagai77:20200119210040p:plain

もう一度ビルドします。

f:id:kazuhironagai77:20200119210057p:plain

今度は成功しました。

うーん。

UTexture2Dはポインターが必須みたいです。ここでもポインターを使用してますね。

f:id:kazuhironagai77:20200119210121p:plain

これで、Items_Shopを開いて見ると

f:id:kazuhironagai77:20200119210145p:plain

あれ、ToolImageはありません。何で?

ItemsDataから新しくDataTableを作成してみると、

f:id:kazuhironagai77:20200119210222p:plain

今度のはToolImageがありました。

念のためUE4を再起動してみました。

f:id:kazuhironagai77:20200119210242p:plain

再起動したら、Items_ShopにToolImageが出来ていました。

取りあえず、200pxx200pxで道具のイラストを作成します。

f:id:kazuhironagai77:20200119210302p:plain

f:id:kazuhironagai77:20200119210313p:plain

こんな感じで追加しました。

どうせ追加したのですから、表示したいですね。

ボタンのイメージにでも追加しますか。

うーん。出来ませんでした。

f:id:kazuhironagai77:20200119210334p:plain

ボタンのイメージにアクセス出来ませんね。ひょっとしたらUE4C++からなら出来るんかもしれませんが。今回は諦めます。

それてボタンの上をマウスでホバーしたらWidgetを表示するようにしてそのWidget内に道具のイメージを表示する事にします。

f:id:kazuhironagai77:20200119210353p:plain

こんな風なWidgetを作成しました。白い部分に道具のイメージが表示されるようにします。名前は、DisplayToolImageにしました。

まず、ItemNameと言う変数をTextから作成しました。

f:id:kazuhironagai77:20200119210430p:plain

Itemのウィジェットでマウスがホバーした時に、このウィジェットは作成されます。その時に、ItemNameにItemの変数であるItemの値をパスします。

f:id:kazuhironagai77:20200119210451p:plain

DisplayToolImageウィジェット内のイメージを選択してBrushのバインドをクリックしてイメージを表示する関数を作成します。関数の名前はAddToolImageにしました。

f:id:kazuhironagai77:20200119210514p:plain

以下のように作成しました。

f:id:kazuhironagai77:20200119210556p:plain

Item_Shopに保持されているイメージのタイプはTexture2Dですが、表示するためのイメージのタイプはImageです。そのまま繋いだら変換してくれませんでした。色々調べたら、SlateBrushノードを使用するとTextureからimageに変換出来るみたいな事が書かれていました。最初、Itemウィジェット内でしたのですが、エラーになってしまいました。理由は分かりませんが、DisplayToolImageウィジェット内からならエラーになりません。

テストします。

f:id:kazuhironagai77:20200119210616p:plain

f:id:kazuhironagai77:20200119210626p:plain

こんな感じで表示されます。

ちなみに道具袋を開いて、道具の上にマウスをホバーした場合、

f:id:kazuhironagai77:20200119210655p:plain

f:id:kazuhironagai77:20200119210704p:plain

こんな感じでした。

絵の下手さはともかく中々上手く出来ました。

道具の効果にHP以外も追加

先週、気が付いたのですが、道具を使用してもHP以外は回復しません。Itemウィジェットのブループリント内でMPを追加します。

f:id:kazuhironagai77:20200119210746p:plain

もうこの辺をどうやって作成したのか全く覚えていません。

まずHPの値を保持しているCharacter Targetが何者なのかから見ていきます。

同じItemウィジェット内に以下のコードがありました。

f:id:kazuhironagai77:20200119210808p:plain

ほうほう。RPGGameInstance内にある配列の一要素みたいですね。配列の名前はParty Membersですね。

C++のRPGGameInstance.hを開きます。

ありました。

f:id:kazuhironagai77:20200119210832p:plain

これは、UGameCharacterクラスから作成していますね。UGameCharacterクラスってなんでしたっけ。

f:id:kazuhironagai77:20200119210850p:plain

ありました。ヘッダーファイルを見てみると、

f:id:kazuhironagai77:20200119210909p:plain

こんな感じにキャラクターのパラメーターを指定するためのクラスでした。

RPGGameInstanceのInit()関数内の実装をみてみると

f:id:kazuhironagai77:20200119210934p:plain

PartyMemberはUGameCharacter クラスのメンバー関数であるCreateGameCharacter()関数を使用してPartyのメンバーを追加しています。

CreateGameCharacter()関数では、

f:id:kazuhironagai77:20200119211022p:plain

キャラクターのパラメーターが実際に作成されていました。

大体全体の構造が分かりました。どうやら、Item内のブループリントにMPのための道具を追加すればいいだけみたいです。

f:id:kazuhironagai77:20200119211045p:plain

こんな感じでHPの計算した後に全く同じ方法でMPを計算しました。

テストします。

f:id:kazuhironagai77:20200119211209p:plain

う。レベルが表示されていませんね。後で直します。

まず、回復薬を使用します。

f:id:kazuhironagai77:20200119211232p:plain

20ほど回復しました。いいですね。更に回復薬を使用します。

f:id:kazuhironagai77:20200119211254p:plain

あれ、何で101.100で終わるはずですが。まあいいです。

f:id:kazuhironagai77:20200119211321p:plain

ああ。回復薬を使用した場合、道具の絵が消えていない。

f:id:kazuhironagai77:20200119211348p:plain

これを道具を使用した場合に追加しました。

f:id:kazuhironagai77:20200119211424p:plain

f:id:kazuhironagai77:20200119211432p:plain

今度は使用した瞬間に道具の絵は消えました。

ちょっと横道に逸れてしまいましたが、今度こそイーサーを使用してMPが回復するか試します。

MPが回復するか試すにはまず、MPを減らさないといけないので、こんな道具を作成しました。

f:id:kazuhironagai77:20200119211506p:plain

魔力消費薬を使用したらMPが50に減りました。

f:id:kazuhironagai77:20200119211528p:plain

ここで、イーサーを使用します。

f:id:kazuhironagai77:20200119211546p:plain

MPが回復しました。

もう一回使用します。

f:id:kazuhironagai77:20200119211614p:plain

更にMPが20回復しました。

もう一回使用します。

f:id:kazuhironagai77:20200119211633p:plain

最大値まで回復しました。

もう一回使用します。

f:id:kazuhironagai77:20200119211651p:plain

今度はMPは変化しません。完璧ですね。

ついでにレベルが表示されないバグも直します。

Pause_Inventoryウィジェットを開くとそもそもLvl.の後にTextがありませんでした。

f:id:kazuhironagai77:20200119211712p:plain

ので作成し、そのTextに以下の関数をバインドしました。

f:id:kazuhironagai77:20200119211731p:plain

はい。レベルが表示されるようになりました。

f:id:kazuhironagai77:20200119211749p:plain

同様に、装備画面も直しておきます。

f:id:kazuhironagai77:20200119211807p:plain

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

ワープしても所有している道具が消えないようにする。

もうこれは、単純にデータをGameInstanceに保存するだけです。

プレイヤーがコントロールするキャラクターが保持する道具のデータはFieldPlayerクラスにある変数、arrayItemに保持されています。

f:id:kazuhironagai77:20200119211846p:plain

ワープする前に、このデータをMyRPGGameInstanceBPに保存します。

そのための変数をMyRPGGameInstanceBP内に作成します。

f:id:kazuhironagai77:20200119211907p:plain

FieldPlayerクラスのEvent press Mの最後でarrayItemをMyRPGGameInstanceBP 内のItemsDataにコピーします。

f:id:kazuhironagai77:20200119211925p:plain

f:id:kazuhironagai77:20200119211932p:plain

そしてFieldPlayerクラスのEvent BeginPlayの最後でMyRPGGameInstanceBP 内のItemsData のデータをArrayItemにコピーします。

f:id:kazuhironagai77:20200119211954p:plain

f:id:kazuhironagai77:20200119212003p:plain

これでワープしても所有する道具のデータは消えないはずです。

テストします。

f:id:kazuhironagai77:20200119212023p:plain

現在、道具袋には、回復薬、イーサー、魔力消費薬があります。

ワープします。

f:id:kazuhironagai77:20200119212040p:plain

ワープした後も道具は消えませんでした。

<感想とまとめ>

今週はかけた時間が少ない割には、結構、進みました。理由の一つはブループリントを活用し始めたからだと思います。今までは、プログラマーなんだからブループリントしか使えないのは恥ずかしいと常に思っていたのでどうしてもUE4C++に重点をおいて勉強してしまっていましたが、もうUE4C++とブループリントの関係がはっきり理解出来たので、ブループリントを使用する事に抵抗がなくなりました。

もう一つは、アイデアに対する評価方法を変えたからだと思います。アイデアそのものに対して評価を下すと、ほとんどのアイデアは下らないとなりますが、それは間違っていたと先週気が付きました。アイデアそのものを評価してはいけなかったのです。アイデアは発展させるものだったんです。ので、今週は思いついた事はどんどん実行しました。その結果沢山の事をいつもより短い時間で終わらせる事が出来ました。

来週は用事があるのでお休みします。再来週から再開します。