UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 村人用のAIの開発 とWorld Compositionの設定Part2

f:id:kazuhironagai77:20211114211542p:plain

<前文>

前文には、日本人が誤解しているアメリカ、特に日本文化とキリスト教文化の違いから生じる誤解とその対策について在米歴10年の私が気が付く範囲ですが書いておきます。

<英語はテニス、日本語はボーリング>

これって私がアメリカに行ったばっかしの時に日系人の人から教えてもらった話で、日本人の英語を勉強する人達の間では結構有名な話だと思っていたんですが、知らない人もいるみたいなんでもう一回解説します。

日本語しか知らない人は会話のやり方にもルールがあるなんて夢にも思わないかもしれませんが、実際は会話をする時は暗黙のルールがあってみんなそれに従ってしゃべっています。その会話のルールが英語と日本語だと違うという話です。

その会話のルールが英語の会話はテニス、日本語の会話はボーリングに似ているだそうです。

英語の会話ではテニスのように、必ず相手の発言に対して打ち返す必要があります(ただし一部の日本人がするように会話を遮って自分の話をするのはもっとルール違反です。適切なタイミングで言い返す必要があります)。ところが日本語の会話のルールだとボーリングのように誰かが発言したら、それをみんなで見て(聞いて)いないといけません。日本で育った私には誰かの発言に対して打ち返すなんて発想はまるでなかったです。

日本語の会話のルールだと相手が喋り終わるまで、おとなしく聞いているのが正しいのですが、英語の会話のルールでそれをやっていると会話をする気がないとみなされて激怒されてしまいます。

これを聞いてハイ分かりました。と直ぐに出来る様にはなりません。(実際、多人数の会話で私がそれが出来る様になったのはそれから何年も後の事でしたし。)しかし目指す方向はこの話から理解出来ました。

トヨタと電気自動車>

トヨタは日本で最も外貨を稼いでいる会社みたいですが、この英語の会話においてもっとも基本である打ち返すと言う行為を全くしない会社です。前もPriusの事故でアメリカの消費者から訴えられた時に、アメリカ人から沢山の会話のボールが投げられたにも拘わらず全て無視してとうとうアメリカを激怒させる事態になってしまいました。

今回、電気自動車と地球温暖化防止の問題で、またトヨタがやり玉に挙げられています。

今回も前のように英語圏からの発言に対して無視し続けたら、前回以上の惨事になります。

欧米人が怒っているのは、トヨタ地球温暖化防止のための電気自動車の普及に反対しているからではなくて、自分達の発言に対してトヨタが無視しているからなんです。

英語の出来ない日本人が英語と日本語は会話のルールが違うなんて夢にも思わないのと同じように、欧米人も日本語の会話のルールがヨーロッパ言語と全く違うなんて夢にも思っていません。単に失礼な態度を取っていると思われています。

<私が考える解決策>

怒れる欧米人達を無視し続けるのは、あまり良い対策とは思えません。と言うか最悪の対応です。このまま行くと前のPriusの事件よりも恐ろしい事態を引き起こす可能性もあります。

ここに私が考える最悪の事態を避ける為の解決策を書いて置きます。

<<Redditで直接、質問を受け付けそれに解答する>>

はい。

Elon MuskとかBill Gatesとかが良くやっていますが、トヨタの社長がRedditで直接、質問に対して回答するんです。

別に、相手の意見に無理に同意する必要はありません。単に自分たちが何で環境保全の観点から水素の方が電気より優れていると思っているかを正直に説明するだけで良いんです。

知らない事は知らないで十分です。

へんな質問をする奴や、はなから文句を言うつもりの奴はRedditのルールに基づいてBlockすれば良いだけです。

これやったらトヨタは我々の意見を無視していると言う主張を真っ向から消滅する事が出来ます。

無視していない以上、欧米の電気自動車推進派はトヨタに対して激怒する訳にはいかなくなります。怒ると言う行為自体がキリスト教の大罪の一つですからよっぽど理由がないと怒れないんです。

<<科学系のYoutuberとコラボ>>

流石にRedditで一般人からの質問に一々回答するのは難しい場合は、英語圏の科学系のYoutuberとコラボすれば良いです。

ただし社長が直接、表に出ないと駄目です。そこで社長が科学系のYoutuberに対して説明してそのYoutuberが視聴者に説明すると言う2段戦法です。

<前文まとめ>

昔の日本では、クジラの肉を普通に食べていたそうです。クジラが絶滅しそうになった原因はアメリカが鯨油をとる為に乱獲したからでもあります。

しかしそんな事はどうでもよくて、今となってはクジラの肉を食べるのは日本人にとってもかなりの勇気がいる行為になりました。

このままトヨタが何も対策を打たないとトヨタの車を買うのはクジラの肉を食べる位の勇気がいるような近未来が来る気がします。

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

<本文>

1.今週の予定

今週は以下の内容をやっていきます。

  • Niagara: 先週の復習
  • Material : Ben Cloward氏のTutorialを勉強する
  • NPCのAIを作成するためのAIの復習の続き(Perceptionの勉強)
  • World CompositionによるMap1の作成(Bugの修正)
  • UE5におけるWorld Partitionの勉強の続き

2.Niagara: 先週の復習

2.1 Twisted Ribbon in UE4.27 Niagara Tutorial [1]の復習

先週、勉強したTwisted Ribbon in UE4.27 Niagara Tutorial [1]のNodeや関数などで知らない機能などを復習します。

<Return Normalized Exec Index

これです。

f:id:kazuhironagai77:20211114211747p:plain

Dynamic Input Parameterの一つです。

Cursorを合わせると以下の解説が表示されます。

f:id:kazuhironagai77:20211114211801p:plain

0から1の間の数字を返す事以外は不明ですね。

中身を見てみます。

f:id:kazuhironagai77:20211114211815p:plain

これだけです。

f:id:kazuhironagai77:20211114211829p:plain

あれ。これって見た記憶があります。

あ。

先週この辺までは調べていました。

先週、調べたりない所を調べます。

Execution Countの機能に関しては、

f:id:kazuhironagai77:20211114211842p:plain

と推測しています。

でもこれが合っているのか不明です。今、読んでみるとなんでそう思えるのかの根拠が書かれていませんし。

色々調べてみましたがこのDynamic Inputに関しての資料は見つかりませんでした。

実験してみる事にします。

以下の様な最も基本的なEmitterを組みます。

f:id:kazuhironagai77:20211114211855p:plain

Spawn Rateは1にセットします。

f:id:kazuhironagai77:20211114211908p:plain

Life Timeも1にセットしました。

f:id:kazuhironagai77:20211114211920p:plain

こんな感じです。

f:id:kazuhironagai77:20211114211933p:plain

ここのParticle Update SectionにSet Positionを追加します。

f:id:kazuhironagai77:20211114211956p:plain

そしてParticleのPositionのXにReturn Normalized Exec Indexをセットします。

f:id:kazuhironagai77:20211114212009p:plain

これでReturn Normalized Exec Indexの値の変化に伴ってX方向にSpriteが移動するはずです。

結果です。

f:id:kazuhironagai77:20211114212022p:plain

なんの変化もありません。

Spawn Rateを5にしてみました。

f:id:kazuhironagai77:20211114212035p:plain

僅かな動きか観測されました。

動きを大きくするためにNormalized Index Scaleに20をセットします。

f:id:kazuhironagai77:20211114212048p:plain

こんな感じです。

f:id:kazuhironagai77:20211114212115g:plain

これを見ると、同時期に生存しているParticleの間で0から1の値が割り振られているみたいです。最初に生成されたParticleが0、最後に生成されたParticleが1の値を持っているようです。

この仮説を検証するためにSpawn Rateの値を変更してみます。

Spawn Rate=2の時です。

f:id:kazuhironagai77:20211114212148p:plain

f:id:kazuhironagai77:20211114212156p:plain

二つ発生しています。Return Normalized Exec Indexの値はそれぞれ0と1と考えられます。

Spawn Rate =3の時です。

f:id:kazuhironagai77:20211114212216p:plain

はい。想像した通りの結果になりました。Return Normalized Exec Indexの値はそれぞれ0と0.5と1と考えられます。

これからSpriteの数を増やすのにSprite同士が重なると見にくいのでSpriteのサイズを半分にしました。

f:id:kazuhironagai77:20211114212229p:plain

f:id:kazuhironagai77:20211114212234p:plain

Spawn Rate =4の時です。

f:id:kazuhironagai77:20211114212250p:plain

4つSpriteが発生しています。

Return Normalized Exec Indexの値はそれぞれ0と0.25、0.5、0.75、1となっているはずです。

今度はLife Timeを変更してみます。

Spawn Rateを1に戻します。

Life Timeの値を1から2に変更します。

これでSpriteは一秒間に一回生成され、それぞれのSpriteの寿命は2秒になるので同時に存在するSpriteは2個になります。と言う事はReturn Normalized Exec Indexの値はそれぞれのSpriteで0と1になるはずです。

f:id:kazuhironagai77:20211114212304p:plain

なっていました。

Return Normalized Exec Indexの値は実際はどうなっているのかは分かりませんが、現象としては、

同時期に現れるSpriteの中での現れた順番(ただし最初は0/同時期に現れるSpriteの数

の値が入っているようです。

今度はSpawn Burt Instantaneous Moduleで試してみます。

f:id:kazuhironagai77:20211114212326p:plain

Spawn Countを3にしました。

f:id:kazuhironagai77:20211114212351p:plain

これで0、0.5.1にSpriteが発生するはずです。

f:id:kazuhironagai77:20211114212542p:plain

してました。

確認のためにSpawn Countを4にします。

f:id:kazuhironagai77:20211114212556p:plain

はい。予測通りの結果が出ました。

となるとTwisted Ribbon in UE4.27 Niagara Tutorial [1]でReturn Normalized Exec Indexを使用した理由は、単にRibbonの長さを1にするためだったと言う事でしょうか?

先週と同じ形をもう一回作成しました。

f:id:kazuhironagai77:20211114212611p:plain

Return Normalized Exec IndexのScalingの値を2にしました。

f:id:kazuhironagai77:20211114212624p:plain

Tubeの長さが2倍になりました。

f:id:kazuhironagai77:20211114212637p:plain

うーん。

2021-07-04のBlogで解説しているRibbonの構成をしたに示しますが、

f:id:kazuhironagai77:20211114212651p:plain

この緑色のParticleの位置が均等に配置される効果もあるかもしれませんが、Return Normalized Exec Indexを使用した理由は、基本的には単にRibbonの長さを1にするためだったようです。

以下の部分ですがTutorial内で説明がありました。

f:id:kazuhironagai77:20211114212704p:plain

Spawn RateでRibbonのためのParticleを次々と作成しているのでJittery thingが出来ています。それを無くすためにSpawn Burst Instantaneous Moduleを使用します。

Jittery Thingって以下に示した縞々が動いている時にちょっとだけつぶれて見える事を言っているんでしょうか?

f:id:kazuhironagai77:20211114212719p:plain

こんな感じです。

f:id:kazuhironagai77:20211114212811g:plain

Spawn Burst Instantaneous Module に変更したら一瞬だけRibbonが表示されるようになってしまいました。

f:id:kazuhironagai77:20211114212839p:plain

それでEmitter Update SectionのEmitter State Module

f:id:kazuhironagai77:20211114212851p:plain

のLoop BehaviorをOnceにして

f:id:kazuhironagai77:20211114212907p:plain

Particle Update SectionのParticle State Moduleの

f:id:kazuhironagai77:20211114212940p:plain

Kill Particle When Life Time Has ElapsedのCheckを外します。

f:id:kazuhironagai77:20211114212954p:plain

するとRibbonがずっと表示されるようになりました。

f:id:kazuhironagai77:20211114213009p:plain

今度は先程のようなJittery thingは無くなっています。

f:id:kazuhironagai77:20211114213031g:plain

これってSpawn Burst Instantaneous Moduleを使用すれば別にこの方法じゃなくても消せるはずですよね。

別な方法を試してみます。

Particle Spawn SectionのInitialize Ribbon ModuleのLife Timeの値を5にしました。

f:id:kazuhironagai77:20211114213115p:plain

これだと5秒間はRibbonを表示していますが、その後一瞬だけ消えてしまいます。

うーん。だからこっちを使用してるんですね。

f:id:kazuhironagai77:20211114213132p:plain

大体納得しました。

RibbonにCurveをつける>

この部分は読み直したら大体理解出来ましたが、先週のBlogには何をやっているのか不明と書いていたので一応解説します。

f:id:kazuhironagai77:20211114213206p:plain

Ribbon Link Order変数にはそれぞれのParticleの番号が入っています。

f:id:kazuhironagai77:20211114213241p:plain

その番号に対して50だったらZ軸に対して100の位置、100だったらZ軸に対して0の位置と指定しています。

その結果、

f:id:kazuhironagai77:20211114213255p:plain

こんな曲がった形のRibbonを作製する事が出来ます。

でもそれならReturn Normalized Exec Index 変数を使用して範囲を0から1の間にしても同じだと思うんですが。

f:id:kazuhironagai77:20211114213310p:plain

ほら、同じ結果が出ています。

f:id:kazuhironagai77:20211114213326p:plain

この場合はこれも要らないですし。

f:id:kazuhironagai77:20211114213344p:plain

あれ?

Execution IndexをRibbon Link Orderにセットしなかったら以下のようになってしまいました。

f:id:kazuhironagai77:20211114213401p:plain

何か勘違いしている?

Ribbon Link Order変数の解説を以下に示します。

f:id:kazuhironagai77:20211114213415p:plain

これ読むと、Ribbon Link OrderはParticle同士をRibbonで繋げる時の順番を指定するための変数だったです。

つまりここでRibbonを作る順番をExecution Index通りにしないとさっきのようにグチャグチャになってしまう訳です。

f:id:kazuhironagai77:20211114213430p:plain

ふーん。これはRibbonのEffectを作製する時に結構役立ちそうな情報ですね。

勉強になりました。

<Material内のノードについて>

<<Panner>>

Pannerノードは、基本的なノードらしいですが使用したの初めてです。

f:id:kazuhironagai77:20211114213454p:plain

こんな解説がしてありました。

f:id:kazuhironagai77:20211114213511p:plain

これだけ読むとPannerは単にTextureを動かすノードですね。

試しに以下のMaterialを組んでみましたが

f:id:kazuhironagai77:20211114213525p:plain

f:id:kazuhironagai77:20211114213530p:plain

動いていますね。

f:id:kazuhironagai77:20211114213547g:plain

<Step

f:id:kazuhironagai77:20211114213615p:plain

このStep、公式のDocumentが見つかりません。

これを見てもView Documentationが選択出来ない状態になっています。

f:id:kazuhironagai77:20211114213632p:plain

うーん。

Stepという単語があまりに一般的過ぎてDocumentまでたどり着けないのかな?

Groupを見るとMathに属しています。

f:id:kazuhironagai77:20211114213648p:plain

公式のDocumentのMath Expressions [2]を見ましたが載ってませんでした。

うーん。

分からん。

Ben Cloward氏のSmoothstep - Shader Graph Basics - Episode 15 [3] なら検索に出て来ます。

なんかヒントになるかもしれないと見てたら、Unityで解説しています。

f:id:kazuhironagai77:20211114213702p:plain

うん。ひょっとしてUnityにStepってNodeがあって、しかも機能的にもUnrealと一緒だったりして。

ちょっと探して見ます。

Unity公式のDocumentにStep Node [3] がありました。

f:id:kazuhironagai77:20211114213716p:plain

これを見るとInの値がEdgeの値より大きかったら1を小さかったら0を返すとあります。

UEでも同じでしょうか?

試してみます。

f:id:kazuhironagai77:20211114213731p:plain

こんな感じです。

f:id:kazuhironagai77:20211114213743p:plain

1が返って来た。と言う事でしょうか?

X>Yだと1が返る。と言う事でしょうか?

X<Yにしてみました。

f:id:kazuhironagai77:20211114213757p:plain

今度は黒いです。

f:id:kazuhironagai77:20211114213811p:plain

XがUnityのInと同じでYがUnityのEdgeと同じみたいですね。

うん。

まあ機能が理解出来たのでTextureの時にどうなるかを見てみます。

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

f:id:kazuhironagai77:20211114213827p:plain

Fresnelは以下の様に設定しました。

f:id:kazuhironagai77:20211114213840p:plain

結構白い部分が多いです。

X>Yの部分は白く、Y>Xの部分は黒くなるはずです。

X=0.2 の場合です。

f:id:kazuhironagai77:20211114213854p:plain

X=0.5です。

f:id:kazuhironagai77:20211114213907p:plain

X=0.8 の場合です。

f:id:kazuhironagai77:20211114213919p:plain

ああ、分かりました。

Twisted Ribbon in UE4.27 Niagara Tutorial [1]では

f:id:kazuhironagai77:20211114213936p:plain

黒い部分を透明にしているんです。

確認のために以下の実装をしてみました。

f:id:kazuhironagai77:20211114213949p:plain

穴あいています。

f:id:kazuhironagai77:20211114214002p:plain

はい。Stepの意味も何とか理解しました。

<Set Particle Position Moduleの位置の移動>

f:id:kazuhironagai77:20211114214024p:plain

これは意味を理解した今なら簡単でSet Particle Position ModuleはScratch Moduleの後ならどこでも良いです。

f:id:kazuhironagai77:20211114214042p:plain

Set Particle Position Moduleを使用する前にRibbon Link Order変数にExecution Indexの値をAssignしておく必要があります。

f:id:kazuhironagai77:20211114214110p:plain

のでこれでも大丈夫です。

因みにこれを忘れると先程のように以下のような変な形のRibbonが出来ます。

f:id:kazuhironagai77:20211114214141p:plain

以上です。

2.2 Twisted Ribbon in UE4.27 Niagara Tutorial [1]の残りをやる

色やWidthを変えて以下の様にしました。

f:id:kazuhironagai77:20211114214201p:plain

EmitterをDuplicateして色やサイズを変更します。

f:id:kazuhironagai77:20211114214215p:plain

こんな感じです。

f:id:kazuhironagai77:20211114214230p:plain

うーん。

今度はこのEffectをBPからControlするための実装をしていきます。

まずUser Parameterに以下の変数を作製しました。

f:id:kazuhironagai77:20211114214242p:plain

あ。もう分かりました。

この変数たちをそれぞれのParameterにセットしていくわけですね。

Particle Update SectionのSet PositionのXのAにLength変数をセットします。

f:id:kazuhironagai77:20211114214255p:plain

Particle Update SectionのSet Ribbon TwistのAのAにTwist Speed変数をセットします。

f:id:kazuhironagai77:20211114214309p:plain

Particle Update SectionのScale Ribbon Width ModuleのScale CurveにWidth変数をセットします。

f:id:kazuhironagai77:20211114214324p:plain

あれ。二つ目のEmitterのScale Curveに同じ値はセット出来ませんよね。

f:id:kazuhironagai77:20211114214337p:plain

こうしました。

そう言えばCurve変数は?

Curve変数を抜かしていました。

Particle Update SectionのSet PositionのScale CurveにCurve変数をセットします。

f:id:kazuhironagai77:20211114214352p:plain

この後、BPからこれらの値をセットしていますが説明が簡単過ぎて何をしているのか良く分かりません。

自分で作ってみます。

ActorにComponentとして今作成したNSをつけます。

f:id:kazuhironagai77:20211114214406p:plain

それぞれのUser Parameterの変数にActorの変数をセットします。

f:id:kazuhironagai77:20211114214423p:plain

取りあえずはこれでテストします。

f:id:kazuhironagai77:20211114214442p:plain

こんな感じです。

f:id:kazuhironagai77:20211114214457p:plain

Lengthを2倍にしてみます。

f:id:kazuhironagai77:20211114214510p:plain

Ribbonの長さが2倍になりましたね。

Curveを2倍にしました。

f:id:kazuhironagai77:20211114214526p:plain

Twist Speedを9から3に変更しました。

f:id:kazuhironagai77:20211114214540p:plain

これはあんまり変化してないです。

最後にWidthを1.5倍にします。

f:id:kazuhironagai77:20211114214557p:plain

はい。

Tutorialのとはかなり違いますがUser Parameterの値をBPから呼び出せたのでOKとします。

一つこのNSに不満があるのですが、どこにこのActorを置いてもこのNSが出現するのは原点からになります。

この点は改良したいです。

2.3 Twisted Ribbon in UE4.27 Niagara Tutorial [1]の発生場所を調節する

どこにこのActorを置いてもこのNSが出現するのは原点からになるのはParticle のPositionに元のPositionの値を足してないからだと思っています。

これを試してみます。

取りあえず金色のRibbonのだけParticleのPositionを追加してみました。

f:id:kazuhironagai77:20211114214617p:plain

金色のRibbonの部分がBeamみたいに飛んでいきました。

f:id:kazuhironagai77:20211114214631p:plain

うーん。もう少し考えないといけないですね。

これは来週考える事にします。

3.Material : Ben Cloward氏のTutorialを勉強する

3.1 Smoothstep - Shader Graph Basics - Episode 15 [3] を勉強する

もうこれは運命みたいなもんですね。今週はSmoothstep - Shader Graph Basics - Episode 15 [3]を勉強します。

まずぱっと全部見ました。

うーん。今回はUnityとUEで紹介しているSmooth Stepを使用した応用例が違いますね。どちらかと言うとUnityで作成したヤツの方が興味深いです。UE5の応用例はLandscapeを勉強した時に似た機能を既に勉強していますし。Unityで紹介されている応用例もUE5で作成してみます。

<理論>

Smoothstep - Shader Graph Basics - Episode 15 [3]も最初はGraphを使用して数式の解説から始まっています。

私もDesmosのGraphic Calculatorを使用してTutorialと同じ図を作製します。

f:id:kazuhironagai77:20211114214709p:plain

ほぼ同じGraphを作製しました。

Powerの時の勉強でやりましたが、Materialでは色などを0から1の間の数字で表すので、xが0の時にyが0、xが1の時にyが1である関数は非常に重要です。

Smooth Stepに使用されている関数は、xが0の時にyが0、xが1の時にyが1でありかつ0から1への変化が滑らかな曲線で行われています。

どうやってその関数を作製したのかをここで解説しています。

<<y=x>>

最初の式はy=xです。

f:id:kazuhironagai77:20211114214730p:plain

これは単にxが0の時にyが0、xが1の時にyが1である式の一例として紹介しただけのようです。

この式は直線ですので滑らかな曲線はどこにもないですね。

<<y =x ^2>>

f:id:kazuhironagai77:20211114214750p:plain

Y=x^2のGraphです。

まずこの関数で描かれる線はxが0の時にyが0、xが1の時にyが1でしかも曲線です。

しかしよく見ると0から0.2までは滑らか曲線ですが、0.8から1までは結構激しく曲がっています。0.8から1の間はもっと滑らかな曲線がほしいです。

<<y = 1- (x-1)^2>>

f:id:kazuhironagai77:20211114214810p:plain

y = 1- (x-1)^2ってあまり馴染みのない関数ですが、この関数、0.8から1の間がとても滑らかな曲線を描いています。

しかも先程のy = x^2と正反対の曲線を描いています。

f:id:kazuhironagai77:20211114214824p:plain

当然ですが、0から0.2位まではy=x^2、0.8から1まではこの関数と同じ結果を出す関数がほしくなります。

それが次の関数になります。

<<y =x^2 (3-2x)>>

f:id:kazuhironagai77:20211114214842p:plain

どうやってこの関数を発見したのか検討も付かないですが、兎に角この関数だと0から0.2位まではy=x^2、0.8から1まではy = 1- (x-1)^2と同じような滑らかな曲線を示しています。

おお。これをSmooth Stepで使用しているのかと思ったらこの関数でもまだ完璧ではなくて

f:id:kazuhironagai77:20211114214857p:plain

0より小さい値はずっと0、1より大きい値はずっと1にしたいんです。

それで最後の式が登場します。

<<q = max (0, min(1,x))の時、y = q^2(3-2q)>>

f:id:kazuhironagai77:20211114214916p:plain

はい。これが今まで述べた全ての条件を満たした関数です。

<Smooth Stepノードの基本>

Tutorialの例とはちょっと違いますがこっちの方がSmooth Stepの機能がはっきり分かるのでこの実装で検証します。

f:id:kazuhironagai77:20211114214947p:plain

こんな結果です。

f:id:kazuhironagai77:20211114215002p:plain

これにSmooth Stepを掛けます。

黒い部分は更に黒く、白い部分は更に白くなります。ただし非常に滑らかに変化もします。

f:id:kazuhironagai77:20211114215016p:plain

こんな結果になりました。

f:id:kazuhironagai77:20211114215030p:plain

黒い部分は更に黒く、白い部分は更に白くなっていますが全体の滑らかさは保ったままです。

これがSmooth Stepです。

Tutorialでは更にMinとMaxの機能について解説していました。

同様のテストを行います。

f:id:kazuhironagai77:20211114215043p:plain

<<Max = 0.5 の場合>>

f:id:kazuhironagai77:20211114215101p:plain

こんな結果です。

f:id:kazuhironagai77:20211114215114p:plain

Fresnel ノードで0.5以上の値だったところが全部1になっているはずです。

<<Max = 0.5 、Min=0.4の場合>>

今度は、Minも0.4にします。

f:id:kazuhironagai77:20211114215133p:plain

Fresnel ノードで0.4以下の値を示した箇所は全部黒くなっているはずです。

f:id:kazuhironagai77:20211114215246p:plain

こうなるとSmooth Stepの特徴である滑らかな変化がはっきりしませんね。

<<Max = 0.8 、Min=0.3の場合>>

f:id:kazuhironagai77:20211114215305p:plain

こんな感じです。

f:id:kazuhironagai77:20211114215317p:plain

これなら黒から白に変わる時に少しだけ滑らかな変化がみられます。

<応用編1:消えるStatic Mesh

これは見た目が非常に映えるので結果から先に記録しておきます。

f:id:kazuhironagai77:20211114215400g:plain

球が消えたり出現したりしています。

実装方法です。

f:id:kazuhironagai77:20211114215436p:plain

MinとMaxの値をSineで時間によって変化させているのと、ValueにGradientのあるTextureを使用して作成しています。

更に以下の様に改良する事で、境界線のみを表示する事も可能です。

f:id:kazuhironagai77:20211114215455p:plain

結果です。

f:id:kazuhironagai77:20211114215519g:plain

実際に使用するにはもう少し工夫が必要かもしれませんね。

色々微調整してみました。

f:id:kazuhironagai77:20211114215558g:plain

うーん。

光らせるのは嫌いと言いながら思いっきり光らせています。

やっぱり光らせて印象を強くさせるのは手っ取り早いです。

<応用編2:地面からの距離でMaterialが変化する>

何を言っているのか良く分からないので先に実装から説明します。

f:id:kazuhironagai77:20211114215638p:plain

結果です。

f:id:kazuhironagai77:20211114215657p:plain

Absolute World PositionにMaskしてBの値だけ渡しているので地面から高さに応じて黒の部分と白の部分が生じます。

こんな感じです。

f:id:kazuhironagai77:20211114215723g:plain

これだとただの影じゃん。という感想になってしまいますね。

色付けて見ました。

f:id:kazuhironagai77:20211114215752g:plain

この技術を使用してLandscapeでCameraから遠い所にあるMaterialは別なものを表示出来る訳です。

<おまけ>

f:id:kazuhironagai77:20211114215828p:plain

この技術を使用してセルルック調のMaterialを作製してみました。

うーん。

Smoothに変化しない方がセルルック調になりそうですね。

試しに同じやつをStepノードで作成してみました。

f:id:kazuhironagai77:20211114215844p:plain

これだけ見ると結構よさげですが、Cubeなんか滅茶苦茶です。

f:id:kazuhironagai77:20211114215903g:plain

Stepで輪郭線は出さない方が良いみたいです。

輪郭線の部分を濃い肌色で置き換えてみました。

f:id:kazuhironagai77:20211114215957g:plain

うーん。

今回はこんなもんですか。

3.2 Length & Distance - Shader Graph Basics - Episode 16 [4] を勉強する

後、何をするか考えていなかったので、もう一個、Ben Cloward氏のTutorialをやる事にします。

どれでも良かったんですがたまたまこれが目に入ったんでこれをやる事にします。

まずぱっと全部を見ました。

基礎ではLengthノードとDistanceノードの違いについて解説しています。応用ではこのノードを使用した3つの例が実装されているんですがどれも面白いです。

早速やってみます。

<基礎編>

DistanceノードとLengthノードの違いについてです。

UE5では以下の二つのノードになります。

f:id:kazuhironagai77:20211114220045p:plain

Lengthノードですが名前がVector Lengthとなっていました。しかもVector 3とVector 2の両方に対応しています。

それよりもDistanceノードです。

Distanceで探しても出て来ません。

f:id:kazuhironagai77:20211114220131p:plain

ずっと下にスクロールしたら出て来ました。

f:id:kazuhironagai77:20211114220145p:plain

このTutorialが今年の9月に作られたんじゃなかったら諦めていたところです。

LengthはVectorもしくは線分をパスします。そしてパスされたVectorもしくは線分の長さを返します。それに対してDistanceは2つの位置をパスします。そしてパスされた2つの位置の距離を返します。

Tutorialはこれで分かったでしょう。と応用編へ行ってしまうのですが、ちょっとこの説明では分かりにくい部分もあるので以下の実装を作製してテストします。

f:id:kazuhironagai77:20211114220201p:plain

ここではObjectの位置とCameraの位置をDistanceノードにパスしてDistanceノードの計算結果をDebug Scalar Valuesを使用して表示しています。

f:id:kazuhironagai77:20211114220225p:plain

これと同じ事をLengthでやるには以下に示したように差分のVectorを計算する必要があります。

f:id:kazuhironagai77:20211114220241p:plain

結果は同じです。

f:id:kazuhironagai77:20211114220254p:plain

<応用編1:カメラからの距離で明るくなるMaterialの作成>

実装です。

f:id:kazuhironagai77:20211114220314p:plain

まあ。これは当たり前と言えば当たり前ですね。

敢えて述べるとすればAbsolute World Positionノードを使用しているので距離が近いときはPixel毎に色の違いが表示されるはずと言う事とUE5の単位、Unreal Unitは基本的には1㎝なので10000で割る必要があると言う2つです。

結果です。

近い時です。

f:id:kazuhironagai77:20211114220331p:plain

Pixel毎のGradientが見えるかと言えば少しだけ見えますという感じです。

遠い時です。

f:id:kazuhironagai77:20211114220348p:plain

完全に白くなっています。

<応用編2:ゆらゆら揺れるStatic Meshをつくる>

これと最後の奴が面白いです。

最初に結果から表示します。

f:id:kazuhironagai77:20211114220441g:plain

まるで風に揺られている木のような動きです。

実装方法を以下に示します。

f:id:kazuhironagai77:20211114220516p:plain

ここで凄いのは上に行く程揺れ幅は大きく一番下では揺れていない事です。

Local Position ノードは何を返しているんでしょうか?

f:id:kazuhironagai77:20211114220531p:plain

Material関数に対する一般的な解説しかしてませんね。

World PositionのLocal 板でしょう。それだとPixel毎に色が違って見えているのも納得ですし。

このGradientをSinと掛けてY軸のOffsetに追加しています。これで上に行く程揺れ幅は大きく一番下では揺れていない不思議なMaterialを作製しています。

自分で別な方法でこのY軸のゆらゆらを再現して見ようとしたんですが、出来なかったです。World Offsetにパスする値には何か条件があるんでしょうか?

まだ良く分からない事が多いですね。

と言うかちょっと頭が働かなくなって来ました。

Materialの勉強はここまでにします。続きは来週やります。

ちょっと休憩してから考え直したら出来ました。

f:id:kazuhironagai77:20211114220546p:plain

こんな感じです。

f:id:kazuhironagai77:20211114220606g:plain

Distanceノードは使用していませんがゆらゆら木の様に揺れるところは再現出来ました。

<応用編3:ライトに照らされている様に見えるMaterialをつくる>

これは先に作成して後から何をやっているのかを検証する事にします。

以下に実装部を示します。

f:id:kazuhironagai77:20211114220636p:plain

こんな結果です。

f:id:kazuhironagai77:20211114220722g:plain

どうしてこんな結果になるのかを検証します。

この部分は一つ前の応用編と同じですね。これでLightを左右に動かしているんですね。

f:id:kazuhironagai77:20211114220804p:plain

試しにY軸に変更してみます。

f:id:kazuhironagai77:20211114220816p:plain

こんな結果になりました。

f:id:kazuhironagai77:20211114220834g:plain

Distanceノードの時です。

f:id:kazuhironagai77:20211114220900p:plain

こんな結果です。

f:id:kazuhironagai77:20211114220915p:plain

うーん。これを調節するために残りの計算がある訳ですね。

f:id:kazuhironagai77:20211114220930p:plain

光の強さを弱くしています。

f:id:kazuhironagai77:20211114220948g:plain

これだと黒い部分が移動しているんですね。

当然1-xノードを使用して反転していますね。正確に反転させるためにSaturateをその前に掛けています。

f:id:kazuhironagai77:20211114221016p:plain

ただこの結果だとほぼほぼ白くなっていますね。

f:id:kazuhironagai77:20211114221029p:plain

最後に32乗しています。

f:id:kazuhironagai77:20211114221042p:plain

Y=x^32の式をDesmosでGraph化しました。

f:id:kazuhironagai77:20211114221056p:plain

兎に角、暗くしたみたいですね。

実装の意味は理解出来ましたね。自分でこれを一から思いつけるかと言えば出来ないですが。

4.NPCAIを作成するためのAIの復習の続き(Perceptionの勉強)

4.1 AI Perception [6] を勉強する

やっとAI Perceptionまで来ました。ここまで来るのに思っていたのより10倍位かかりました。

一番最初にUE4のAIの勉強として使用したRyan Laley氏のTutorial [7]もAI Perceptionから始まっています。

f:id:kazuhironagai77:20211114221122p:plain

公式のOnline LearningであるIntroduction to AI with Blueprintsでも

f:id:kazuhironagai77:20211114221136p:plain

AIはNav Meshの次に教えられています。

f:id:kazuhironagai77:20211114221151p:plain

ただ何をここで勉強したのかまではもう覚えていません。

まず公式のDocumentのAI Perception [6]を勉強してこれらのTutorialの内容と比較して何が大切かなどをまとめる事にします。

AI Perception [6]を開いてびっくりしたんですが、Nav MeshのDocumentみたくNav Meshを開くとその中に沢山のTutorialがあるんじゃなくてこれしかないです。

f:id:kazuhironagai77:20211114221208p:plain

まあやる側としては楽で良いです。

さらっと読んだらTutorialと言うよりAI Perceptionで使用するための機能などの紹介が主でした。これだけ読んでもAI Perceptionを追加する事は出来ないですね。どこか別のTutorialでUE4_AIのPerceptionの作成方法を勉強した人がそこで使用した機能の意味をしっかり理解するために利用するのには便利そうです。

以下にそれぞれの項目で何が語られているのかを簡単にまとめておきます。

<前文>

AI Perception SystemとAI Perception Component、On Perception Updatedについて簡単な解説がされています。

Nav MeshではAIにControlされるキャラをAgencyと呼んでいますが、ここでは単にPawnと呼んでいます。勉強する側からの要望としてはこの辺の名称は統一してほしいです。PawnはともかくAgencyは何を指しているのか一瞬分からなくなります。ここではAIが操作するNPCと呼ぶ事にします。

<AI Perception Component

これをNPCにComponentとして追加する事で色々な環境の変化を知覚する事が出来るようになります。

ただこれNPCのAI ControllerのBP内にComponentとして追加します。と書かれていました。

あれ?

そうでしたっけ。

確認します。

Ch4_3を開いてMonsterに使用しているMy AI Controller BPを開きました。

f:id:kazuhironagai77:20211114221235p:plain

確かにAI Perceptionがここで使用されていました。

<<AI Perception Properties>>

AI Perception クラスにあるProperty、AI Perceptionについての解説です。

前にこの辺を勉強した時に作成したProjectを見つけたのですが以下に示したように、それにはAI Sight Config、AI Hearing Config、AI Damage Sense Configの3つがセットされDominant Senseには何もセットされていませんでした。

f:id:kazuhironagai77:20211114221257p:plain

<<<AI Damageについて>>>

このDocumentの解説によるとAI DamageはEvent Any Damage、 Event Point Damage、or Event Radial DamageなどのEventに対して反応するそうです。

AI DamageのSenseを開くと以下の様な項目が表示されます。

f:id:kazuhironagai77:20211114221317p:plain

それぞれの項目が何を管理しているか解説されていました。必要になったら読む事にします。

残りの項目のAI Damageと同じ構成なのでその機能を使用する時に読む事にします。

<<Perception Events>>

この部分に関してですが全く覚えていません。

前にAIの勉強した時に作成したProjectのAI Controller BPを見直すと以下のようなOn Perception Updated (AI Perception) を使用した実装が見つかりました。

f:id:kazuhironagai77:20211114221337p:plain

Documentを読むとPerception Eventがある事でNPCが環境の変化を受け取れると説明されていました。

環境が変化した事で発生するEventなんでしょうが、いつ、どこで、どのように使用するのか全然分からないです。これは他のTutorialを復習する時にもう一回勉強する事にします。

<Stimuli Source

これは覚えています。Player が操作するキャラにつけるComponentです。

何で敵があえてこっちが知りたい情報を教えてくれるんだ。と怒った記憶があります。

このProjectのThird Person Character BPを開いたらAI Perception Stimuli Sourceが追加されていました。

f:id:kazuhironagai77:20211114221356p:plain

ただ使い方までは覚えていません。これも別なTutorialで復習します。

<<Stimuli Properties>>

さっきのAI ControllerのAI PerceptionにはAI Sight Config、AI Hearing Config、AI Damage Sense Configの3つが指定されていましたが、こっちはAISense_Sightしかセットされていませんでした。

f:id:kazuhironagai77:20211114221415p:plain

<<Stimuli Function Calls>>

これは何を指しているのか不明ですね。他のTutorialをやってみて必要だった復習します。

<AI Perception Debugging

これはDebugの時に一緒に復習します。

4.2 2021-02-01のブログを復習する

2021-02-01のブログにOnline LearningのIntroduction to AI with Blueprintの勉強内容が簡潔にまとめられています。

f:id:kazuhironagai77:20211114221450p:plain

この中でPerceptionに関係している箇所を読み直します。

<AI Perception Theory

f:id:kazuhironagai77:20211114221539p:plain

結構書き込んでいて、全く内容を忘れてしまっている今では結構重要な情報です。

やっぱり書いている時はこんな事わざわざ書く必要あるんだろうか?と自問自答しながら書いていましたが、今こうやって見直すととても役に立っています。

Blogを始めていろんな事を新しく学びましたが、その中でも最も重要でかつ不変の真理と思うのが「書いておけば必ず後で役に立つ。」と言う事です。

「AI Perception Component と AI Perception Stimuli Sourceについての解説、そしてTarget Perception Updated eventについての説明がちょっとだけあります。」と書かれています。今の私はまさしくこれらの使用方法について知りたいんです。復習する時はこの講義から見直します。

<Setting up AI Perception

f:id:kazuhironagai77:20211114221559p:plain

この講義は実際にどうやってAI Perceptionを実装するのかの実演がされているみたいですね。Sight以外の知覚の設定方法についても解説しているのでしょうか?

<AI Perception and the Gameplay Debugger

ここはDebugについてですね。

f:id:kazuhironagai77:20211114221618p:plain

Debugについての復習はDebugでまとめてしようと思っていたんですが、AI Perception専用のDebugがある訳ですね。

うーん。やっぱりそれでも後でやる事にします。

f:id:kazuhironagai77:20211114221633p:plain

後はこれのやり方です。

これのやり方、確か後で発見したはずです。どうやったのかは覚えていませんが。

<Using the AI Perception Events

f:id:kazuhironagai77:20211114221651p:plain

Eventの使用方法についての実演のようです。カメラの位置を上手く移動出来ないと確認が出来ないと言っていますね。復習する前にカメラの位置の変え方を調べる必要がありますね。

<Introduction to AI with Blueprint Quiz 3

f:id:kazuhironagai77:20211114221710p:plain

何を言っているのかすら分かりません。

4.3 Ryan Laley氏のUnreal Engine 4 Tutorial - AI - Part 2 AI Perception [8] を勉強する

更とみて大体理解しました。

実際、AI Perception自体はこのTutorialでも後半半分だけで作成しています。

その部分だけ以下にまとめておきます。

<AI PerceptionをAI Controllerに追加する>

f:id:kazuhironagai77:20211114221735p:plain

これは先程の復習でも出て来ました。

<AI PerceptionのSense ConfigにAI Sight Configをセットする>

f:id:kazuhironagai77:20211114221753p:plain

この例では視覚で敵を認識するのでSightをセットします。

<AI Perception Stimuli SourceをThird Person Characterに追加する

f:id:kazuhironagai77:20211114221812p:plain

これも先程勉強した通りです。

<AI Perception Stimuli Source のAI PerceptionにAI Sens e_ Sightを追加する

f:id:kazuhironagai77:20211114221839p:plain

これも先程の勉強したやり方と同じですね。Auto Register as Sourceにチェックを入れていますが、これについては意味がわかりません。

公式のDocumentのAI Perception [6]にAuto Register as Sourceの解説がありました。

f:id:kazuhironagai77:20211114221853p:plain

これにチェックしないとNPCのAIがどの知覚で認識するか自動で決まらないと言う事でしょうか?

読んでも今一理解出来ないですね。

<AI Controller BP内でPlayer の操作するキャラをNPCが知覚出来るようにコードを組む>

先程はここの作成方法が分からなかったです。

早速、AI Controller BP内にOn Target Perception Updated(AI Perception)を追加しました。

f:id:kazuhironagai77:20211114221912p:plain

このノードの機能が分からない。時にOn Perception Updatedとの違いが分からりません。と思っていたら公式のDocumentのAI Perception [6]にしっかり解説されていました。

まずOn Target Perception Updatedですが、

f:id:kazuhironagai77:20211114221928p:plain

と書かれています。On Perception Updatedに関しては

f:id:kazuhironagai77:20211114221945p:plain

と書かれています。

Stimulus Structを返してほしい時はOn Target Perception Updateノードを選択する必要があると言う事のようです。

次にStimulus StructをBreakしてます。

f:id:kazuhironagai77:20211114222015p:plain

次に対象のActorがPlayer が操作するキャラである事を確認するためにCast to Third Person Characterノードを繋げています。

f:id:kazuhironagai77:20211114222029p:plain

これはAI Perceptionとは関係ないのでコメントはなしで先に進みます。

Blackboardクラスの変数の値を以下の方法で変更します。

f:id:kazuhironagai77:20211114222044p:plain

Make Literal NameにはBlackboardクラスに作成した変数の名前が入ります。

NPCのAI Controller内でPlayer の操作するキャラを知覚するだけでなく、知覚した後にBlackboardクラスの変数の値を変更する事でBehavior Treeの行動を変化させる機能もここで作成しています。

納得しました。

5.World CompositionによるMap1の作成(Bugの修正)

一週間、考えましたがMap1は一端消して作り直す事にします。

その際に、World Compositionは止めてLoad Stream Levelノードを使用する事にします。

World Compositionの使用を中止する理由は2つです。

Landscape自体が消えると以下に示した様な変な背景が制作されてしまう事が一つ

f:id:kazuhironagai77:20211114222106p:plain

遠くの山が見えなくなるのはオカシイのがもう一つの理由です。

反対に町の人なんかは町から離れたら全く見えなくてもオカシクないです。

のでWorld Compositionを使用するよりもLoad Stream LevelノードでLandscape以外のActorのLoad /Unloadの管理をした方が自然に近くなるとの結論が出ました。

5.1 Map1のActor全部をPersistent Levelに戻す

最初1個ずつ戻していたんですが、らちが明かない。

何か良い方法はないかなと探していたらありました。

World Outlinerの表示をTypeからLevelに変更します。

f:id:kazuhironagai77:20211114222126p:plain

これでどのActorがどのSub Levelに属しているのかが丸分かりになります。

ここでMap1に属していないやつは全部Map1に移せばいいんです。

f:id:kazuhironagai77:20211114222141p:plain

全部のActorをPersistent Levelに移しました。

とはいかなかったです。幾つかのActorが問題ありそうなので移す前に対応を考える必要があります。

f:id:kazuhironagai77:20211114222159p:plain

これって前に作成したLandscapeが残っているんでしょうか?

調べたらSub Level 1-1のLandscape Streaming Proxyが無いんです。色々弄ってみるとどうもSub Level 1-1のLandscape Streaming ProxyがLandscape5と言う名前に変更されているみたいです。なんでこうなったんでしょう?

当然ですがLandscape Streaming Proxyはそのままで残しています。これらのSub Levelは後で全部消してしまいます。

f:id:kazuhironagai77:20211114222214p:plain

Level Boundもです。

f:id:kazuhironagai77:20211114222227p:plain

良く考えなくてもこれらのActorの機能が分かっていません。

勝手に消して後で問題が発生したらどうしましょう?

後、先週作成した2つのTrigger Boxです。

f:id:kazuhironagai77:20211114222243p:plain

これらは消してしまいます。新しいTrigger Boxをまた作成する事にします。

ここまでやって気が付いたんですが、Level2_5がSave出来るようになってます。

f:id:kazuhironagai77:20211114222311p:plain

あれ。

どうしよう。

一寸考えます。

考えました。もう一回ActorをそれぞれのSub Levelに移します。これをする事でどこでSub Level2_5がSave出来なくなるバグが発生したのかを特定出来るからです。

5.2 Map1のActorをそれぞれが属するSub Levelに戻す

一応、今の時点でPlayが出来る事を確認しておきます。

f:id:kazuhironagai77:20211114222332p:plain

Monster発生用のTrigger boxを消したのにMonsterが発生していますが、それは以下に示した実装部からMonsterを生成したからです。

f:id:kazuhironagai77:20211114222347p:plain

当然ですがSub Level、Level2_5からやります。

Level2_5に配置されているActorは全部Persistent LevelからLevel2_5に移しました。

以下にLevel2_5 を見えない状態にした図を示します。

f:id:kazuhironagai77:20211114222411p:plain

ここでLevel2_5を消しても表示されているActorつまりLevel2_5の上に配置されているのにPersistent Levelに配置されてるActorはGood Sky、Post Process Volume、Atmospheric Fog、Sky Light、Sphere Reflection Capture、そしてNav Mesh Bounds Volumeです。どれもLevel2_5とは直接関係ないActor達です。

残りのActorは全てLevel2_5に移しました。

f:id:kazuhironagai77:20211114222433p:plain

しかしLevel2_5は普通にSave出来ます。

テストします。

普通に表示されています。

f:id:kazuhironagai77:20211114222448p:plain

遠くに行くとUnloadもされます。

f:id:kazuhironagai77:20211114222501p:plain

今度はTrigger Boxを追加します。

f:id:kazuhironagai77:20211114222514p:plain

先週作成した実装も追加します。

f:id:kazuhironagai77:20211114222527p:plain

普通にSave出来ますね。

f:id:kazuhironagai77:20211114222548p:plain

Playしてみます。

Monsterを倒して戻って来ました。

f:id:kazuhironagai77:20211114222608p:plain

倒したMonsterは消滅しています。

全て上手くいっています。

それでは他のSub Levelもやっていきます。

Level3_6も直しました。Trigger boxも新しく追加しました。

f:id:kazuhironagai77:20211114222622p:plain

それ以外のSub Levelも全部やりました。

テストします。

f:id:kazuhironagai77:20211114222637p:plain

Monsterが追いかけて来ませんね。

原因が不明なのでもう一回テストしたら今度は普通に歩いていました。

f:id:kazuhironagai77:20211114222652p:plain

他の箇所をチェックします。

村の中で石で舗装された地面に草が生えている箇所があります。

f:id:kazuhironagai77:20211114222705p:plain

村人との会話は面白いです。

f:id:kazuhironagai77:20211114222720p:plain

PCからファンの音が大きくなる時があるんですが、その理由が分かりました。夕方から夜になる時と夜から朝になる時になっています。

今はテストを兼ねて一日を5分で設定しているので仕方ない部分もあるのかもしれません。一日を30分とかにしたらPCの負担も減ると思われます。

特にSave出来ないSub Levelも発生していないので先に進みます。

5.3 先週中止したMonsterの追加をやる

Sub Level 2_5にMonsterをもう一体発生させる。

Monster Spawn Data 2_5 に新しいMonsterのDataを追加します。

f:id:kazuhironagai77:20211114222741p:plain

テストします。

f:id:kazuhironagai77:20211114222754p:plain

出来ています。

出来ていますが、突然止まるときがあります。

MonsterのAIももっと自然にPlayerの操作するキャラを追いかけるように改良する必要がありそうです。

5.4 Level 2_4にMonsterを追加する

先週のバグの発生が結構精神的なショックだったみたいで、どうやって動的なMonsterを生成していたのかとか、どうやって倒したMonsterを消したのかとかを忘れてしまいました。

思い出しながら作成してみます。

取りあえずMonster BPを静的に配置してみました。

f:id:kazuhironagai77:20211114222822p:plain

動きません。

これはNav Meshが働いていないみたいです。

新しいNav Meshに交換しました。

ここで隣のNav MeshをDuplicateして配置しようとしたらLevel 2_4がsave出来なくなりました。

どうやらSub Level間を跨いでDuplicateしたNav Meshを配置しようとすると新しいNav Meshが配置されたSub LevelはそのNav MeshがSave出来なくなるみたいです。

これが先週のバグの原因だったみたいです。

新しいNav MeshをNav Mesh Bounds Volumeから作成してしかもそのNav MeshはPersistent Levelに配置しました。

そしたらLevel 2_4は普通にSave出来るようになりました。

f:id:kazuhironagai77:20211114222843p:plain

テストします。

今度はMonsterは普通に徘徊しています。

f:id:kazuhironagai77:20211114222856p:plain

これを動的に生成するようにします。

まずMonster Spawn Data 2_4をGame Instance BP内に作成して

f:id:kazuhironagai77:20211114222910p:plain

先程、静的に配置したMonsterのdataを追加します。

f:id:kazuhironagai77:20211114222922p:plain

Level 2_4のBPにLevel2_5で実装したMonsterの生成方法を実装します。

先週、Level2_5で実装したやり方と全く同じです。

f:id:kazuhironagai77:20211114222936p:plain

これでテストします。

f:id:kazuhironagai77:20211114222951p:plain

普通に徘徊しています。

今度はMonsterの数を増やしてみます。

3体追加しました。

f:id:kazuhironagai77:20211114223008p:plain

特に問題なく動いています。

Level 2_5のMonsterも生成するようにするとかなり壮観な眺めになります。

f:id:kazuhironagai77:20211114223021p:plain

今度は倒したMonsterが消滅するための実装を作製します。

Game Mode BP内のRemove Defeated Monster from Map 1関数にLevel 2_4の場合を追加します。

f:id:kazuhironagai77:20211114223037p:plain

Level 2_4のためのTrigger Boxを追加して

f:id:kazuhironagai77:20211114223052p:plain

Trigger Box用の実装もLevel 2_4のBP内に追加します。

f:id:kazuhironagai77:20211114223106p:plain

これで倒したMonsterは消滅するはずです。

テストします。

Monsterを2体倒しました。

戦闘から戻ったら2体だけ生成されています。

f:id:kazuhironagai77:20211114223131p:plain

Level 2_4のMonsterは全体で4体なので出来ています。

5.5 Blueprint Function Libraryを使用して重複箇所を簡単にする

後二つ、作成すれば終りなので力技でコードを書いても良いですが、折角全く同じ実装を幾つかのSub Levelで行うのだからBlueprint Function Libraryを使用して重複箇所を簡単にして見ようと思います。

f:id:kazuhironagai77:20211114223153p:plain

何と、Blueprint Function LibraryクラスからはSpawn Actor From Class ノードが使用出来ません。

f:id:kazuhironagai77:20211114223207p:plain

はい。力技で全部のSub LevelにSpawn Monsterの実装を作成していきます。

5.6 Level 2_3にMonsterを配置する

f:id:kazuhironagai77:20211114223225p:plain

f:id:kazuhironagai77:20211114223231p:plain

f:id:kazuhironagai77:20211114223237p:plain

f:id:kazuhironagai77:20211114223243p:plain

結果です。

f:id:kazuhironagai77:20211114223257p:plain

普通に戦闘したら消滅しました。

5.7 残りのSub LevelにMonsterを配置する

f:id:kazuhironagai77:20211114223317p:plain

Monster Trapも追加しました。

f:id:kazuhironagai77:20211114223353p:plain

取りあえずこれでMap1は完成とします。

来週、World Compositionに対しての総括を行います。

6.UE5におけるWorld Partitionの勉強の続き

先週の勉強で、

f:id:kazuhironagai77:20211114223418p:plain

と書いています。ので今週はData Layerについて勉強します。

6.1 World Partition - Data Layers [9] を勉強する

公式のDocumentには以下の解説がされています。

f:id:kazuhironagai77:20211114223438p:plain

要するにUE4のWorld CompositionやLoad Stream Levelで手動でActorをそれぞれのSub Levelに分配していた事をUE5のWorld Partitionは自動でやってくれます。Data Layerはその時に分けたActorのグループ(これをLayerと呼ぶらしい。)を整理するのに使用されていると。

これだとそれぞれのLayerはwp.Runtime.ToggleDrawRuntimeHash2Dで今まで見てた図とそんなに変わらないと思いますが、どうなんでしょう。

<Data Layer Outliner

Tutorialでは以下のようにそれぞれのLayerが表示されていますが

f:id:kazuhironagai77:20211114223506p:plain

私のData Layerには何も表示されていません。

f:id:kazuhironagai77:20211114223520p:plain

ひょっとしてActorを配置していないからなのかと思い、Cubeを適当に配置しましたが何の変化もありませんでした。

色々試しましたが、それぞれのLayerが表示される事はありませんでした。

これは分からん。とあきらめ、取りあえず先を読んたら以下の説明がありました。

f:id:kazuhironagai77:20211114223534p:plain

うん。Layerって自分で作成するの?

試しにCreate Empty Data Layerを選択したら

f:id:kazuhironagai77:20211114223550p:plain

出来ました。

うーん。Layerは自動で作成されると思っていたんですが、違うんでしょうか?

取りあえずCubeを配置してAdd Selected Actors to New Data Layerを選択してそのCubeをData Layer1に追加しました。

f:id:kazuhironagai77:20211114223605p:plain

f:id:kazuhironagai77:20211114223611p:plain

Data Layer1のIs Initially Visibleのチェックを外して

f:id:kazuhironagai77:20211114223624p:plain

Playを押すとCubeが消えました。

f:id:kazuhironagai77:20211114223643p:plain

今度はIs Initially VisibleにチェックしてPlayを押すと

f:id:kazuhironagai77:20211114223657p:plain

今度もCubeは消えてしまいました。

あれっと思ったらData Layer – RuntimeのInitial StateがUnloadになっていました。

f:id:kazuhironagai77:20211114223711p:plain

ここをLoadedに変更してもう一度Playを押すと

f:id:kazuhironagai77:20211114223726p:plain

それでもCubeは表示されません。

あれ。

これだったらLoadされているはずだから表示されてもいいはずですが。

今度はIs Dynamically Loadedのチェックを外します。

f:id:kazuhironagai77:20211114223747p:plain

流石に今度はCubeが表示されるでしょう。

Playを押します。

f:id:kazuhironagai77:20211114223802p:plain

今度は表示されました。

うーん。

良く分からない。

良く分からないと言えばWorld OutlinerでCubeのLayerを表示させようとしましたが、何も表示されません。これもよく分からないです。

f:id:kazuhironagai77:20211114223818p:plain

まあいいです。先を読んでみます。

<Actor Details Panel

UE5のActorを選択すると以下の項目がDetail内に表示されます。

f:id:kazuhironagai77:20211114223837p:plain

多分ですがこれについての説明でしょう。

f:id:kazuhironagai77:20211114223850p:plain

Data Layer内にもう一個Data Layerを作製する事が出来るとあります。

それを先程のActorを選択した時にDetail内に表示されるData Layerで作成するのでしょうか?

新しいData Layerを作製してそれを追加してみます。

f:id:kazuhironagai77:20211114223904p:plain

追加するも何も作成した瞬間に自動で追加されていました。

f:id:kazuhironagai77:20211114223917p:plain

うーん。これもどんな機能なのか具体的な事は全く分からないですね。

<Showing Data Layers in the Viewport

Viewport 1のShowをクリックすると

f:id:kazuhironagai77:20211114223941p:plain

Data Layerがあるそこに作成したData Layerが表示されます。

f:id:kazuhironagai77:20211114223954p:plain

これを選択する事でそれぞれのData Layerに属するActorを表示出来ます。

<Managing Files

公式のDocumentには以下の解説が最初にされています。

f:id:kazuhironagai77:20211114224012p:plain

これ読むとMMOのような大量のUserが同じMap内でゲームをするのが前提条件になっています。MMO自体の仕組みをよく知らない私にはどうやって個々のUserのDataをSaveすべきか自体が良く分かっていませんので、こうするとOverlapしているDataを減らせます。と言われても今一ピンと来ません。

そしてこのDocumentの最初の疑問に戻ります。OverlapしたDataを減らすためにLayerを作っているなら最初からLayerってあるべきなのに

f:id:kazuhironagai77:20211114224029p:plain

自分でLayerを作成するまでData Layerには何も表示されません。

しかも作成したLayerは

f:id:kazuhironagai77:20211114224043p:plain

自動では表示されないというおまけ付きです。

今まで、

f:id:kazuhironagai77:20211114224056p:plain

で設定してLoadしたりUnloadしてたActor達はLayerに自動的に割り振られていたからそう言う事が出来たんじゃないのかと言う疑問が生じます。

この辺の謎が解明しないとこのDocumentを読んでも、よく意味が分からないです。

その辺の謎はこのままData Layerの勉強を続けて行けば、ジグソーパズルの作成のように全体像が見えてきたら一気に理解が進むはずなので今は気にしないで進みます。

次の文章では、それぞれのLayerはDisplay LabelとID番号を持っていて、そうする事のメリットを語っています。

この辺はData Layerの使い方を理解した後にもう一回読みます。

<Using Data Layers with Blueprints

BPからData Layerの設定が変更出来る事とその例を解説しています。

<Converting from Previous Layer System

ここは注意書きのようなもので、World Partitionに変更したら前に作成していたData LayerのDynamically Loaded は自動的にDisabledにセットされます。説明されていました。

6.2 World PartitionのData Layerの疑問点のまとめ

World PartitionのData Layerについて公式のDocumentで勉強したんですが、逆に訳わからなくなってしまいました。勿論、全部が分からないと言う訳ではなく理解した部分は沢山あります。のでその辺を整理します。

まずData Layerの理論的な理解と操作の方法に分かれて説明します。

Data Layerの操作方法については大体は理解しました。Data LayersはWidowから表示出来るData LayersとActorのDetailに表示されているData Layersによって操作されますがその操作方法は大体覚えました。

Viewport1のShowからLayerを表示する方法も覚えました。

BPからData Layersの設定を変える方法は読んだだけで実際に試す所までは出来なかったです。

Data Layerの理論についてですが、こっちが良く分かっていません。

World Partitionで以下の様に設定すると

f:id:kazuhironagai77:20211114224145p:plain

Loading Rangeより外側に位置するActorは自動的にUnloadされます。

これを管理しているのがData Layersだとずっと思っていたのですが、どうやらこれが勘違いだったみたいです。

またこれは操作に関する内容になるかもしれませんが、Data Layerは自分でData Layers内に作成する必要があり、

f:id:kazuhironagai77:20211114224202p:plain

それぞれのLayerに属するActorも自分で指定する必要があるみたいです。

指定する方法についてですが、それぞれのActorのDetailのData Layersに属するLayerを選択した場合と

f:id:kazuhironagai77:20211114224216p:plain

単にActorを選択して更にWorld LayersからLayerを選択してAdd Selected Actors to Selected Data Layerを選択した場合の違いも分かりません。

f:id:kazuhironagai77:20211114224236p:plain

最初、一つのActorを二つ以上のLayerに同時にセット出来るのかと思いましたが、これは不明です。

更に、Data Layerの設定で

f:id:kazuhironagai77:20211114224249p:plain

Initially VisibleかつInitial StateをLoadedにしてもPlay中に自動的にLoadされないです。Initial StateがLoadedなのに表示されない理由が分かりません。

これらの疑問はData LayersのTutorialで実際の作成手順を見れば解決するはずです。

Data LayersのTutorialを探してみます。

6.3 Data Layersに関係したTutorialを探す

Open Worlds with World Partition | Exploring Unreal Engine 5 [10]

先週、見たTutorialで詳しい解説がしてたと思ったんですが、

詳しい解説をしていたのはWorld Partition [11] のOne File Per Actorについてでした。

f:id:kazuhironagai77:20211114224311p:plain

How to Use Data Layers in Unreal Engine 5 (Dark Realm Access) [12]

これはTutorialと言うよりUE5のDemoでDark Worldの表示方法についての解説でした。

しかしData Layerについて幾つかの新しい情報がありました。

まずDemoでData Layersが実際に使用されている事です。

これはDemoを見ればData Layersに関するある程度の情報が得られると言う事です。今の私のPCではDemoを動かす事は出来ませんので、実際に試すにはかなり後になりそうですが。

もう一つ分かった事が、このDemoでは同じLandscapeに二つの世界Dark WorldとDesertを作成しています。Data Layersは距離に応じてActorをLoadしたりUnloadしたりする機能の事ではなく全く別な機能のようです。

ここからはそのDemoとこのVideoからの推測です。

Gameで同じ地形上に、今の世界と1000年後の世界を作成したいとします。そんな時にData Layerを使用すると同じLevel上に同時に作成出来るんじゃないでしょうか?

それがData Layerの機能のように感じました。

となるとどうやってData Layerを切り替えるのかを知りたいですね。

単に

f:id:kazuhironagai77:20211114224331p:plain

としただけではこのData Layerに属しているActorは表示されませんから。

おそらくTrigger Boxか何かを使用してBP内で指定するのでしょうが、その具体的な方法が知りたいです。

Unreal Engine 5 - Data Layers Tutorial [13]

私が見た時点ですが3割の人がBad buttonを押しています。

f:id:kazuhironagai77:20211114224352p:plain

内容を見たら、音が無いのと、4分の動画なのに後半の2分間、関係ない話をしているからで、Data Layerの内容そのものについては十分信頼出来そうです。

ここでは、World PartitionをEnableする方法とその後にData Layerを作成してそのData LayerにActorを移す方法が紹介されていました。

この後で、そのData Layerをどうやって最初から表示するのかが説明されていたら完璧だったんですが、それでもかなりの新しい情報が得られました。

<ここまでのまとめ>

やっぱりData Layerの機能はRangeによってActorをLoadしたりUnloadしたりするためのものではないです。

同じLevel上に、全く別のActorを配置して1000年後の世界なんかを表現したりするための物の様です。

そこが分かると今までモヤモヤしていた部分がはっきりしてきます。

後はどうやってPlay中にloadしたりunloadしたりする事が出来るのかが分かれば大体分かったと言えますね。

この辺りはDemoを見れば分かるはずです。

今週の勉強で分かった事はこんな事ぐらいでしょうか。

7.まとめと感想

今週は、まさかWorld Compositionのバグが直るとは思っていなかったのでそこで予定が結構変わってしまいました。

Nav Meshを別なSub LevelからDuplicateして配置するとその配置されたSub LevelではSave出来なくなる(実際はSaveは出来ますがSaveした後でもSaveが必要な表示になっている。)ようです。

しかしWorld Compositionはそれ以外にも幾つかの問題を抱えており、Landscapeは最初に一括でLoadして個々のActorはLoading Stream Levelノードを使用して一々Loadした方がPCに対する負担が少ない気がしています。

後、LandscapeをLoadするのはPlayer が操作するActorが生成された後なので、Userは地面の無い画面を1秒位眺めている必要があり、見た目が悪いと言う問題もあります。

World Compositionと言う機能を勉強する事は大変重要ですが、その後どこにどうやって使用するかを考えるのも同じ位重要になりそうです。

NiagaraRibbonについての勉強をしました。

Particle Position変数がそれぞれのParticleの発生する位置を指定しているのは間違いないのでWorld Coordinateの値がしっかり入っていれば位置を自由に指定出来ると思ったのですが出来なかったです。これは来週検討します。

MaterialはStep、Smooth Step、LengthそしてDistanceについて勉強しました。やっぱりMaterialの関数は0と1の間の挙動がどうなっているのかを理解するのが大事ですね。

AIはPerceptionについての復習をしました。やっぱり前に勉強していた内容は直ぐに思いだしました。

World PartitionについてはData Layersについて勉強しました。Data Layersは勉強する前に想像していた様なものではなくて、同じLevel上に1000年後の世界なんかを作成するために使用するみたいです。ただ現時点では参考に出来る資料が少ないので何とも言えないです。

今週は以上です。

8.参照(Reference

[1] CGHOW. (2021, October 11). Twisted Ribbon in UE4.27 Niagara Tutorial | Download Files [Video]. YouTube. https://www.youtube.com/watch?v=RvTQup0Jxf4

[2] Epic Games. (n.d.-b). Math Expressions. Unreal Engine Documentation. Retrieved November 14, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Materials/ExpressionReference/Math/

[3] Unity3d.com. (n.d.). Step Node | Shader Graph | 6.9.2. Unity3D. Retrieved November 14, 2021, from https://docs.unity3d.com/Packages/com.unity.shadergraph@6.9/manual/Step-Node.html

[4] Cloward, B. [Ben Cloward]. (2021a, September 16). Smoothstep - Shader Graph Basics - Episode 15 [Video]. YouTube. https://www.youtube.com/watch?v=dn3y5KVxylQ

[5] Cloward, B. [Ben Cloward]. (2021b, September 23). Length & Distance - Shader Graph Basics - Episode 16 [Video]. YouTube. https://www.youtube.com/watch?v=wTHKzjYBH7U&list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl&index=16

[6] Epic Games. (n.d.-a). AI Perception. Unreal Engine Documentation. Retrieved November 14, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/AIPerception/

[7] Laley, R. (n.d.). AI. YouTube. Retrieved November 14, 2021, from https://www.youtube.com/playlist?list=PL4G2bSPE_8ukuajpXPlAE47Yez7EAyKMu

[8] Laley, R. [Ryan Laley]. (2019, January 24). Unreal Engine 4 Tutorial - AI - Part 2 AI Perception [Video]. YouTube. https://www.youtube.com/watch?v=X5l0u7M-ILo&list=PL4G2bSPE_8ukuajpXPlAE47Yez7EAyKMu&index=2

[9] Epic Games. (n.d.-d). World Partition - Data Layers. Unreal Engine Documentation. Retrieved November 14, 2021, from https://docs.unrealengine.com/5.0/en-US/WorldFeatures/WorldPartition/DataLayers/

[10] Polygon Hive. (2021, June 9). Open Worlds with World Partition | Exploring Unreal Engine 5 [Video]. YouTube. https://www.youtube.com/watch?v=4z9Ea7eCxt4

[11] Epic Games. (n.d.-c). World Partition. Unreal Engine Documentation. Retrieved November 14, 2021, from https://docs.unrealengine.com/5.0/en-US/WorldFeatures/WorldPartition/

[12] MR3D-Dev. (2021, May 27). How to Use Data Layers in Unreal Engine 5 (Dark Realm Access) [Video]. YouTube. https://www.youtube.com/watch?v=4O4t0BXcuwE

[13] DonThaMon. (2021, May 28). Unreal Engine 5 - Data Layers Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=QueqScGNDUM