UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 村の地面をデコボコにする

f:id:kazuhironagai77:20201108221555p:plain

<前文>

HxHの念タイプがプログラマーにも良く当てはまる件について

HxHの念タイプは単なる空想の産物ですが、ソフトウェアエンジニアが受ける性格診断テストであるPersonality Types診断より真実を表してる気がします。知らない人にHxHの念タイプを簡単に説明すると以下の6つのタイプがあります。

  1. 強化系:兎に角、(念を)強化する。6種類の中で最も使い勝手が良いタイプ。当り。
  2. 変化系:元にあるものを変化させる。(念から電気に変化など。)
  3. 具現化系:(念から)新しい物を作り出す。
  4. 特質系:他のどれにも属さない。ガチャで言う激レア。他のタイプを超越した能力。
  5. 操作系:(念を)操作するのが得意。
  6. 放出系:(念を)放出するのが得意。

更に、これらのタイプ同士はお互いに関連していて、番号が隣り合っているタイプ(6は1と隣り合っている。)とは仲良しになりやすいとか。隣り合っている能力は(特質系を除き)それなりに習得できると紹介されています。特質系はこの中で最も優れていますが数は非常に少ないです。しかし特質系の隣りである操作系や放出系は、後天的に特質系になったりする。などの解説があります。

これを実際の職業や性格に当てはめてた場合、変な心理診断なんかより正しい診断が出来る気がしています。

例えば強化系ですが、普段はあまり練習や勉強をしないのに試合前や試験前は滅茶苦茶、集中して練習や勉強をするタイプの人がいます。自分の能力をその時だけ強化している訳です。これらのタイプの人は試合やテストの結果で、実力以上の成果を出す人が多いです。だから実社会でもある程度は成功しているはずです。つまりアタリのタイプです。

プログラマーに例えると「明日までにバグを直さなくてはならない。今日は徹夜。」みたいな状況で凄い力を発揮するタイプです。後、普段からある分野の勉強が好きでその分野に関しては誰よりも知っていると言うタイプの人も強化系だと思います。知識を強化している訳ですから。一緒に仕事していると一番頼りがいがあるタイプの人で、やっぱりアタリのタイプです。

変化系は、GitHub何かから既存のコードをコピペしてちょっとだけ変更して対応するタイプです。強化系の人から見ると勉強不足に見られる場合もあるかもしれませんが、実際それで動いてしまうんでプログラムに対しての見解の相違なんでしょうね。怠けるために努力するタイプとか、優秀だがサボる癖があるとか、言われる人に多いタイプです。

放出系は(知識を)放出するのが得意なタイプです。強化系の人が10知っているとその内の1しか話さないのに対して、放出系の人は1しか知らなくても10くらい話します。人に教える事で自分も上達するタイプでもあります。このタイプは講師や技術営業向きで、教えている内容が強化系の人から見るとちょっと間違えているように見えても、生徒や部外者からすると10倍くらい分かり易いので大変有り難い存在です。ただしHxHで行っている通り(感情を)放出するのも得意なので短気な人が多いです。

放出系の人は放出するための知識、変化系は変化元の知識が必要なので、強化系の人と仲良くする必要があります。一方で強化系の人にとって変化系の人は自分の成果を1.5倍にしてくれますし、放出系の人は自分の成果を10倍にも20倍にも拡大して宣伝してくれるので組むメリットは十分にあります。ので大抵、この3タイプはつるんでいます。これもHxHに書かれている通りです。

具現化系は習った知識で直ぐに何か作るタイプです。Linux kernelを作成したLinus Torvaldsや、アップルの創設者であるSteve Wozniakがこのタイプです。日本で言えば、世界で最初のCPUを作成した人とか、MMDを作った人、更にrubyを作った人なんかが具現化系タイプだと思います。そこまで有名な人でなくても休みの日にアプリを開発したり、サーバーを自作したりWeb siteを作成する人は具現化系です。

このタイプ、残念ながら一番外れです。能力に対して一番割食っているタイプです。テストなどの成績は強化系には勝てません。放出系ほどプレゼンも上手くありません。更に変化系ほど楽も出来ません。後述しますが、操作系はプログラマーの世界ではかなりの勝ち組ですので唯一の外れタイプです。

操作系は、ずばりハッカーです。彼らは他人のPCや企業のサーバーに侵入して自分の好きな様に操作します。多人数で遊ぶゲームでCheatingのツールを使用して自分だけ特別な操作が出来る様にしたりとか、ハッキングで得た大量の他人のIPからbotを使用してDDos攻撃をしたりとか、そこまでいかなくてもSpamを送ったり、兎に角、他人の資産を操作して自分のために使用する技術に長けています。このタイプ、具現化系と違いどんなにプログラミングに通じていても自分で何かを作成しようとは思いません。他人の作った物をどうやってコントロールする事しか考えません。

私がアメリカにいた時のルームメートの一人がまさにこのタイプでした。彼は電気工学の博士課程の生徒でCPU関連の研究をしていたんですが、ゲームが大好きで好きなゲームが発売されると勉強や研究そっちのけで一日中ゲームしているんです。そんなにゲームに人生を捧げている彼でも、敗北の時は来ます。そうなると彼は直ぐにCheatingのツールを制作してズルして戦うんです。そんなにゲームが好きならゲームそのものを作成すれば良いと思うんですが、ゲームを自分で作る事には興味が全くないんです。ゲームの中で勝つ事に極振りしているんです。

特質系とはプログラマー界のセレブや大金持ちになった人たちを指すと考えます。見事に具現化系と操作系からしか特質系になっていません。例えばビルゲイツ氏やスティーブジョブ氏。一見具現化系のようですが、彼らの経歴を知ると実際は操作系ですね。一方、Googleの創設者やIBMの創設者はその経歴を知ると完全に具現化系です。

こんな感じでHxHの念タイプによる分析は結構当たると個人的には思っています。

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

<本文>

f:id:kazuhironagai77:20201108221734p:plain

今週はこの中の「実際のゲーム内の町の地面をデコボコにする。」を行います。

10月4日のブログに書かれている通りLandScapeを使用して地面をデコボコに出来る事は確認しました。その時は以下の示した条件で作成しましたが、この条件が適切なのか全く分かりません。その辺から調べます。

f:id:kazuhironagai77:20201108221758p:plain

そしたら。実際のプロジェクト内の町にLandScapeを追加して町の地面をデコボコにします。

1. LandScapeの条件の確認と最適化

1.1 付属のSampleの数値を調べる

Medieval KingdomのサンプルMap1を調べて見ます。

f:id:kazuhironagai77:20201108221843p:plain

デコボコな地面はGround_Map_1で作成されています。

f:id:kazuhironagai77:20201108221900p:plain

Ground_Map_1はStaticMeshActorで作成されていました。

因みにデータのサイズは566KBです。

f:id:kazuhironagai77:20201108221920p:plain

うーん。

Landscapeで作成された場合、Landscapeと表示されています。

f:id:kazuhironagai77:20201108221942p:plain

f:id:kazuhironagai77:20201108221951p:plain

因みにLandscapeのデータのサイズは以下に示したように、大体9000KBでした。

f:id:kazuhironagai77:20201108222011p:plain

データのサイズが10以上違います。

2つの地面の大きさが全然違う可能性もあるので並べて比較してみました。

f:id:kazuhironagai77:20201108222048p:plain

SM_Ground_Map1から作成されたインスタンスの上を歩いて見ましたがLandscapeと比べて特に劣っていると感じる点はありませんでした。

f:id:kazuhironagai77:20201108222115p:plain

dataのサイズが十倍以上違うのは問題です。

Blenderか何かでSM_Ground_Map1のようなものを作成してimportすべきでしょうか?

うーん。

f:id:kazuhironagai77:20201108222139p:plain

Blenderで作成するとなると今週の予定から大きく外れますね。更にBlenderの使用方法の勉強もしないといけません。今はBlenderUE4を同期してBlenderでデザインしたのを即UE4で見れるようになっているらしいです。

先にlandscapeについて調べてみます。

あ。これってLevel全体のデータ量でした。

f:id:kazuhironagai77:20201108222159p:plain

Landscapeだけのデータ量は分かりませんね。

まず。Landscapeを作成する時に決定するparametersたちが実際の何を表しているのかを確認します。

f:id:kazuhironagai77:20201108222221p:plain

Section sizeが7x7 Quadsですが、以下に示した黄色の枠で覆った正方形の枠が7x7で表示されています。

f:id:kazuhironagai77:20201108222241p:plain

今度はSection sizeを15 x 15 Quadsに変更してみます。

f:id:kazuhironagai77:20201108222304p:plain

何と、黄色の枠で覆った正方形の枠は7x7で変化しませんでした。しかしその正方形内に存在する四角の数が

f:id:kazuhironagai77:20201108222322p:plain

15 x 15 Quadsに変化していました。

f:id:kazuhironagai77:20201108222349p:plain

ただし、この最小単位の正方形の大きさは一緒で、

f:id:kazuhironagai77:20201108222415p:plain

f:id:kazuhironagai77:20201108222423p:plain

結果としてLandscape全体のサイズが大きくなりました。

これらの事から推測するとSectionとは

f:id:kazuhironagai77:20201108222443p:plain

この黄色で囲った正方形の部分を指しています。

今度の   parameterはSection Per Componentです。

f:id:kazuhironagai77:20201108222507p:plain

を2x2に変更しました。

f:id:kazuhironagai77:20201108222525p:plain

f:id:kazuhironagai77:20201108222533p:plain

f:id:kazuhironagai77:20201108222551p:plain

に変化しました。4つのsectionが一個のcomponentに入っている状態です。

よし、これで分かりました。

まずLandscapeの最小単位の正方形のサイズは、どんなにparameterを変更しても同じです。変わりません。

次に、その最小単位の正方形を束ねる2つの単位があります。SectionとComponentです。

f:id:kazuhironagai77:20201108222626p:plain

通常1対1で設定されているのでSectionとComponentは同じですが、SectionはComponentの内側に存在しています。

一個一個のsectionのサイズはSection sizeで決定されます。

f:id:kazuhironagai77:20201108222644p:plain

一個一個の最小単位の正方形、Quadsのサイズは同じなので数が多くなるほどSectionのサイズは大きくなります。

最後にComponentの数を決定出来ます。

f:id:kazuhironagai77:20201108222708p:plain

これでLandScapeの大きさは決定されます。

はい。ここで疑問です。

Section/componentは1x1 sectionで固定したと仮定します。

Landscapeの大きさは同じで、sectionのサイズを大きくしてcomponentの数を小さくした場合と、sectionのサイズは小さくしてcomponentの数を大きくした場合はどちらがデータが小さくなるのでしょうか?

このサイトにComponentについての説明がありました。

更にお勧めの設定が載っていました。

f:id:kazuhironagai77:20201108222735p:plain

このページのお勧めの設定の中でmapの地面のサイズに最も近い奴を選択すると

f:id:kazuhironagai77:20201108222756p:plain

この二つになります。下の設定を使用しました。

f:id:kazuhironagai77:20201108222818p:plain

すこし大きいですね。

f:id:kazuhironagai77:20201108222853p:plain

こんな感じです。

でもこれでLandscapeのparameterの最適解は分かりました。

後は、Landscapeのデータのサイズが分かれば最高なんですがどこにLandscapeのデータを保持しているのかが分かりません。

ただ分からないですが、Landscapeのデータのサイズは凄い小さい気がします。ので今回はLandscapeでやる事にします。

2. LandScapeを追加して村の地面をデコボコにする

それでは実際に作成します。

f:id:kazuhironagai77:20201108222930p:plain

f:id:kazuhironagai77:20201108222937p:plain

で作成します。

f:id:kazuhironagai77:20201108222957p:plain

f:id:kazuhironagai77:20201108223007p:plain

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

中を見るとこんな感じです。

f:id:kazuhironagai77:20201108223026p:plain

f:id:kazuhironagai77:20201108223034p:plain

f:id:kazuhironagai77:20201108223044p:plain

大分、真っ平ら感が無くなりました。

うーん。もっと難しいと思っていたのですが簡単に出来ました。

3. 村の制作のTutorialをみて勉強する

3.1 Fantasy village: Unreal Engine 4 - Landscape - UE4 - Environment Design

このサイトのビデオです。

20分程度見ましたが特に勉強になる事はありませんでした。Landscapeのデザインと言っていますが実際は、landscapeは既に完成していてその上にレベルデザインをしているだけです。そのレベルデザインの手法も知らないようなテクニックは使用されていませんでした。

1~2年前にLevel deignにチャレンジした時は、滅茶苦茶なマップしか作れませんでしたが、その間に特に練習した訳ではありませんが、今回はかなり綺麗なdesignが出来ました。

それで率直な感想ですが、Level design自体にはそんなに勉強する事ないんじゃないかなと思いました。

にも関わらずLevel designをする人が少ないのは気になります。作成した作品に対して著作権が付きにくいなどの制作意欲を削ぐ問題があるのかもしれません。

これで今週の予定であるLandscapeの勉強は終りですが、時間が大幅に余ってしまったので、次の課題である昼と夜の作成の続きをやります。

4. 昼と夜の追加の続き

10月4日のブログで昼と夜をGood Skyを使用して作成しましたが、一端時間を指定したら途中で変化させる事は出来なくなりました。Good Skyの機能をもっと良く調べて昼と夜を自由に変化させたいと思います。

4.1 Good Skyの復習

Good Sky のSky Beta項目に以下に示したような設定でセットすると自動で昼と夜になります。

f:id:kazuhironagai77:20201108223145p:plain

こんな感じです。

f:id:kazuhironagai77:20201108223207p:plain

f:id:kazuhironagai77:20201108223213p:plain

f:id:kazuhironagai77:20201108223222p:plain

しかし自主的に昼と夜を変える事は出来ませんでした。

4.2 別な方法で昼と夜を自主的に変える。

色々試した結果。以下の2つの事が判明しました。

4.2.1 判明した事実

1. “Enable Auto Day/Night Cycle in Game?”にチェックを入れると完全にオート化してしまいます。

f:id:kazuhironagai77:20201108223304p:plain

以下に示した方法で、play中にEnable Auto Day/Night Cycle in Game?をoffにセットしても昼と夜は自動で変化し続けます。

f:id:kazuhironagai77:20201108223357p:plain

2. “Enable Auto Day/Night Cycle in Game?” のチェックを外した状態(以下に示したような設定の場合)Directional Light Actorにセットしたdirectional lightのY軸の値を変化させる事で昼夜を変化させる事が出来ます。

f:id:kazuhironagai77:20201108223432p:plain

以下の方法で、Directional lightのY軸の角度を50度に変更します。

f:id:kazuhironagai77:20201108223451p:plain

f:id:kazuhironagai77:20201108223500p:plain

こんな感じになります。

f:id:kazuhironagai77:20201108223520p:plain

が、

f:id:kazuhironagai77:20201108223538p:plain

です。

4.2.2 昼と夜の実装

これらの事実を利用して以下のコードを実装しました。

f:id:kazuhironagai77:20201108223603p:plain

はい。   “Enable Auto Day/Night Cycle in Game?” のチェックを外した状態で、昼と夜を自動で表現出来る様になりました。

f:id:kazuhironagai77:20201108223633p:plain

f:id:kazuhironagai77:20201108223641p:plain

f:id:kazuhironagai77:20201108223649p:plain

f:id:kazuhironagai77:20201108223657p:plain

4.3 宿屋に泊まって寝た後は必ず朝になる

当然な事です。しかし“Enable Auto Day/Night Cycle in Game?” のチェックが入った状態だと、外部の操作を全く受け付けないのでこれが実現出来ませんでした。しかし4.2.2で制作した方法なら単にTimeSpend変数の値を0にセットし直すだけで朝に戻るはずです。

以下のコードで試してみます。

f:id:kazuhironagai77:20201108223722p:plain

夜になるのを待ってIを押します。

f:id:kazuhironagai77:20201108223745p:plain

朝になりました。

f:id:kazuhironagai77:20201108223806p:plain

4.4 戦闘時に別なmapに飛んで戦闘終了後に戻ってくる時、時間は止まっているべき

まだ作成していませんが、戦闘時は別なmapに飛んで戦う予定です。戦闘終了後に元のmapに戻ってきたら、何もしなければ必ず朝になってしまいます。これの対策をします。

別なmapに移れば、GameInstanceクラス以外で保持しているデータは全て消えてしまうので、Directional lightのY軸の角度はGameInstanceクラスで保持する必要があります。

GameInstanceクラスにFloatタイプの変数、DirectionalLightAngleYを作成します。

f:id:kazuhironagai77:20201108223835p:plain

新しいmapを開く前に、TimeSpend変数の値をGameInstanceクラスの変数、DirectionalLightAngleYにセットします。

f:id:kazuhironagai77:20201108223856p:plain

もう一度、mapを開く時はTimeSpend変数の値はGameInstanceのDirectionalLightAngleY変数からコピーします。

f:id:kazuhironagai77:20201108223916p:plain

こんな感じで時刻を保持して別なmapに移動して戦闘し、戦闘終了後にその時刻に戻ってくる事が出来るはずです。

f:id:kazuhironagai77:20201108223936p:plain

Uを押して別なマップに移動して戻ってきます。

f:id:kazuhironagai77:20201108223956p:plain

同じ時刻に戻ってきました。

4.5 時刻の管理にFrame rateに頼っている件について

全部上手く行っているように見えますが、実はこのやり方、Tick()関数のDelta secondが0.008333秒である事を前提に定数6を掛けています。

f:id:kazuhironagai77:20201108224020p:plain

一日を3時間程度に設定しようと思っているのですがTick()関数のDelta secondが変わるとこの定数である6.0も変える必要がある気がしています。これについて検証します。

上記の計算と全く同じ計算をエクセル上で再現してDelta Secondsが1秒の場合と0.5秒の場合の0から60秒における値の変化を計算しました。

f:id:kazuhironagai77:20201108224039p:plain

全く変わりませんでした。

この結果から推測するに定数の6.0はDelta Secondsが変わっても変える必要はないみたいです。

確かにこの結果を見て考えるとFrame rateが大きくなれば、Delta Secondsは小さくなるので結果は同じになってもオカシクはないです。

うーん。1時間位、この問題について考えていました。結果的にはこの問題は杞憂でした。考える必要はなかったですね。

5. 昼と夜をプロジェクトに追加する

Ch4_3にgood skyを追加して昼夜を作成します。

だだし。Ch4_3にはレベルが複数あり、それぞれにgood sky BPを追加する必要があります。その辺りをどのように実現するか考えなければなりません。

5.1 前節で作成したのと機能をCh4_3のmap1に作成します。

取りあえずは、前節で作成したのと全く同じ物をmap1に作成します。

何故か赤いです。

f:id:kazuhironagai77:20201108224119p:plain

滅茶苦茶調べました。

SkyLightのMobilityをStaticに変更したら直りました。

f:id:kazuhironagai77:20201108224137p:plain

f:id:kazuhironagai77:20201108224147p:plain

理由は分かりません。

f:id:kazuhironagai77:20201108224212p:plain

f:id:kazuhironagai77:20201108224218p:plain

f:id:kazuhironagai77:20201108224227p:plain

f:id:kazuhironagai77:20201108224236p:plain

全体的に暗いです。

Auto Exposureの設定を元に戻しました。

f:id:kazuhironagai77:20201108224305p:plain

これはいい感じになりました。

f:id:kazuhironagai77:20201108224325p:plain

5.2 宿屋に泊まったら朝になるようにセットします。

これ簡単だと思っていたんですが、何とLevel BPの変数は他のBPから呼び出す事は出来ないんだそうです。仕方ないので以下の様にしました。

宿屋のWidgetであるInn_Welcomeで泊まるボタンをクリックした時に、以下のコードが実行されます。

f:id:kazuhironagai77:20201108224351p:plain

そしてGameInstanceクラスのその変数をLevelBPでFrame毎にチェックします。

f:id:kazuhironagai77:20201108224409p:plain

Trueだった場合はLevelBPのTimeSpend変数の値を0にセットします。

f:id:kazuhironagai77:20201108224427p:plain

テスト結果を示します。

夜に宿屋に泊まります。

f:id:kazuhironagai77:20201108224446p:plain

朝になりました。

f:id:kazuhironagai77:20201108224503p:plain

一瞬で朝になるので、BGMの変化があるいは、5秒間位の睡眠中のアニメーションを追加する必要がありそうです。後でやります。

出来ました。出来ましたがFrame毎にGameInstanceクラスの変数の値をチェックすると言うかなりコストの掛かる事をしなければならなくなりました。Event dispatcherを利用したらLevelBPと他のBPの連絡も取れやすく成ったりしないんでしょうか?これも後で調べて見ます。

5.3 戦闘後に元のmapに戻っても時間は一緒にする

前節で説明した通り、戦闘時は別なmapに飛んで戦う予定です。戦闘終了後に元のmapに戻ってきたら必ず朝になってしまいます。これを直します。

やり方は前節と全く同じです。Iを押したら、別なmapに移動します。その時GameInstanceクラスのTimeSpend変数に今のLevelBPのTimeSpend変数の値をコピーします。

f:id:kazuhironagai77:20201108224535p:plain

そしてもう一度、このmapを開くときは、さっきとは逆にLevelBPのTimeSpend変数にGameInstanceクラスのTimeSpend変数の値をコピーします。

f:id:kazuhironagai77:20201108224650p:plain

テストします。

f:id:kazuhironagai77:20201108224715p:plain

戻って来た時も時刻は同じです。ただし場所は変わっています。これは後で直します。

f:id:kazuhironagai77:20201108224734p:plain

 6. まとめと感想

今週はここまでです。最も大変と思っていたLandscapeの箇所が簡単だったので来週やる予定だったGoodSkyを使用して昼夜を再現する部分もやりました。来週は戦闘システムの改良を行います。