UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 戦闘中のanimation の直し

f:id:kazuhironagai77:20210228233202p:plain

<前文>

他人の評価と

この前文では、日本の話題についてはあんまり書かないと決めています。その理由は、結構な頻度でその問題の当事者にあったりするからです。他人事で批判していたら、その当事者に会ったりした時、かなり気不味いです。ので基本的に日本の話題については書きません。今回だけは例外です。のでかなりボヤカして書きます。

ある人が社会的にかなり権威のある賞を取ったんですが、その時にその人が「俺を今まで馬鹿にしていた連中め。ザマーミロ。」と言ったんです。思わず呟いちゃったんでしょうね。これって社会人としてはかなり問題発言ですし、常識から考えても「今まで応援してくれた人達のお陰でここまで来れました。」位に留めておくべきでした。

しかし、それ聞いた時、私は逆に感動しちゃったんです。だってそんな賞取る人でも、完全無欠でここまで来た訳じゃなくて、そういう世間や上司などの第三者からの理不尽な低評価に、歯を食い縛りながら戦って来た事が分かったからです。彼も天才じゃなかったんです。見えない所で不断の努力を行っていたんですね。しかもずっと評価されない状態で。

何かを成すためには、第三者からの評価は絶対に必要です。自分勝手になったり、そこまで行かなくても客観的な事実に目を向けられずに、間違ったまま進んでしまったりしている時に、他人からの助言ではっと我に返る事が出来るからです。

しかし多くの第三者の人は理不尽としか思えない低評価しか付けない人が多いです。

他人の評価をする義務なんで無いです。実際ほとんどの人は他人の行為や作品に対しての評価はしてくれません。そんな中で評価したり、敢えて助言したりしてくれる人の意見は大変貴重で大切ですし、どんなに理不尽な評価でも本当にその人が思っている事ならば聞かねばなりません。

しかし本当にその人そう思っているんでしょうか?世間一般がそう言うから低評価しておいた。とか、この部下を低評価しておくと自分が上司から高評価受けるから。とか、あるいは、あからさまな悪意によって低評価している場合も多い様に思えます。

そうなった時に、その意見は聞かないと言う選択肢は有りと私は思っています。

しかし世の中の所謂、仕事が出来る人の多くは、そういう人の意見もかなり真剣に聞く傾向にあります。そういう人達は自分に対する戒めが大変強いので、第三者の評価を非常に大切にします。更に「悪意が在ったとしても助言は助言。」と考える人もいます。

それは私の経験から言うと大変危険です。

悪意のある助言や無能な人の評価を聞くのは、第三者の評価を全く聞かない以上に危ないんです。破滅する可能性まで在る最悪の選択です。

言っては何ですが、こういう仕事が出来る人って恵まれた環境で育っていて、本当に悪意がある人や本当に無能な人に今まで会った事が無いんです。厳しい言い方をすると悪意がある人の意見と真剣に助言してくれる人の区別が付かないし、無能な人でも雰囲気だけで有能そうと判断してしまったりします。

私が個人的に見聞した悪意ある助言は「取りあえずここは謝って」と「今日は家に帰ってゆっくり休んで」です。もし謝ったら「次は誠意が足りない。」と更なる譲歩を要求して、最終的には土下座か一筆書かされるまで追い込むそうです。家に帰すのは、貴方が不在の間に貴方に対しての何かしらの犯罪行為を行うためだそうです。

無能な助言で多いのが「数字の間違い」です。これは日本ではあまり無かったですが、アメリカで何回も経験しました。特に役所で。アメリカの恐ろしい所は、嘘には非常に厳しいのに間違いにはほとんどペナルティーが付かないんです。しかし間違いでも損害が発生しますから。損害を受ける側は大変です。

そこまで行っても「実際、悪意が在るのか、自分が意固地になっていて正しい助言に対して悪意があると思い込んでいるのか、自分では分からないじゃないか。」と反論されるかもしれません。

そこで妥協案です。「一回だけその人の助言を聞いて見たらと。」

絶対に無いでしょうが、それで劇的に改善したら聞き続けるべきです。もし変化が無いのなら、破滅する可能性がある意見は無視すべきでしょう。劇的に悪くなったら、その人に対して今すぐ最大級の警戒をすべきです。

最後にまとめると、馬鹿にしていたり低評価しかしない連中は、悪意を持っていたり無能な人の場合が多いですので、評価や助言は無視すべきです。

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

<本文>

1.今週の予定

戦闘中のアニメーションにPlayAnimation nodeを使用していますが、アニメーションは全部AnimBPで管理すべきでした。今週はここを直します。

  • モンスターのAnimBPを改良して、戦闘のAnimationAnimBPで表示出来る様にします。
  • 同様の方法で、Playerが操作するキャラのアニメーションもAnimBPで表示します。

アニメーションを直した後に時間がまだある場合は、このゲームをプレイしてバグ出しをします。

もしバグ出しした後でも、それでも時間があるならば、Levelデザインでもやってマップを完成させます。

2.PlayAnimation ノードを外して、戦闘中のアニメーションもAnimBPで管理する。(モンスターの場合)

2.1 モンスターのAnimBP の復習

AnimBPでどのようにアニメーションを管理しているのかすっかり忘れてしまいました。まず復習から始めます。

MonsterBPを開いて見ると

f:id:kazuhironagai77:20210228233541p:plain

使用しているAnim ClassはSkelSwordAni_Cとなっています。

f:id:kazuhironagai77:20210228233612p:plain

これですね。

f:id:kazuhironagai77:20210228233634p:plain

開いて見ると、まず変数としてSpeedとDelayがありました。

f:id:kazuhironagai77:20210228233707p:plain

以下に示した様に、開始して1.6秒経つとdelay変数がTrueになります。

f:id:kazuhironagai77:20210228233733p:plain

Speed変数はモンスターの移動スピードを表しています。

f:id:kazuhironagai77:20210228233754p:plain

そうだ。思い出して来ました。Animation BPにはEventGraphとAnimGraphがあったんです。

f:id:kazuhironagai77:20210228233813p:plain

今度はAnimGraphを見て行きます。

f:id:kazuhironagai77:20210228233921p:plain

思い出して来ました。このDefaultの中で色々な条件とそれに沿ったアニメーションを指定したんです。

それはそうと、このAnimGraphではDefaultとOutput Pose以上の作成出来るんですかね。もっとUE4アニメーションに詳しくなったらモット複雑な形のAnimGraphがあるんでしょうか?

Default stateの中を見ます。

f:id:kazuhironagai77:20210228233940p:plain

Spawn stateとIdle/Run stateがありその間に条件節が一個あります。

Spawn stateを見るとSkeleton_Swordman_Spawnのanimationを表示させています。

f:id:kazuhironagai77:20210228233958p:plain

Skeleton_Swordman_Spawnのanimationは以下のヤツです。

f:id:kazuhironagai77:20210228234016p:plain

f:id:kazuhironagai77:20210228234024p:plain

f:id:kazuhironagai77:20210228234032p:plain

f:id:kazuhironagai77:20210228234041p:plain

このアニメーションに掛かる時間が1.6秒でした。

もう分かりました。delay変数がTrueになるのが、Spawn stateからIdle/Run stateに移動出来るため条件ですね。

一応調べて見ます。

f:id:kazuhironagai77:20210228234111p:plain

f:id:kazuhironagai77:20210228234121p:plain

その通りでした。

最後のIdle/Runを見ます。

f:id:kazuhironagai77:20210228234303p:plain

あれ。思っていたより簡単な構造でした。

そうか。歩くのと走るのは、早歩きみたいな歩くと走るの中間があるから、それをBlendspace PlayerクラスであるSkelSword1Dで再現したんでした。

SkelSword1Dの中身も見てみます。

f:id:kazuhironagai77:20210228234322p:plain

Speedが345以上で完全に走り出します。Speedが85までは歩いています。

85?

AIでモンスターが探索する時の最大速度は幾つでしたっけ。

MyBehaivorTreeを見てみると150にセットされています。

f:id:kazuhironagai77:20210228234339p:plain

f:id:kazuhironagai77:20210228234347p:plain

計算式を見直さないと数値が同じ単位なのか分かりませんが、後で数値の確認をする必要がありますね。モンスターが探索している時は、歩くべきですので。

取りあえず、モンスターのAnimBPがどうなっているのかは分かりました。

2.2 戦闘時におけるモンスターのplayAnimationの使用箇所についての復習

RPGGameModeBP内の以下の部分でモンスターの戦闘中のアニメーションを担当していました。

f:id:kazuhironagai77:20210228234414p:plain

あれSetViewTargetwithBlendノードは何をする関数何でしょうか?

覚えていません。調べます。

f:id:kazuhironagai77:20210228234430p:plain

使用するカメラを切り替えるんでした。

あれ。でもこの設定だと、カメラを切り替えるだけですよね。

実際の戦闘では以下の様に、モンスターを正面から撮影しています。

f:id:kazuhironagai77:20210228234446p:plain

この設定だとモンスターの後ろ姿を撮影するんじゃ…。

分かりました。

元々、monsterBPのカメラはモンスターに対して正面を向いた状態で作成していました。

f:id:kazuhironagai77:20210228234509p:plain

戦闘中のカメラの管理については全く忘れていました。今週はやりませんが、このやり方が正しいのかの検証は必要ですね。

そしてPlayAnimationです。

f:id:kazuhironagai77:20210228234533p:plain

Skeleton_Swordman_Default_Attackアニメーションをplayしています。

f:id:kazuhironagai77:20210228234557p:plain

この時にSkelSwordAniからこのアニメーションをplay出来るようにすればいい訳ですね。

大体やり方が分かって来ました。

もう一か所、戦闘中のモンスターのアニメーションでPlayeAnimationを使用している箇所がありました。

f:id:kazuhironagai77:20210228234620p:plain

ここでは、モンスターが死んだアニメーションを流しています。

f:id:kazuhironagai77:20210228234636p:plain

これもSkelSwordAniからPlay出来る様にします。

2.3 SkelSwordAniにSkeleton_Swordman_Default_AttackアニメーションとSkeleton_Swordman_Dieアニメーションを追加する。

それでは、モンスターが使用するAnimation BPであるSkelSwordAniからSkeleton_Swordman_Default_AttackアニメーションとSkeleton_Swordman_Dieアニメーションが使用出来るようにします。

SkelSwordAni内に新しいBoolean変数、Attackを作成します。

f:id:kazuhironagai77:20210228234707p:plain

このAttack変数がTrueの時に、Skeleton_Swordman_Default_Attackアニメーションを流すようにします。

まずDefault StateでIdle/Run stateにAttack Stateを追加します。

f:id:kazuhironagai77:20210228234723p:plain

Attack StateではSkeleton_Swordman_Default_Attackアニメーションを流します。

f:id:kazuhironagai77:20210228234740p:plain

移行する条件は、Attack変数の値がTrueに成る事です。

f:id:kazuhironagai77:20210228234757p:plain

これでSkelSwordAniからSkeleton_Swordman_Default_Attackアニメーションが使用出来るはずです。

同様な方法で、Skeleton_Swordman_DieアニメーションもSkelSwordAniから使用出来るようにします。

f:id:kazuhironagai77:20210228234819p:plain

f:id:kazuhironagai77:20210228234825p:plain

f:id:kazuhironagai77:20210228234834p:plain

f:id:kazuhironagai77:20210228234841p:plain

これでSkelSwordAniからSkeleton_Swordman_Dieアニメーションも使用出来るはずです。

2.4 戦闘中にSkelSwordAniからSkeleton_Swordman_Default_Attackアニメーションを使用する。

RPGGameModeBPのここの部分を変更します。

f:id:kazuhironagai77:20210228234907p:plain

以下の様に実装しました。

f:id:kazuhironagai77:20210228234924p:plain

テストします。

普通に攻撃しています。

f:id:kazuhironagai77:20210228234956p:plain

出来ました。

整理して見やすいようにしました。

f:id:kazuhironagai77:20210228235015p:plain

2.5 戦闘中にSkelSwordAniからSkeleton_Swordman_Dieアニメーションを使用する。

今度は、Skeleton_Swordman_Dieアニメーションの番です。Skeleton_Swordman_Default_Attackアニメーションの場合と全く同じやり方で行います。

このPlayAnimationノードを外します。

f:id:kazuhironagai77:20210228235041p:plain

以下の様に実装しました。

f:id:kazuhironagai77:20210228235108p:plain

テストします。

モンスターを倒した時にこのアニメーションが流れましたが、その後で、モンスターが復活してしまいました。

f:id:kazuhironagai77:20210228235128p:plain

良く考えたら当たり前でした。直します。

f:id:kazuhironagai77:20210228235149p:plain

もう一回テストします。

今度は死ぬモーションをひたすら繰り返しています。

うーん。

もうちょっと考えたら直せそうですが、ここはPlayAnimationを使用した方が適切な気がしてきました。

この後、このモンスターがSkelSwordAniを使用して動く事はないからです。

やっぱりここは元に戻します。

f:id:kazuhironagai77:20210228235209p:plain

f:id:kazuhironagai77:20210228235216p:plain

確認のためのテストをします。

f:id:kazuhironagai77:20210228235234p:plain

元に戻りました。

3.PlayAnimation ノードを外して戦闘中のアニメーションもAnimBPで管理する。(プレイヤーの操作するキャラの場合)

プレイヤーの操作するキャラは、素手、武器、魔法を使用した時にそれぞれ別のアニメーションを使用する必要がありますし、特に魔法を使用した時にParticle Systemも使用します。モンスターの時よりかなり複雑なはずです。気を付けてやって行きましょう。

3.1 プレイヤーの操作するキャラのAnimBP の復習

プレイヤーの操作するキャラのためのCharacter Class ですが、ThirdPersonCharacterをそのまま使用していました。

f:id:kazuhironagai77:20210228235305p:plain

使用されているAnim ClassはMyThirdPerson_AnimBP_Cでした。

f:id:kazuhironagai77:20210228235332p:plain

MyThirdPerson_AnimBPを見て行きます。

まず変数ですが、以下の3つがありました。

f:id:kazuhironagai77:20210228235417p:plain

多分、SpeedとIsInAirは元々あった変数と思われます。WithWeaponは自分で追加した事を覚えています。

EventGraphを見てみます。

f:id:kazuhironagai77:20210228235449p:plain

見にくい。ちょっと整理します。

f:id:kazuhironagai77:20210228235508p:plain

EventGraphでは二つの変数の値を常にUpdateし続けていました。

自画自賛ですが、関数の下にその関数にパスする値を書く私のやり方、先週、発明したReroute  nodeを併用すると非常に見やすくなります。これはBPの書き方における大発明かもしれません。最初、この書き方を始めた時は、自分自身ではもっとも分かり易い書き方であると信じていましたが、誰もやっている人がいなくて内心かなり弱気でした。しかしこれを見れば、私の書き方が見やすい、理解しやすいのは一目瞭然です。

整理する前の書き方だと、TryGetPawnOwnerノードを中心に見てしまいます。しかしTryGetPawnOwnerノードからコードの流れを見ても何をやっているのか曖昧になってしまいます。あれっと最初からコードの流れを見る羽目になります。

所が私の書き方だと、まずこの部分の実装の目的は二つの変数、IsiInAirとSpeedに値をセットする事であると一発で分かります。その後でそれらにセットするための値はどうやって得ているのかを知りたくなったら、その下の関数らを追えば良いだけです。

今度はAnimGraphを見てみます。

f:id:kazuhironagai77:20210228235526p:plain

勿論、Default Stateを開きます。

f:id:kazuhironagai77:20210228235543p:plain

成程、分かりました。Idle/RunとIdle/RunWithWeaponのStateがあるんですね。

後、Jumpの機能もあったんですね。

走ったりするStateの中を開いて見る必要がない事は既に分かっているのでここまでにします。

3.2 戦闘時におけるモンスターのplayAnimationの使用箇所についての復習

戦闘時に攻撃を選択した時、武器を所持している時としていない時のアニメーションの表示にPlayAnimationを使用しています。

f:id:kazuhironagai77:20210228235608p:plain

武器を装備しているかどうかはRPGGameInstanceBPから調べるべきでしょう。何で敢えてAnimInstanceから調べているんでしょうか?

以下に示した様に、武器を装備している時はplayAnimationノードの後で、MyThirdPersonAnimBPをセットし直して更にMyThirdPersonAnimBPの変数WithWeaponをTrueに指定しています。

f:id:kazuhironagai77:20210228235627p:plain

本当に無駄手間をかけています。こここそ、全てのアニメーションをMyThirdPersonAnimBPで直接管理すべき所です。

次は魔法を選択した時のアニメーションです。魔法はParticle Systemを使用していますので複雑な構造になっていると思っていたのですが、実際の実装を見るとplayer の操作するキャラとは別なActorがParticle Systemを担当していました。

f:id:kazuhironagai77:20210228235648p:plain

これなら簡単に直せそうです。

更に戦闘に負けて死んだときと戦闘に勝利した時のアニメーションもPlayAnimationが使用されていました。

f:id:kazuhironagai77:20210228235732p:plain

f:id:kazuhironagai77:20210228235742p:plain

これらに使用されているアニメーションは両方とも武器なしのものだけでした。武器在りのアニメーションも追加したら見栄えがもっと良くなると思って提供されているアニメーションを調べたら武器なしのアニメーションしかなかったです。

f:id:kazuhironagai77:20210228235803p:plain

3.3 MyThirdPerson_AnimBPに武器なしの場合の攻撃アニメーションと武器ありの場合の攻撃アニメーション、そして魔法使用時のアニメーションを追加する。

以下の様に追加しました。

f:id:kazuhironagai77:20210228235828p:plain

新たに作成した変数は、MagicとAttackです。

f:id:kazuhironagai77:20210228235847p:plain

Attack変数の使用方法は「2.3 SkelSwordAniにSkeleton_Swordman_Default_AttackアニメーションとSkeleton_Swordman_Dieアニメーションを追加する。」での使用方法と全く同じです。

Magicを使用した場合は武器を装備している時としていない時で返るstateが違います。以下の様に設定しています。

武器装備なしの場合

f:id:kazuhironagai77:20210228235905p:plain

武器装備在りの場合

f:id:kazuhironagai77:20210228235923p:plain

多分これで上手く行くそれぞれのStateに帰るはずです。

戦闘に負けて死ぬアニメーションと戦闘に勝って処理のポーズを取るアニメーションはPlayAnimationを使用する予定なので、これらのアニメーションはMyThirdPerson_AnimBPには追加しません。

3.4 戦闘中にMyThirdPerson_AnimBPから攻撃アニメーションを使用する。

以下の様に攻撃アニメーションの実装を変更しました。MyThirdPerson_AnimBPの実装が正しくされていれば武器装備ありと武器装備なしで分けてアニメーションを指定する必要はないはずです。

f:id:kazuhironagai77:20210301000005p:plain

テストします。

武器を装備したらいきなり攻撃モーションを繰り返し始めました。

調べたら以下の部分を逆に設定していました。

f:id:kazuhironagai77:20210301000046p:plain

もう一度テストします。

武器なしの場合です。

f:id:kazuhironagai77:20210301000159p:plain

武器なしのモーションが選択されています。

武器在りの場合です。

f:id:kazuhironagai77:20210301000230p:plain

武器在りのモーションが流れました。

出来てますね。

コードを整理します。

f:id:kazuhironagai77:20210301000300p:plain

たったこれだけになりました。

3.5 戦闘中にMyThirdPerson_AnimBPから魔法アニメーションを使用する。

今度は魔法アニメーションです。以下の様に実装し直しました。

f:id:kazuhironagai77:20210301000343p:plain

テストします。

何回も同じモーションを繰り返しています。

魔法のモーションが約0.7秒だったので0.7秒辺りでMyThirdPerson_AnimBP のMagic変数の値をFalseに戻しました。

f:id:kazuhironagai77:20210301000403p:plain

テストします。

まず武器なしで魔法を使用した時です。

f:id:kazuhironagai77:20210301000427p:plain

その後、攻撃を選択します。

f:id:kazuhironagai77:20210301000442p:plain

素手の攻撃モーションを使用しています。

今度は武器ありで魔法を使用します。

f:id:kazuhironagai77:20210301000500p:plain

その後、攻撃を選択します。

f:id:kazuhironagai77:20210301000514p:plain

武器の攻撃モーションを使用しています。

出来ていました。

3.6 戦闘中のコードを整理する。

RPGGameModeBP内の戦闘中の実装が以下の様にぐちゃぐちゃなので整理します。

f:id:kazuhironagai77:20210301000535p:plain

以下の様に整理しました。

f:id:kazuhironagai77:20210301000553p:plain

もう少し整理出来ますが、この状態でテストします。

武器在りの時です。

魔法を使用します。

f:id:kazuhironagai77:20210301000619p:plain

その後、攻撃します。

f:id:kazuhironagai77:20210301000636p:plain

武器で攻撃しています。出来ています。

今度のテストは武器なしの時です。

魔法を使用します。

f:id:kazuhironagai77:20210301000705p:plain

その後攻撃します。

f:id:kazuhironagai77:20210301000722p:plain

武器なしの攻撃をしています。

出来ています。

もう少しだけ整理します。

色んな所でMyThirdPerson_AnimBPにアクセスしているので変数として作成します。

f:id:kazuhironagai77:20210301000740p:plain

RPGGameModeBP内のEventBeginPlay関数で、以下に示した様に変数MyThirdPersonAnimBPを作成しました。

f:id:kazuhironagai77:20210301000802p:plain

まだまだスパゲッティコードですが、前よりは遥かに見やすく成りました。

f:id:kazuhironagai77:20210301000819p:plain

確認のテストをします。

スクリーンショットは取らなかったですが出来ている事は確認出来ました。

4.兎に角、Playしてバグを見つける

4.1 Playします。

まず、プレイ中の音楽が無いです。

夜になると真っ暗で何も見えません。

f:id:kazuhironagai77:20210301000846p:plain

PCが突然、凄い音出し始めました。

f:id:kazuhironagai77:20210301000903p:plain

地面の無い所にいったらフリーズしました。

戦闘から戻った時にカメラの方向が一定です。

戦闘中に「読みましたボタン」が表示されないバグが発生しました。

f:id:kazuhironagai77:20210301000919p:plain

再現性もあります。

Level10に成れないためのバグかもしれません。

f:id:kazuhironagai77:20210301000936p:plain

「読みましたボタン」が表示されないバグではなく勝利シーンに移行できないバグのようです。

たった十分程度Playしただけでこれだけのバグが出て来ました。

でもそれなりに面白かったです。

4.2 バグのまとめ

以下のバグが見つかりました。

  • プレイ中の音楽が無い。
  • 夜になると真っ暗で何も見えない。
  • PCが突然、凄い音出し始めました。(ずっとではない。)
  • 地面の無い所にいったらフリーズした。
  • 戦闘から戻った時にカメラの方向が一定。
  • 戦闘から戻れないバグ発生。

これらのバグを直します。

5. バグの直し

5.1 プレイ中の音楽の追加

以下の方法で、Map1にBGMを追加しました。

f:id:kazuhironagai77:20210301001021p:plain

BGMは場所によって変化させる予定なので音の編集が出来るSpawnSound2Dノードを使用します。

使用するCueは以下のデータです

f:id:kazuhironagai77:20210301001042p:plain

Mega Game Music Collectionから使用しました。

f:id:kazuhironagai77:20210301001119p:plain

BGMをループさせるため、Cueを開いてLoopingにチェックします。

f:id:kazuhironagai77:20210301001143p:plain

モンスターが発生する危険な地域や、町や城でBGMは変更しますが、それは後で作成します。

5.2 夜になると真っ暗で何も見えない。

もう単純にPoint LightをThird Person Characterに追加しました。

f:id:kazuhironagai77:20210301001207p:plain

Lightが無い状態です。

f:id:kazuhironagai77:20210301001224p:plain

Lightがある状態です。

f:id:kazuhironagai77:20210301001239p:plain

かなり見やすく成っていますが、回りを見渡すまでは明るくはないです。今回はこれ位にしておきます。

5.3 PCが突然、凄い音出し始めました(ずっとではない)。

再現したくて何回もゲームをPlayしたがその後、一回もそんな事態にはならなかったです。

F5でShaderの負担をチェックしたが特に特別に重そうな所は見つからなかったです。

f:id:kazuhironagai77:20210301001302p:plain

f:id:kazuhironagai77:20210301001310p:plain

原因が不明なのでこのバグの修復はパスします。

5.4 地面の無い所にいったらフリーズした。

落ちたら死ねば良いだけですが、どうやって実装しましょうか?

思い付きました。

この方法はベストではないでしょうが、これでも出来るはずです。

MyThirdPerson_AnimBPに二つの変数、IsInAirとSpeedがあります。

f:id:kazuhironagai77:20210301001337p:plain

更に、ThirdPersonCharacterのMax Walk Speedを見ると600になっています。

f:id:kazuhironagai77:20210301001356p:plain

この二つから推測すると、IsInAirがtrueでSpeedが600以上だった場合、プレイヤーが操作するキャラが墜落していると考えて良いのではないでしょうか?

RPGGameModeBPのTick関数に以下のコードを追加しました。

f:id:kazuhironagai77:20210301001417p:plain

これでPlayerが操作するキャラが墜落した時が分かるはずです。

墜落した場合は墜落死を知らせる新しいmapを開きます。

f:id:kazuhironagai77:20210301001438p:plain

そのためのWidgetも作成しました。

f:id:kazuhironagai77:20210301001456p:plain

テストします。

f:id:kazuhironagai77:20210301001513p:plain

落ちます。

一瞬でGame Overに成りました。

f:id:kazuhironagai77:20210301001536p:plain

もっと発展させる必要はありますが、最低限の機能は出来ました。

5.5 戦闘から戻った時にカメラの方向が一定

これが何で成るのかが分からないです。

考えられるのはRootCompomentとして指定されているCapsuleComponentにScaleしか指定出来ないため指定出来ないのかもしれません。

f:id:kazuhironagai77:20210301002120p:plain

f:id:kazuhironagai77:20210301002128p:plain

色々試したのですが、結局原因は不明でした。

カメラとCameraBoomの関係をもう一度勉強しないと理解出来なそうです。

色々調べたら、PlayerStartの向きとカメラの向きが同じになっているみたいです。

それならPlayerStart を消してPlayerが操作するキャラを動的に作成すれば向きも自然になると思いその方法を調べました。

以下の方法でPlayerが操作するキャラを動的に作成出来るそうです。

f:id:kazuhironagai77:20210301002153p:plain

この方法を試してみます。

以下の方法でMap1、LevelBP内に実装しました。

f:id:kazuhironagai77:20210301002217p:plain

テストします。

f:id:kazuhironagai77:20210301002233p:plain

後ろ向きで戻って来ました。

ただし。大量のエラー報告と一緒にですが…

f:id:kazuhironagai77:20210301002256p:plain

直していきます。

最初のエラーの原因はRPGGameModeBPのMyThirdPersonAnimBPがnullだからでした。その原因はRPGGameModeBPのEventBeginPlayの時にはまだPlayerが操作するキャラを作成していないからです。

Playerが操作するキャラはRPGGameModeBPで作成する事にします。

f:id:kazuhironagai77:20210301002319p:plain

更に戦闘時の場合はPlayerが操作するキャラの生成される場所が違うのでそれに対応した別のSpawnPlayerCharacterBattleFiledも作成します。

f:id:kazuhironagai77:20210301002343p:plain

Levelによってそれぞれのイベントを呼び出します。

f:id:kazuhironagai77:20210301002419p:plain

テストします。

素手の戦闘では上手く行きましたが、武器を持った場合、元に戻った時、以下の様なエラーが発生しました。

f:id:kazuhironagai77:20210301002439p:plain

原因はRPGGameModeBPでPlayerが操作するキャラを作成して更に、Map1でも作成してたからと思われます。

Map1の作成は外します。

f:id:kazuhironagai77:20210301002459p:plain

今度は大丈夫でした。

f:id:kazuhironagai77:20210301002524p:plain

以下のWarningが出ています。何なんでしょうか?

f:id:kazuhironagai77:20210301002649p:plain

分かりませんね。

ThirdPersonCharacterを(0,0,0)の位置にSpawnせよという命令はしていないはずですが。

5.6 戦闘から戻れないバグ発生

レベルが10になった時、以下のif節に入ってエラーになっていました。

f:id:kazuhironagai77:20210301002714p:plain

色々検討した結果、このIf節はrowがNullの全ての場合に対応しているので、消す訳にはいかないので以下のような変更にしました。

f:id:kazuhironagai77:20210301002733p:plain

テストします。
Levelが10に上がってゲームが途中で止まる事も無くなりました。

f:id:kazuhironagai77:20210301002753p:plain

ここは直ったんですが、以下のコードがLevel10になった時にゲームを停止させてしまう事に気が付きました。

f:id:kazuhironagai77:20210301002811p:plain

取りあえず試してみます。

やっぱり停止しました。

f:id:kazuhironagai77:20210301002833p:plain

以下のコードを追加してそもそもLevelが10になった時はLevelUpの検査を受けないようにしました。

f:id:kazuhironagai77:20210301002851p:plain

テストします。

普通に戦闘が終了しました。

直りました。

6.バグ出しもう一回

「5.5 戦闘から戻った時にカメラの方向が一定」でPlayerが操作するキャラをLevel上に配置したPlayerStartから静的に生成するのではなく、動的にBPから生成する事にしました。

この大改造により、バグが大量に生成されていると思われます。

現状把握しているだけでも、以下のWarningは出続けていますし。

f:id:kazuhironagai77:20210301002921p:plain

もう一回バグ出しをやって行きます。

6.1 スタート画面でエラー、更に墜落死画面でもエラー

直します。

以下の様にしました。

f:id:kazuhironagai77:20210301003003p:plain

ここで動的にPlayerの操作するキャラを作成しなければ勝手にPlayerStartの位置にThirdPersonCharacterが作成されるはずです。

試してみます。

出来ました。

出来ましたが、またエラーが大量に発生しました。

f:id:kazuhironagai77:20210301003022p:plain

直します。

ここでエラーが発生しています。

f:id:kazuhironagai77:20210301003040p:plain

成程。このやり方だとMyThirdPersonAnimがnullになってしまうんですね。

直します。

以下の様に直しました。

f:id:kazuhironagai77:20210301003058p:plain

まずEventを止めました。基本的にEventは電話と同じ機能をProgrammingで実装したものです。全ての作業を中止しても対応しなければならない、突然発生する事態(つまり電話の対応)のための機能です。

Playerのキャラを作成する事は突然発生しません。毎回、Levelを開く時にする必要があります。のでEventは使用しません。

代わりに関数、SpawnPlayerCharを作成しました。

f:id:kazuhironagai77:20210301003118p:plain

キャラの生成する位置と角度を指定するとキャラを動的にSpawnしてくれます。

それぞれのLevelや戦闘が発生した場所で、キャラの生成する位置と角度は変わりますので、そこに対応出来る様にします。

f:id:kazuhironagai77:20210301003138p:plain

この部分はもっとマシな書き方があると思います。後で、少し考えます。今回はこれで行きます。

最後に、エラーが出た変数に値をパスします。これでエラー出ないはずです。

f:id:kazuhironagai77:20210301003202p:plain

テストします。

まずスタート画面です。

エラーの表示はありません。出来ています。

f:id:kazuhironagai77:20210301003228p:plain

出来ていますが、何か画面が異常に明るいです。

そうだ。ThirdPersonCharacterにPointLightを追加した事を忘れていました。ここではそのPointLightは切っておくべきですね。

「新しく始める」をクリックしました。

Map1が作成されました。

f:id:kazuhironagai77:20210301003250p:plain

特にエラーの発生はありません。落下してみます。

ゲームオーバーになりました。

f:id:kazuhironagai77:20210301003313p:plain

エラーの表示もないのでバグは直りました。

6.2 スタート画面の修正

スタート画面でPlayerの操作するキャラが明るすぎるのでそれを修正します。

以下の様に直しました。

f:id:kazuhironagai77:20210301003353p:plain

テストします。

f:id:kazuhironagai77:20210301003410p:plain

暗くなっています。

Map1に入ると今度はPlayerの操作するキャラは明るくなっています。

出来ています。

あれ?

Monsterが動いていません。

f:id:kazuhironagai77:20210301003430p:plain

新たなバグの発見です。

6.3 モンスターを動かす

何で動いてないんでしょうか?

AIが機能していないんでしょうか?

Behavior TreeのDebug機能で調べて見ると、Blackboard Decorator ノードであるIsRandomPlace?がFalseを返している事が分かりました。

f:id:kazuhironagai77:20210301003454p:plain

IsRandomPlaceノードの設定を見ると、以下に示した様に、Blackboardの変数、RandomPlaceの値をチェックしています。

f:id:kazuhironagai77:20210301003512p:plain

この値に問題があるみたいです。

BlackboardのRandomPlaceの値は、ServiceクラスであるFindRandomPlace内で指定されています。

FindRandomPlaceを見るとGetRandomReachablePointInRadiusがFalseを返してる事が分かります。

f:id:kazuhironagai77:20210301003531p:plain

更に、GetActorLocationはあるActorの位置情報は返してる事も分かりました。

と言う事は、GetRandomReachablePointInRadiusが適切な場所が見つけられないからモンスターは動いていないと言う事になります。

確認のために他のモンスターの場合も確認しましたが、以下に示した様に全く同じ問題が発生していました。

f:id:kazuhironagai77:20210301003558p:plain

何で、GetRandomReachablePointInRadiuが機能しないのでしょうか?

一番考えられるのは、NavMeshBoundVolumeが機能していない事です。

確認します。

NavMeshBoundVolumeは効いていませんでした。

取りあえず、左側のNavを動かしたらそれだけは効くようになりました。

f:id:kazuhironagai77:20210301003617p:plain

これでテストしてみます。

以下に示すように凄い勢いで追いかけて来ました。

f:id:kazuhironagai77:20210301003634p:plain

直りました。

6.4 以下のWarningについて

今週最後は、以下のWarningについて調べます。

f:id:kazuhironagai77:20210301003654p:plain

Output Logを読み直したらすぐ分かったのですが、これはPlayerStartを消した事から起きるみたいです。

f:id:kazuhironagai77:20210301003710p:plain

となると、直せませんね。もしPlayerStartを追加したら、戦闘マップから戻って来た時に、playerの操作するキャラの向きが一定になってしまいます。

Packagingの時とかに問題にならないと良いですね。

7.来週以降にやらないといけない事

今週中にバグ出しを終えたかったんですが、無理でした。以下に来週以降やらないといけない事をまとめておきます。

  • モンスターの歩く速度の設定がアニメーションとAIで全然違う
  • BGMの変更、町や村、モンスターが居る廃墟で別々のBGMにする。
  • BPの整理。RPGGameModeBPを整理します。
    • そこら中でThirdPersonCharacter変数に値をセットしている。過去、EventBeginPlay関数がBPから呼べなかったので毎回呼び出していた。これを直す。
    • 戦闘システムから呼ばれるEventを整理してまとめる。
  • セリフシステムの整理。確認出来るだけで3種類以上の方法でセリフを管理している。これを統一する。
  • 更なるバグだし。せめて1時間はこのゲームで遊んでバグ出しする。(今週は10分だった。)
  • Levelデザイン。

これらの事をやっていきます。

8.まとめと感想

今週はここまでです。戦闘マップから戻って来た時に、向きが変わってしまう問題は一応解決できました。Levelが10になるとゲームが止まってしまうバグは予想外でした。まだまだ、先は長いですが、ジグソーバズルが埋まって行く時に感じるような手ごたえを感じれるようになって来ました。