UE4の勉強記録

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

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

f:id:kazuhironagai77:20200726221920p:plain

<前文>

UE4でゲームを作るための予備知識はどれくらい必要なのか?

そろそろUE4の勉強記録用のブログを始めて2年半が経ちます。私なりにUE4でゲームを制作するためどれぐらいの勉強が必要なのかとか、その前提としてどれくらいの知識があればUE4を勉強する事が可能なのかが分かって来ましたのでここにまとめようと思います。

まず、私が分かった中で非常に大切な事が、UE4の使用方法を理解する事とUE4を使用してゲームを作成する事は違うと言う事です。車の運転ならば、操作の仕方を覚えるのと路上で運転する事にそんなに違いはありません。しかしUE4は使用方法を覚えるのと実際にUE4を使用してゲームを作成する事には大きな違いがあります。UE4の使用方法を理解する事は割かし簡単で誰でも覚えられます。これは市販されているUE4の教科書を1,2冊勉強すればUE4C++は無理としてもBPとそれぞれの機能の使い方を覚える事は出来るはずです。しかしそれからどうやって自分が作りたいゲームを作成するのかが全く分からない状態になってしまいます。

結論から言えばC++C#のようなオブジェクト指向高級言語で、一からゲームを作れる能力がある人だけがUE4を使用する事でゲームを作成出来ると言う事です。UE4は結局は凄いLibraryでゲームをより速くより良く作る助けには成っても、元々コンピューターゲームを一から作成出来ない人が出来る様になる魔法の道具ではないと言う事です。

更に、数学と英語の問題もあります。仮想空間で3Dのオブジェクトを扱うには厳密に言えばlinear algebraの知識が必要です。UE4ではこれらの行列の計算はBPではノードの関数が行ってくれますが、ちょっと複雑になった場合、本当にこれらの数学の知識なしに望んだ結果が達成出来るのか疑問です。更にエラーが起きた時に解決方法を探す時など英語圏の情報を当たる必要もあり英語の能力もかなり要求されます。

これらから考えると、

1.英語圏の大学のcomputer scienceやcomputer engineering もしくはsoftware engineering の学士以上の学位を持つ人、

2.日本のトップレベルの大学(東大クラス)の情報科の学士以上の学位を持つ人(帰国子女であるとなお望ましい)、

3.日本の中堅レベルでしっかり教育するので有名な大学を優れた成績で卒業した後、理系の修士以上の学位を持ち、更にプログラミングを独自に勉強した人

もしくはそれと同等の非常に高い学力を持っている人だけが、UE4を使用してゲームの作成が出来ると言わざる得ません。かなり専門性の高いツールに当たると思います。

決してUE4を使用すればプラモデルを作成するようにゲームが作成出来る訳ではないと言う事です。

この辺をUE4でゲームの作成方法を教える教材は隠しています。まるで誰でもUE4を使用すればゲームが作れるように歌っています。これははっきり言って私は詐欺だと思います。誰でも出来るのはUE4の使い方を覚える所までです。それ以上は極一部の人だけが先に進めます。

その上でUE4でゲームを制作するためどれぐらいの勉強が必要なのかですが、アセットは全て購入する前提ですが、BPで作成するならば半年位だと思います。

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

<本文>

先週の続きをやって行きます。本来ならば1週間で教科書の内容は全部終わらせるつもりだったのですが、既に3週目です。今週中には終わらせたいです。

1. レベルアップ、アビリティそしてセーブ

1.1 経験値とレベル上げのためのコード

教科書では、CharacterClassInfoクラスにMXPとXP変数を追加しています。私のゲームではCharacterClassInfoクラスはYourHeroClassInfoクラスとEnemyMonsterInfoクラスに分けて作成されているのでそれぞれのケースで考えます。まずYourHeroClassInfoクラスの場合は、MXPもXPも要りません。最初のXPは0ですし、XPがHPやMPのように最大値から減る事もないからです。EnemyMonsterInfoクラスはそのモンスターを倒した時に得られるXPを決めるためにXP変数のみが必要になります。

そしてそれらの変数は以下に示したように既に作成されています。

f:id:kazuhironagai77:20200726222048p:plain

次にLVを表す変数ですが、これもYourHeroClassInfoクラスとEnemyMonsterInfoクラスには必要ないです。勿論、GameCharacterクラスで味方のキャラを作成する場合、以下に示すように

f:id:kazuhironagai77:20200726222110p:plain

LV変数を作成しますが、その値はキャラの作成時は常に1ですし、LVがMPやHPのように下がる事もありません。のでXPと同じ扱いで良いはずです。

既にGameCharacterクラスでもこれらの変数は追加されているのでここで新しく作成する必要はないです。

f:id:kazuhironagai77:20200726222131p:plain

f:id:kazuhironagai77:20200726222141p:plain

次にXPの計算をCombatEngineに追加します。

f:id:kazuhironagai77:20200726222208p:plain

ここは教科書とはかなりやり方が違いますが、私のゲームでは敵のモンスターは常に一体なのでこれでいいはずです。

この後、XPがいくつになったらLVが上がるのかについて考えなければなりません。しかし先にテストをします。

以下に示したようにプレイヤーが操作するキャラのXPをGを押す事で表示出来るようにします。

f:id:kazuhironagai77:20200726222228p:plain

ゴブリンとの戦闘後にGをおしてXPを確認すると

f:id:kazuhironagai77:20200726222245p:plain

と表示されます。

以下に示したように、ゴブリンのXPは50なので合っています。

f:id:kazuhironagai77:20200726222304p:plain

レベルアップなのですが、教科書では単にMXPを超えるとLVが上がる様に成っています。これは余りにも単純で作り直します。

まずTableRowBaseでsoldierのレベルアップ表を作るためのLevelDataを作成します。名前はLevelUpDataとします。

f:id:kazuhironagai77:20200726222322p:plain

ここで又、ULevelUpDataのままでビルドしてエラーになり慌てました。いつもこの部分を直す事を忘れてしまいます。

UE4エディターがクラッシュして再起動する処も同じです。

パラメーターは以下のようにしました。

f:id:kazuhironagai77:20200726222402p:plain

XPは次のレベルに必要なXPの値を表します。LVはそのままレベルを表します。MHPはそのレベルになった時に追加されるMHPの値を示しています。後に続くMMPなどのパラメーターも同じです。

f:id:kazuhironagai77:20200726222424p:plain

ここまで作成して気が付きましたがレベルアップした時に覚える魔法の欄がありませんでした。

作り直します。

f:id:kazuhironagai77:20200726222451p:plain

これを足しました。

うーん。そうすると今度はGameCharacterクラスにも使用出来る魔法の名前を保持する変数が必要になりますね。ただ今週は教科書の内容を終わらせるのが最優先なので、この問題は後で考える事にします。

まずはレベル挙げのためのコードを実装します。

f:id:kazuhironagai77:20200726222522p:plain

簡単に解説するとSoldierLevelUpのRowNameをLVと同じにする事でCharacterのLVからSoldierLevelUpのrowを呼び出せるようにしました。

f:id:kazuhironagai77:20200726222542p:plain

呼び足した後は、経験値が次のレベルに上がるのに十分かどうかチェックします。そしてレベルが上がる場合はそれぞれのパラメーターも上がります。データでは簡単にするために全部1上がるようにしました。

正しレベルの上限は10までで10以上は上がらないようにしました。

後は、経験値を大量に得てレベルが沢山上がる場合にも対応しました。

テスト結果も簡単に紹介します。

ゴブリンのXPを100に変更して一回だけ戦闘しました。レベルは3、MHPは102、MMPは2になるはずです。試しにPause画面を開いて見ると

f:id:kazuhironagai77:20200726222619p:plain

レベルはまだ表示出来るようにしていませんでした。が他の値は正しいのが確認出来ます。

このようなテストを何通りも行いましたが全部予測した結果になりました。

1.2 DataTableの初期値

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

1.3 レベルと経験値の表示

教科書を見ると以下のように表示されています。

f:id:kazuhironagai77:20200726222649p:plain

次のレベルを調べるのは結構大変なので、それ以外を表示させます。データの保存の仕方が既に教科書とは大分違うので自分で作成します。

f:id:kazuhironagai77:20200726222723p:plain

普通に作成しました。結果は以下に示しました。

f:id:kazuhironagai77:20200726222741p:plain

テストはまあ大丈夫でしょう。

1.4 戦闘で正確なダメ―ジを与える

今までは、戦闘では一律、10ポイントのダメ―ジを与えていましたが、それを正確なダメージを与える様にします。

f:id:kazuhironagai77:20200726222805p:plain

と言っても変更したのは、TestCombatActionクラスのBeginExecuteAction()関数のこの部分だけです。

一応テストはします。

うん。正常に動いているみたいです。

1.5 アビリティをセットします。

アビリティ自体を無くしてしまったのでこの部分と次の節は読むだけにします。

1.6 セーブとロード

この部分も自分で作成し直したいので後にします。

一応、これで教科書の内容が終わりました。

2. 直す部分のまとめ

3週間に渡って教科書の内容をch4_3に追加しました。その際に結構な数の問題が出て来ましたが後で直す事にしました。その後で直す箇所をまとめ直します。

先々週の部分

  • 戦闘中はPause出来ないようにする。
  • 教科書ではプレイヤーのキャラの状態値を保持する変数の名前をTargetCharacterと名付けているので、後になると何を指しているのか分かりづらいです。TargetCharacterが指している値はRPGGameInstanceクラスのYourMyHero変数なのでTargetCharacterYourMyHeroに変更します。
  • モデルの入れ替え
  • 教科書ではUE4C++PRGGameInstanceクラスにBoolean変数であるTalkShopを作成し、NPCShopOwnerBoxPlayerの操作するキャラがOverlapしたらTalkShop変数がTrueに成るように作成します。そしてTalkShopTrueの時にEを押すとNPCとの会話が出来るようになっています。何で敢えてUE4C++Boolean変数を作成する必要があるのかが不明ですが、更にその変数の管理をGameInstanceクラスに任せるのは更に不明です。このBoolean変数をどこで管理するかをしっかり考察します。
  • NPCbox内にプレイヤーが操作するキャラがいると、Eを押すとHelloが表示されます。この部分の実装をLevelBP内でしています。別なBPで実装した方がいい気がします。これを考察します。
  • お金の管理をRPGGameInstanceクラスにさせるのか、それともGameCharacterクラスにさせるのか?

先週の部分

  • アイテムを使用した時にHPしか影響されない。
  • 使用したアイテムが消滅しない。
  • 武器を装備した時のATKと外した時のATKの違いが分からない
  • 武器を選んでも防具を選んでも武器に装備される

今日の部分

  • GameCharacterクラスに使用可能な魔法の名前を保持するための変数を作成する。
  • セーブとロード機能の追加

以上です。

3. 直す

3.1 セーブの作成

SaveGameから新しいブループリントNewSaveGameを作成します。

f:id:kazuhironagai77:20200726222935p:plain

ここにRPGGameInstanceクラスの変数を作成します。

f:id:kazuhironagai77:20200726222954p:plain

これをPauseMainで

f:id:kazuhironagai77:20200726223012p:plain

とする事でセーブします。

3.2 ロードの作成

Start_Menuウィジェットを作成します。

f:id:kazuhironagai77:20200726223039p:plain

このLoadボタンを押した時にセーブしたデータをロードするようにします。

f:id:kazuhironagai77:20200726223107p:plain

どうやらGameInstanceは直接コピーする事は出来ないみたいですね。変数一個ずつコピーするしかないみたいです。

f:id:kazuhironagai77:20200726223133p:plain

ああ…。RPGGameInstanceの変数のほとんどはBPからいじれない設定にしていました。

これは、UE4C++から作成する方が良いですね。

ここにUE4C++からsaveGameを利用してデータをセーブしたりロードしたりする方法を説明した詳しいチュートリアルがありました。これを元にして作成します。

まず、SaveGameをPrivateで作成します。

f:id:kazuhironagai77:20200726223155p:plain

多分privateで大丈夫でしょう。

f:id:kazuhironagai77:20200726223211p:plain

f:id:kazuhironagai77:20200726223219p:plain

で、色々試したんですが、RPGGameInstanceそのものをセーブしても、shallow copyみたいな状態になってRPGGameInstanceのそれぞれのオブジェクトが持つ変数の値まで保持してくれないみたいで、仕方ないのでセーブしたい変数の値は全てここに作成する事にしました。

取りあえず、GameGoldで試します。

f:id:kazuhironagai77:20200726223252p:plain

f:id:kazuhironagai77:20200726223300p:plain

f:id:kazuhironagai77:20200726223307p:plain

f:id:kazuhironagai77:20200726223318p:plain

これでセーブとロードが出来るはずです。
試してみます。
2回戦闘してGoldを20貯めました。

f:id:kazuhironagai77:20200726223339p:plain

セーブしました。ゲームを一回終了します。

もう一度ゲームを開始してLoadを選択します。

f:id:kazuhironagai77:20200726223356p:plain

Pauseを開くとGOLDが20になっていました。

f:id:kazuhironagai77:20200726223413p:plain

今度は、NewGameをクリックします。

Pauseを開くとGOLDは0のままです。

f:id:kazuhironagai77:20200726223429p:plain

出来てますね。

追記* GameInstanceクラスの変数や関数を追加した時にGameInstanceBPを作り直す必要がありました。これをしないとエラーになりました

残りはアイテムや武具を保持した状態になってからじゃないと作成出来ないのでここで中止して後でやります。

3.3 GameCharacterクラスに使用可能な魔法の名前を保持するための変数を作成する。

追加しました。

f:id:kazuhironagai77:20200726223504p:plain

レベルが上がった時は以下に示した方法で魔法を追加します。

f:id:kazuhironagai77:20200726223532p:plain

テストします。
以下の方法で、Magicsに保存されている魔法を表示します。

f:id:kazuhironagai77:20200726223552p:plain

因みに、SoldierLevelUpのデータを以下のように変更したのでLv.2ではSmallFire、Lv.3ではBigFireを覚えるはずです。

f:id:kazuhironagai77:20200726223609p:plain

Lv.3の時にSmallFireとBigFireを覚えているのが確認出来ました。

f:id:kazuhironagai77:20200726223629p:plain

3.4 アイテムを使用した時にHPしか影響されない

ItemウィジェットのBPを見たら、MPが上昇する場合を追加すれば良い事が分かりました。

f:id:kazuhironagai77:20200726223654p:plain

のでこんな感じで作成しました。

テストします。

MPが10/50の状態でイーサーを使用します。

f:id:kazuhironagai77:20200726223714p:plain

MPが30/50に成りました。さらに何回もイーサーを使用します。

f:id:kazuhironagai77:20200726223734p:plain

MPが50/50になったらMPの値はそれ以上増えなくなりました。

f:id:kazuhironagai77:20200726223755p:plain

出来ていますね。

3.5 使用したアイテムが消滅しない

Itemウィジェットの最後に以下のコードを追加しました。

f:id:kazuhironagai77:20200726223822p:plain

購入したアイテムの管理をRPGGameInstanceクラスで管理しているとずっと思っていたので、購入したアイテムが消せず凄い苦労しました。後でThirdPersonCharacterクラスで管理している変数はGameInstanceクラスに移します。

テスト結果です。

f:id:kazuhironagai77:20200726224048p:plain

回復薬を使用します。

f:id:kazuhironagai77:20200726224110p:plain

回復薬が消えました。

一度この画面を出て入り直します。

f:id:kazuhironagai77:20200726224130p:plain

回復薬が消費されてイーサーのみが残っている状態になっています。成功です。

3.6 武器を装備した時のATKと外した時のATKの違いが分からない

この問題と次の「武器を選んでも防具を選んでも武器に装備される。」は来週から始める「自分で改良した機能を追加する。」でしっかりやるのでここはパスします。

3.7  戦闘中はPause出来ないようにする

現状、戦闘の時はどうなっているのか確かめます。

f:id:kazuhironagai77:20200726224202p:plain

今のままでも戦闘中はpauseは出来ませんでした。

3.8 TargetCharacterをYourMyHeroに変更します

直しました。

3.9 モデルの入れ替え

来週以降やります。

3.10 UE4C++にBoolean変数であるTalkShopを作成する必要があるのか、更にその変数の管理をGameInstanceクラスに任せる事についての考察

TalkShopはプレイヤーの操作するキャラが店員と会話できるくらい近い位置にいる事を証明するためだけの変数で、店員の数が増える事やそれぞれのレベルに別々に存在している事を考えると、RPGGameModeBaseBPで管理した方がいい気がします。しかしもっと大切な事は店員との会話を一括で管理するシステムを構築してそのシステムを利用してそれぞれの店員の会話を管理する事です。このシステムを構築する事で沢山の店を一括で管理できるからです。

更に、将来的には村や町の住人も作成します。沢山のNPCそれぞれにBoolean変数をつけて会話開始の管理をするのは非効率です。これは次の問題の「 NPCの管理をこの部分の実装をLevelBP内でしています。別なBPで実装した方が良い気がする」とも関連しますが、もしそれぞれのNPCに個別にBoolean変数をつけて会話開始の管理をするならば、それはLevelBPで作成するのもアリと思います。

この辺はRPGにおけるNPCの管理方法についての調査が必要です。沢山のNPCを管理するためのソフトウェアデザインがあるはずです。まずその辺から始めましょう。ただ今週は他にもやる事が沢山あるので、この課題は後で考える事にします。

3.11 お金の管理をRPGGameInstanceクラスにさせるのか、それともGameCharacterクラスにさせるのか?

もうこれは結論が出ました。私のゲームでは主人公が変わったりしませんので、お金がプレイヤーが操作するキャラが変化する事で変わる事はありません。のでRPGGameInstanceクラスに管理させます。

4.まとめと感想

何とか、教科書の内容を追加する事が出来ました。来週からこのプロジェクトに自分で改良した機能を追加します。