UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 教科書のサンプルをもう一度作成する

f:id:kazuhironagai77:20200712210833p:plain

<前文>

高齢者ビジネスとコロナ共生時代

スシロー、ハズキルーペ、そしてポケモンGoは意図しているのか偶然かは分かりませんが、高齢者向けの商品を開発して大成功した例と考えています。ハズキルーペポケモンGoはまあ分かるとして何でスシローが高齢者ビジネスなの?と思うかも知れませんが、スシローの寿司は他の回転ずしと比べて小さいんです。歯が悪くなっている高齢者でも食べ易いんです。

ドローン(Drone)、VR、そして機械学習は今から4,5年前にこれから成功すると言われたIT関連の技術です。今これらの技術を見てみるとドローン(drone)は大成功、VRは完全な失敗、機械学習は引き分けですかね。これドローンは高齢者でも操縦したりドローンからの映像を録画したり出来るのに対してVR機械学習は高齢者を全く無視しているんです。特にVRは酔いを無視し過ぎていて体が弱くなった高齢者が使用したら大変な事になる仕様です。

何でこんな事を言っているのかと言うと、これから日本で成功するビジネスは全部、高齢者向けのサービスだと思っているからです。

そしてコロナ共生時代です。コロナによって変化した社会と高齢者の組み合わせがどんなニーズを生み出すのでしょうか?コロナも一部の人が予測したような悲惨な結果には成らなそうですが梅雨が来ても収束していないと言う事は、コロナと共生して生きていかなければならない新しい時代が来た事を示しています。これはこれから社会が大変化する事を示しています。社会が大変化するに従って多くの経済的な敗者を作り出しますが、その引き換えに次の時代の支配階級になる大きな勝者も生み出す事でしょう。

ではIT関連ではどんなビジネスが来るのでしょうか?

現時点でも判明しているのは、コロナ共生時代では在宅勤務は増えると言う事です。これは体力のない高齢者にはありがたい事でもあるので、加速度的に在宅勤務は増えると思われます。そうなるとIOTを使用して自宅に居なくても携帯で〇〇が出来る様な技術よりも自宅に居ながら○○が出来る様な技術が必要になるとかと思います。自宅と自宅でデータのやり取りをするのですから通信の秘密の保証は絶対必要でしょう。更に通信量自体も爆発的に増える事が予測されます。これらに関連した技術を持つビジネスは絶対伸びるでしょうね。

ネットにおける売買も今より更に活発になるでしょう。今、アメリカではGoogleやアップルに取られるアプリの手数料が高すぎるとして、そのアプリを制作した会社が自社のホームページ上で手数料を差し引いた値段で全く同じアプリが買えるようなって来ているそうです。中小企業が楽天やアマゾンに出店して販売するだけでなく、更に自分たちのウェブサイトから直接、商品を販売する事で手数料の分だけ安く販売する形態は日本でも増えそうです。となると物品の売買が出来るwebの制作依頼は増加しそうですね。ただ高齢者が今までオンラインショッピングのやり方で買い物が出来るかどうかかなり疑問でアマゾンのワンクリックみたいな新しい技術が必要になって来るかも知れません。

ゲームも高齢者向けのゲームが主流になるでしょう。それがどんなものか分かりませんが、在宅勤務が主流になる社会では携帯でやるゲームは今ほど盛んにはならないでしょう。

このテーマはまだまだ深堀り出来そうですね。しかし今週はこの位にして勉強を始めましょう。

<本文>

今週は、教科書のサンプルで作成されている機能をch4_3にどんどん追加していきます。

色々考えたんですが、教科書通りにまず作成します。その後で自分で改良した部分を、ブログを見ながら直していきます。この方法が一番速いし簡単だと思います。

1. ポーズメニューの追加

1.1  ポーズメニューの作成

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

f:id:kazuhironagai77:20200712210930p:plain

教科書でやった事の取りこぼしがないかどうかの確認だけなので、どんどん先に行きます。

1.2 Inventory サブメニューの作成

こんな感じに作成しました。

f:id:kazuhironagai77:20200712210952p:plain

1.3 Equipment サブメニューの作成

Weapon とarmorにborderを使用しています。

f:id:kazuhironagai77:20200712211019p:plain

1.4 Key のバインド

以下に示したコードをThirdPersonCharacterのBPに実装しました。

f:id:kazuhironagai77:20200712211041p:plain

このコードは後で、RPGGameModeBaseBPに移すと思います。更に戦闘中にはPause出来ないような設定も追加します。

1.5  Pause_Mainのボタンに機能を追加する

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

f:id:kazuhironagai77:20200712211103p:plain

f:id:kazuhironagai77:20200712211111p:plain

f:id:kazuhironagai77:20200712211118p:plain

このやり方だとpause 画面からプレイ画面に戻った時、カーソルが表示されたままですが、良いんでしょうか?

それはともかくとして簡単ですね。眠くなりそうです。

f:id:kazuhironagai77:20200712211137p:plain

やっぱりcursorは消せと書かれていました。消します。

f:id:kazuhironagai77:20200712211155p:plain

テストします。

全部正常に動きました。簡単過ぎるのでスクリーンショットは省略します。

2.ポーズメニューにキャラの状態を表示させる。

教科書見る前に自分で考えてみます。まず以下に示したRPGGameInstanceクラスのMyYourHero変数にアクセスします。

f:id:kazuhironagai77:20200712211220p:plain

BlueprintReadOnlyなのでBPからのアクセスが可能なはずです。

アクセス方法はGetGameInstance -> cast to RPGGameInstanceです。

以下に示したようにGameCharacterクラスの変数、HP、MP、ATK、DEF、そしてXPはBlueprintReadWriteなのでBP側から読む事が出来ます。

f:id:kazuhironagai77:20200712211241p:plain

この値をPause_Mainのキャラの状態値に読み込ませます。

2.1 キャラのデータを得る

以下の方法で表示しました。

f:id:kazuhironagai77:20200712211302p:plain

f:id:kazuhironagai77:20200712211309p:plain

教科書のやり方は私の想像したやり方とほぼ同じでした。一個だけ変更したのはCharacterTarget変数のassign方法だけです。PauseMainウィジェットを作成する時にassignしました。

教科書ではGameInstanceをRPGGameInstanceにcastしています。私はRPGGameInstanceBPにcastしました。

うーん。どっちがいいんでしょうか?

正直、分かりません。今回のケースではどちらでも必要な値にアクセス出来るので問題はないはずです。

2.2  他の状態値も値を表示させる

PauseMainのMP値は以下の方法で値が表示出来るようにします。

f:id:kazuhironagai77:20200712211340p:plain

Pause_Inventoryとpasue_equipmentの状態値も表示されるようにコードを実装します。

結果だけ以下に示します。

f:id:kazuhironagai77:20200712211416p:plain

f:id:kazuhironagai77:20200712211424p:plain

f:id:kazuhironagai77:20200712211436p:plain

教科書ではプレイヤーのキャラの状態値を保持する変数の名前をTargetCharacterと名付けているので、後になると何を指しているのか非常に分かりづらくなります。

TargetCharacterが指している値はRPGGameInstanceクラスのYourMyHero変数なのでTargetCharacterをYourMyHeroに変更します。ただしこれは教科書に書かれている内容を全部終わらしてからやります。

3NPCとセリフ

今度はNPCとそのセリフを作成します。

以下に示す道具屋と武器屋を作成するための土台部分の作成に当たります。

f:id:kazuhironagai77:20200712211513p:plain

どうやって作ったのかもう覚えていませんので、復習を兼ねて教科書に書かれているままに作成していきます。

3.1 NPC Character BPの作成

教科書のままに作成しました。

f:id:kazuhironagai77:20200712211536p:plain

Characterクラスから作成します。

f:id:kazuhironagai77:20200712211553p:plain

Boxを追加します。

f:id:kazuhironagai77:20200712211610p:plain

MeshにSK_MannequinをセットしてAnim ClassにThirdPerson_AnimBPをセットします。

f:id:kazuhironagai77:20200712211627p:plain

f:id:kazuhironagai77:20200712211635p:plain

見た目はかなり変ですが後でモデルは入れ替えるので、今回はこのままで行きます。

f:id:kazuhironagai77:20200712211705p:plain

スケルタルメッシュの設置やアニメーションの追加など、こっちが完全に理解している内容をやっているので滅茶苦茶簡単です。去年はほとんど理解しないでやっていたのであまり大きな口では言えませんが。

3.2 NPC との干渉

教科書ではUE4C++のPRGGameInstanceクラス内にBoolean変数であるTalkShopを作成し、NPCShopOwnerのBoxにPlayerの操作するキャラがOverlapしたらTalkShop変数がTrueに成るように作成します。そしてTalkShopがTrueの時にEを押すとNPCとの会話が出来るようになっています。

何で敢えてUE4C++にBoolean変数を作成する必要があるのかが不明ですが、更にその変数の管理をGameInstanceクラスに任せるのは更に不明です。このBoolean変数をどこで管理するかは後でしっかり考察します。

今週は教科書に書かれているままに作成します。

f:id:kazuhironagai77:20200712211733p:plain

ビルドします。

f:id:kazuhironagai77:20200712211751p:plain

成功しました。

変数一個追加したぐらいで大袈裟かもしれませんが、久しぶりにUE4C++側をいじったのでちょっと緊張しながらやりました。

NPCShopOwnerのBoxにPlayerの操作するキャラがOverlapしたらTalkShop変数がTrueに、Overlapしなくなったらfalseになるように実装します。

f:id:kazuhironagai77:20200712211809p:plain

OverlapしているactorがThirdPersonCharacterでない場合はTalkShopはTrueにはなりません。そんくらいですかね。このコードで重要なのは。

LevelのBP内で以下のコードを実装します。

f:id:kazuhironagai77:20200712211825p:plain

もしNPCのbox内にプレイヤーが操作するキャラがいると、Eを押すとHelloが表示されます。

何故、この部分の実装をLevelBP内でするのでしょうか?別なBPで実装した方がいい気がします。これは後で考察します。

テストします。

f:id:kazuhironagai77:20200712211842p:plain

されました。

f:id:kazuhironagai77:20200712211900p:plain

一応確認のために、NPCのBox外でEを押してみました。この時はHelloは表示されませんでした。

成功ですね。

3.3 セリフ用のボックスの作成

セリフ用のボックスって一体何?と思ったら、これの事でした。

f:id:kazuhironagai77:20200712211940p:plain

それでは作って行きます。

f:id:kazuhironagai77:20200712211956p:plain

NPC_dialogクラスをUserWidgetクラスから作成しました。

NPCDialogを作成しました。

f:id:kazuhironagai77:20200712212014p:plain

NPC_Parentクラスを親クラスとするDialogBoxクラスを作成します。

f:id:kazuhironagai77:20200712212041p:plain

f:id:kazuhironagai77:20200712212053p:plain

ここまで、これから先の実装は次の節でやるそうです。

3.4 Welcomeボックスの作成

Shop_WelcomeウィジェットをDialogBoxを複製して作成します。

f:id:kazuhironagai77:20200712212119p:plain

f:id:kazuhironagai77:20200712212126p:plain

以下に示したようにTextBlock_DialogBox内にセリフが表示されるように実装しました。

f:id:kazuhironagai77:20200712212147p:plain

このNPCのボックス内にプレイヤーが操作するキャラがいる時にEを押した場合、Shop_Welcomeウィジェットが表示されるようにします。

f:id:kazuhironagai77:20200712212222p:plain

テストします。

f:id:kazuhironagai77:20200712212242p:plain

表示はされましたが、一々マウスの動きに合わせて視点が激しく動きます。見にくいです。

余りにも見にくいので、SetGamePausedをTrueで追加しました。

f:id:kazuhironagai77:20200712212322p:plain

更にExitを押した時、

f:id:kazuhironagai77:20200712212345p:plain

GamePausedを解除してMouseのCursorを消しました。

f:id:kazuhironagai77:20200712212429p:plain

大分見やすくなりました。

3.5 NPC会話ボックスを追加します。

Shop_TalkをDialogBoxを複製して作成します。

f:id:kazuhironagai77:20200712212458p:plain

中身は全く一緒です。

f:id:kazuhironagai77:20200712212518p:plain

テキストはNPCDialogの0に保存されている文章を表示します。

f:id:kazuhironagai77:20200712212539p:plain

Shop_welcomeウィジェットTalkをクリックした時にShop_Talkウィジェットが開くようにします。

f:id:kazuhironagai77:20200712212604p:plain

Shop_talkのExitボタンがクリックされた時は以下に示したように実装しました。

f:id:kazuhironagai77:20200712212635p:plain

最後に表示される文字がはみ出さない様にAuto Wrap Textにチェックを入れました。

f:id:kazuhironagai77:20200712212709p:plain

テストします。

Talkをクリックすると以下のウィジェットが表示されました。

f:id:kazuhironagai77:20200712212733p:plain

更にExitをクリックすると

f:id:kazuhironagai77:20200712212752p:plain

普通の画面に戻りました。

3.金貨、アイテムそしてショップ

ショップでアイテムを買えるようにします。

3.1 金貨のインスタンスとセッター、ゲッター

ショップで買い物が出来るためには、最初にお金を作る必要があります。金貨を作成します。

最初にモンスターを倒した時に手に入る金貨を設定するためにEnemyMonsterInfoクラスに変数、Goldを追加します。

f:id:kazuhironagai77:20200712212841p:plain

既に作成されていました。

今度はGameCharacterクラスに変数、Goldを追加します。

f:id:kazuhironagai77:20200712212902p:plain

GameCharacterクラスにはGold変数はないので追加します。

f:id:kazuhironagai77:20200712212918p:plain

念のためにビルドもしましたが、大丈夫でした。

GameCharacterクラスはCH2のGameCharacterクラスを元に作成していると思っていたのですが、何でGold変数を作成していなかったのか覚えていません。Ch4_3 のGameCharacterクラスにはGold変数がないので追加する以外の選択肢はないですが何か気になります。

f:id:kazuhironagai77:20200712213004p:plain

をCreateEnemyMonster()関数に追加します。

次に教科書ではCombatEngineクラス内に敵のモンスター全員の合計の金貨を表す変数、GoldTotalを作成しています。

f:id:kazuhironagai77:20200712213136p:plain

私のゲームでは敵は常に一体なのでこの部分はスキップします。

教科書では更に、保持している金貨の管理をGameInstanceクラスで行います。どうもこの教科書ではキャラクターは敵だけでなく味方も途中で交代する場合を考慮していてそのためにお金の管理はGameInstanceクラスで行うようにしたみたいです。

うーん。私、個人的にはお金の管理はそのキャラに任せるべきと思います。更に私のゲームではキャラは一体のみなので、敢えてGameInstanceクラス内に保持している金貨の管理を行う変数を作成する意味はないです。

取り敢えず教科書通りに作成して後で直します。

RPGGameInstanceクラスにGameGold変数を追加します。

f:id:kazuhironagai77:20200712213203p:plain

RPGGameModeBaseクラスのTick()関数内に以下のコードを追加します。

f:id:kazuhironagai77:20200712213229p:plain

これで戦闘に勝利するたびにRPGGameInstanceクラスの金貨を管理している変数GameGoldの値が増えるはずです。

f:id:kazuhironagai77:20200712213252p:plain

ビルドも成功しました。

今度はこのGameGoldの値をPauseMainウィジェットに表示させます。

f:id:kazuhironagai77:20200712213313p:plain

f:id:kazuhironagai77:20200712213320p:plain

テストします。

f:id:kazuhironagai77:20200712213340p:plain

戦闘に勝利したらGOLDが10増えました。

勿論ゴブリンが保持する金貨は10です。

f:id:kazuhironagai77:20200712213359p:plain

二回戦闘した場合は、金貨の数は20になっています。

f:id:kazuhironagai77:20200712213429p:plain

うん。出来ましたね。

3.2 アイテムのデータ

この部分は既に作成していました。のでスキップします。

3.3 ショップのスクリーンの作成

アイテムを買う時に使用するウィジェットを作成します。

f:id:kazuhironagai77:20200712213521p:plain

Shop_welcomeウィジェットのShopボタンをクリックしたらこのウィジェットが開くようにします。

f:id:kazuhironagai77:20200712213543p:plain

Exitボタンをクリックした時にこのウィジェットが閉じるようにします。

f:id:kazuhironagai77:20200712213602p:plain

当然、GamePausedを解除してMouse cursorを非表示にします。

最後にGOLDの値を表示するようにします。

f:id:kazuhironagai77:20200712213625p:plain

以上です。

テストも成功しました。

3.4 アイテムボタンのフレームワークの作成

最初に作成した時、この節の題であるThe Item button Frameworkの意味が全く分からなかったんですが、この場合のフレームワークとは、アイテム一個一個を表示するために使用するウィジェットの事を指しています。

UE4WidgetBlueprintはWidgetBlueprintからWidgetBlueprintを呼べるためにそう言う事が出来ます。

f:id:kazuhironagai77:20200712213656p:plain

f:id:kazuhironagai77:20200712213705p:plain

このフレームワークではCanvasPanelは使用していませんが、CanvasPanelを使用した方が制約も付きますが、複雑な構造も作成出来ます。

f:id:kazuhironagai77:20200712213727p:plain

教科書の図ではItem変数はarrayのように見えたんですが、arrayにする必要はありませんのでしませんでした。

3.5 アイテムデータのリンク

3.4で作成したウィジェットItemをウィジェットshopのスクロールボックス内に表示されるように実装します。

f:id:kazuhironagai77:20200712213759p:plain

このやり方は散々勉強しました。ここで更に復習する必要はないでしょう。

テストをすると以下に示した図が表示されました。

f:id:kazuhironagai77:20200712213823p:plain

4.まとめと感想

教科書の内容は今週で全部やる予定でしたが、量的にちょっと無理なので来週もやる事に変更しました。今丁度半分終わったところです。