UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 戦闘システムを完成する6

f:id:kazuhironagai77:20201220215614p:plain

<前文>

ʌの音の位置が違う

以下にWikipediaのVowel diagramに載っていたIPAによる母音の発音表を示します。

f:id:kazuhironagai77:20201220215644p:plain

左側に書かれているClose とかOpenは口の開ける大きさを表しています。FrontとかBackとかの上側に書かれているのは舌の盛り上がっている位置を表しています。同じ位置に2つ発音があるのは、一つは唇の形がそのままで、もう一つは唇を丸める場合の発音です。

ʌの音をみると口はかなり開けて舌の奥を挙げて更に唇は丸めないで発音しています。

この表の何が大切かというと、イギリス人が世界中の言葉に使われている音を、一つの音に対して一つのalphabetで表そうとした結果がこの表だからです。つまり母音に限って言えば、口の開ける大きさと舌の形、そして唇を丸めるかどうかで、全ての言語の音を表せると当時のイギリスの言語学者は考えたんです。

ちなみに日本語のアイウエオを見てみると、この図で日本語のアの音は、äが最も近いと思われます。日本語でアと言うとき、日本語のエの時より口を大きく開けていますし、アと言う時に舌を触ってみると舌の真ん中に力が入っています。実際にこの図のäをクリックしてäのページに飛んでみると日本語のアの音が例として入っています。

ただ、この日本語の説明が完全に正しいのかは疑問で、日本語のウの音はɯに分類されていますが、実際にウと言うときはかなり唇を丸めています。日本語のウの音はUの方じゃないのかなと思います。ɯの音の例に空気が載っていますが、試してみれば分かりますが、空気の発音は実際はくーきって言っていてこの時のーの部分の発音では唇は丸めません。しかしくうきと発音した時は唇を丸めます。Vowel diagramの基準で考えれば、くーきのーの音とくうきのウの音は違う音です。

更に日本語のエの音に関して言えば、舌の先を下げて舌の前方を丸めている気がします。イのように単純に舌の前方を押し上げているのとは違うと思います。この舌の先を丸めると言う行為についてもこの表で表されているのと解釈出来るのか不明です。

と言う訳で、日本語に限って考えてみてもこの方法で完璧に全ての音を表せているとは思えませんが、イギリス人の言語学者が行っている以上、少なくとも英語に関しては100%上手く行っているはずです。

以下のもう一つのvowel diagramを見て下さい。

f:id:kazuhironagai77:20201220215705p:plain

このvowel diagramはhttps://rose-medical.com//vowel-sounds.htmlから引用させてもらった図ですが、アメリカ人が作成したvowel diagramなんです。ʌの音が見事にschwa (ə)の音に被っています。幾人かのアメリカ人の発音のコーチが主張するəの音とʌの音は同じでストレスがあるかどうかが違うだけを表しています。

これってどう解釈するのが正しいですかね。

個人的には、https://rose-medical.com//vowel-sounds.htmlのvowel diagramの方が、アメリカ英語における母音の発音を正確に表している気がしますが…。

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

<本文>

先週、終わらなかった「11月22日のブログの「2. 今の戦闘システムを見直して問題点やバグを探しまとめます。」の「2.2 戦闘シーン毎の復習」で述べられている改善点。」の直しの続きをやります。

1. 戦闘システムの改善点の直しの続き

1.1 戦闘の終了

f:id:kazuhironagai77:20201220215748p:plain

レベルが上がった時、Userに分かるようにコメント欄に詳しい内容を報告します。

1.1.1 現状のチェック

現時点においてレベルが上昇した時に何をしているのかの確認をします。

RPGGameModeBaseクラス内のtick()関数内で戦闘に勝利した場合の中に以下に示した様に、レベルが上昇した時の処理が実装されていました。

f:id:kazuhironagai77:20201220215816p:plain

その中にReportCharacterLevelUp()関数と言うのがあり、BlueprintImplementableEventでspecifyされています。

f:id:kazuhironagai77:20201220215837p:plain

実装内容を見ると以下の様になっています。

f:id:kazuhironagai77:20201220215853p:plain

思い出してきました。これはUE4C++のUGameCharacterクラス内の変数は、武器や防具を装備した後のATKやDEFの値しか保持していないので、計算が面倒になるため、ThirdPersonCharacter内に武器や防具の無い状態でのATKとDEFの値を保持する変数を作成したんです。

ReportCharacterLevelUp()関数は、そのThirdPersonCharacter内の変数の値を変更するための関数ですね。

しかしこの関数のおかげでレベルアップした時のコメントは簡単に表示出来そうです。

1.1.2 レベルアップ時のコメント表示

ReportCharacterLevelUp()関数の最後に「レベルが上がりました。」のコメントを追加しました。

f:id:kazuhironagai77:20201220215915p:plain

これでまず試してみます。

f:id:kazuhironagai77:20201220215931p:plain

表示はされましたが、レベルが上がった事は勝利の報告の後ですべきです。

対症療法ですが、以下の様にしました。

RPGGameModeBaseクラスにBooleanタイプの変数、LevelUpを作成します。そしてReportCharacterLevelUp()関数の最後に以下の様にセットします。

f:id:kazuhironagai77:20201220215951p:plain

そして勝利しましたのコメントを表示するコードのすぐ後に、先程のレベルアップのコメントを以下の様に追加しました。

f:id:kazuhironagai77:20201220220009p:plain

結果、以下の様に表示されるようになりました。

f:id:kazuhironagai77:20201220220025p:plain

基本は出来ました。

f:id:kazuhironagai77:20201220220043p:plain

もっと細かい報告が必要ですが、現時点でコメント欄が一杯になっています。これ以上のコメントはいっぺんに表示する事が出来るように作成していないので、今回はここまでとします。

1.2 勝利のアニメーション

f:id:kazuhironagai77:20201220220103p:plain

1.2.1 勝利の時のカメラ位置の修正

直します。

確認したらカメラの位置はキャラの正面から撮影するように予めセットされていました。

f:id:kazuhironagai77:20201220220128p:plain

何で正面から撮影しないんでしょうか?

もう一度テストしてみます。

f:id:kazuhironagai77:20201220220145p:plain

勝利のポーズ時は、普通に正面から撮影していました。何回やっても前から撮影しています。

11月22日のブログを見ると、勝利のポーズ時に、後ろから撮影しています。

f:id:kazuhironagai77:20201220220201p:plain

何なんでしょうか?このバグは?

バグの再現が出来ないのでこのままで終わりにします。

1.2.2 モンスターの死亡アニメーションを追加しましょう

先週既に追加しました。

1.3 戦闘が終わってから元のマップに戻るまで

f:id:kazuhironagai77:20201220220235p:plain

これらは有ったら更に面白くなる要素なので、今回は無視して時間がある時に考えます。

1.4  元のマップに戻る

f:id:kazuhironagai77:20201220220308p:plain

1.4.1 元のマップに戻る

以下に示した様にしました。

まず元のマップに戻った時にモンスターが居たらもう一回戦闘になってしまいます。

戦闘が終了した時に、元のマップにいるモンスターは消えるようにします。

以下の方法で実装しました。

f:id:kazuhironagai77:20201220220333p:plain

f:id:kazuhironagai77:20201220220344p:plain

f:id:kazuhironagai77:20201220220352p:plain

f:id:kazuhironagai77:20201220220400p:plain

この方法では、全部のモンスターが消えてしまいますのであまり現実的な方法ではありません。

元のマップに戻って来た時に「10秒くらいモンスターから姿が見えない。」みたいな方が良いのかもしれません。

後で考えます。

元のマップに戻るのに必要な事はそのマップを開く事だけなので以下の様にしました。

f:id:kazuhironagai77:20201220220420p:plain

これで戻ります。

テストします。

f:id:kazuhironagai77:20201220220438p:plain

戻って来ました。

1.4.2 アイテムや装備品、金貨そしてキャラのパラメーターなどが、戦闘マップに行く前と変化していないか

確認します。

1.4.2.1 アイテム

戦闘前に所持しているアイテムです。この後でbattle fieldマップに移動します。

f:id:kazuhironagai77:20201220220510p:plain

戦闘後にbattle fieldマップからmap1に帰って来た後です。所有していたアイテムはそのまま残っています。

f:id:kazuhironagai77:20201220220535p:plain

念のために戦闘中に回復薬を使用した場合も試してみました。

戦闘後にbattle fieldマップからmap1に帰って来た後で、在庫表を確認すると、回復薬が消えています。

f:id:kazuhironagai77:20201220220556p:plain

アイテムの管理は大丈夫そうです。

1.4.2.2 装備品

今度は装備品の確認をします。

短剣(小)と木の盾(小)を装備品として所有しているが装備はしていない状態で戦闘してみます。

f:id:kazuhironagai77:20201220220621p:plain

f:id:kazuhironagai77:20201220220628p:plain

戦闘後にbattle fieldマップからmap1に帰って来た後で、装備表を確認すると戦闘開始前と全く同じ状態になっています。

f:id:kazuhironagai77:20201220220646p:plain

f:id:kazuhironagai77:20201220220653p:plain

今度は武器と防具を装備した状態でテストしました。

戦闘開始前と全く同じ状態で戻って来ました。

f:id:kazuhironagai77:20201220220718p:plain

正し一個バグが見つかりました。

武器と防具を装備した状態でモンスターの攻撃を受けると何故か、攻撃を受けた時のコメントではなく、アイテムを使用した時のコメントが表示されています。

f:id:kazuhironagai77:20201220220744p:plain

直します。

原因が分かりました。ReportCharacterHPisDamaged()関数の実装でダメージが0以下の場合は自動的に回復薬を使用したと判断されていました。

f:id:kazuhironagai77:20201220220802p:plain

Branchの部分をswitchに変更しました。

f:id:kazuhironagai77:20201220220821p:plain

テストします。

f:id:kazuhironagai77:20201220220839p:plain

出来てます。

道具を使用した時も元のコメントが表示されています。

f:id:kazuhironagai77:20201220220858p:plain

このコメント少しオカシイので後で直します。

1.4.2.3 金貨

薬草などを買って所持している金貨を55枚にしました。

f:id:kazuhironagai77:20201220220927p:plain

戦闘後にbattle fieldマップからmap1に帰って来た後で、所持している金貨の量を確認すると100枚に戻っていました。

f:id:kazuhironagai77:20201220220944p:plain

直します。

原因が分かりました。Map1のevent BeginPlayで金貨の所持量を100枚にセットしていました。

f:id:kazuhironagai77:20201220221004p:plain

直します。

f:id:kazuhironagai77:20201220221021p:plain

所持している金貨の量はRPGGameInstanceのconstructor内で指定しました。

f:id:kazuhironagai77:20201220221040p:plain

Map1のevent BeginPlayで金貨の所持量をセットしていたところは消しました。

テストします。

f:id:kazuhironagai77:20201220221057p:plain

10枚増えています。

f:id:kazuhironagai77:20201220221115p:plain

戦闘に勝った後、モンスターの所持している金貨を奪っていました。すっかり忘れていました。

EnemyMonsterのデータシートを見たらGoldの値が10にしっかりなっていました。

f:id:kazuhironagai77:20201220221133p:plain

戦闘に勝ったことで金貨を獲得した事を、コメント欄で報告しないといけないですが、これは後でやります。

1.4.2.4 キャラのパラメーター

ゴブリンを倒して得られるXPが50のままだとレベルが上がってしまい、キャラのパラメーターが保持されているのかどうか分からないので、ゴブリンを倒して得られるXPを20に変更します。

f:id:kazuhironagai77:20201220221159p:plain

これでテストします。

戦闘終了時、HP:70、MP:20でした。

Map1のevent BeginPlayでキャラのパラメーターを確認したところ、戦闘終了時と同じ値でした。

f:id:kazuhironagai77:20201220221217p:plain

1.4.2.5 戦闘画面との移動におけるアイテムや装備品、金貨そしてキャラのパラメーターの変化についてのまとめ

アイテムや装備品、金貨そしてキャラのパラメーターについて戦闘画面との移動によって値が変化しないか確認した。変化するモノには個別に修復した。

1.4.3 戻った先にいたモンスターは消滅しているか?

「1.4.1 元のマップに戻る」で戦闘後にモンスターは消滅するようにしたので、戻った先にいたモンスターは消滅している。

1.4.4 モンスターを倒して得た財宝を持っているか?

「1.4.2.3 金貨」で確認済み。

2. 先週のバグの直し

11月22日のブログの直しがとうとう終わったので、先週のバグの直しを始めます。

  1. 戦闘の攻撃時、自分を選択した場合のコメント欄のセリフの直し
  2. 戦闘画面の戻るボタンの作成

これしかありませんでした。直していきます。

2.1 戦闘の攻撃時、自分を選択した場合のコメント欄のセリフの直し

まず、セリフを見てみます。

攻撃を選択した後、KUROを選択します。

f:id:kazuhironagai77:20201220221543p:plain

このセリフは特にオカシクは無いです。次のセリフを見てみます。

f:id:kazuhironagai77:20201220221559p:plain

二行目がオカシイですね。KUMOはKUMOを攻撃した。が正しい文です。直します。

「“KUMO”がゴブリンを攻撃しました。」はRPGGameModeBaseクラスのOnClicked(AttackedButton)に実装されていました。

f:id:kazuhironagai77:20201220221616p:plain

以下に示した通り、攻撃対象の名前はCombatUIWidgetクラスのGetCharacterTargets()関数を使用して取得していました。

f:id:kazuhironagai77:20201220221715p:plain

今のゲームの内容ではGetCharacterTargets()関数そのものが不要ですがそれは一応残しておきます。「“KUMO”がゴブリンを攻撃しました。」のセリフの部分は外してAttackTargetButtonウィジェット内のボタンをクリックした時に発動するeventに移しました。

f:id:kazuhironagai77:20201220221734p:plain

テストします。

f:id:kazuhironagai77:20201220221750p:plain

直りました。

2.2  戦闘画面の戻るボタンの作成

これ、簡単に作れると思ったら、Combat EngineのTick()関数内をいじる必要がありました。ので中止します。

3. 戦闘システムの完成

一応、これで最低限の戦闘システムが完成しました。

今回、上記の教科書を元に作成した戦闘システムは以下の構成になっています。

f:id:kazuhironagai77:20201220221828p:plain

Combat engineを純正のC++で作成し、そのEngineとUE4C++で連絡し合って戦闘を進め、実際の3Dの映像はUE4C++とUE4BPで連絡しながらUE4BPが担当しました。

戦闘システムに関する感想を以下に示します。

3.1  純正のC++でcombat engineを作成する

敢えてC++UE4の外側にcombat engineを作成するメリットはなかったと思います。

このような作成方法で、純正のC++をUE4C++から利用出来る事は分かりました。それは有効な知識になりましたが、実際のゲーム作成において、UE4C++にある非常にゲーム作成に有効なAPIを使用しないで、最初から自分でengineを作成する意味はなかったです。

更にUE4BPと純正のC++の連絡は一端UE4C++を通してのみ可能と言う事実が、大変な足枷になりました。

3.2  UE4C++でUObjectからGameCharacterクラスを作成した事

これも、教科書で勉強している時は理由が良く分からないので、教科書の通りに作成しましたが、Characterクラスから作成した方が後々の管理が楽な気がします。ただデータの管理と言う点では、分けた方が少ないデータで済むのかもしれません。その場合でもGameCharacterクラスと言う名称はCharacterクラスとの混乱を生むので、EntityParameterみたいな別な名前を付けた方が良いと思います。

3.3  UE4C++を使用するデメリット

Compileに時間がかかり過ぎます。BPならば一瞬で終わってくれるような小さい変更でも5分とか待たされます。それ以外では特にデメリットは感じませんでした。

3.4  UE4BPについて

AIやアニメーション、そしてparticle systemなどのUE4BPにある沢山の機能の使い方が、全く知らない事を思い知らされました。この辺の勉強は個別に必要です。これから勉強します。

3.5  報告、連絡、相談について

ユーザーとしてモンスターとの戦闘を試した所、全く知りたい情報が得られていない事にびっくりしました。UIに報告、連絡、相談する機能をつける事は必須と感じました。そのためにどんな機能が必要とか、その機能はどうやって作成するのか等の情報は、この教科書には全く紹介されていません。

この辺はノウハウとして蓄積が可能な分野かもしれません。自分で研究してみます。

3.6 これからの課題

音楽を追加するのを忘れていました。来週追加します。

マップ上にモンスターを散りばめて、沢山戦闘して試してみます。

4. まとめと感想

今週はこれで終わりです。