UE4の勉強記録

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

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

f:id:kazuhironagai77:20211024224245p:plain

<前文>

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

アメリカに約10年暮らしていた私からすると、アメリカ人と日本人の常識って表面上は似ているんですが、そこにたどり着くための道程が全く違うんです。今日はそんな話です。

<Dot Product内積なのか?>

Dot Product。最近もMaterialの勉強で新しく勉強し直しました。

2021-10-03のBlogを見ると以下のように書かれています。

f:id:kazuhironagai77:20211024224312p:plain

いやあ、分かり易いですね。

大満足です。

と書いて後で気が付いたんですが、内積って良く以下に示したような図で説明されていますよね。

f:id:kazuhironagai77:20211024232327p:plain

ベクトルAとBがあってAの影をB上に投影した時に出来る線の大きさが内積。みたいな解説です。

先程のBlogを書いたときは、この説明方法がある事をすっかり忘れていました。

それで後から思いだした時、「あれ、この説明でも良くない。というかこっちの方が正確だよね。」とか言われたらどうしようかと、焦ってかなり内積について見直しました。

そしたら、この説明方法かなり無理があると言うか、直観的に理解すると間違って理解してしまう可能性も含んでいて2021-10-03のBlogに紹介した説明と比べるとかなり落ちる事が分かりました。

以下にその理由をまとめておきます。

  • 影に方向がある。つまり内積の最大の特徴である計算結果がScalerになってVectorではない事がこの図だと分からない。
  • 太陽の位置によって影の大きさが変わってしまうが、その辺を無視している。太陽が真上の場合で、と言う条件は図を見ただけでは直観的には理解しづらい。言い換えると地面と言う平面に対するNormal Vector(法線)という概念を隠して説明している。

そう言う訳で、この説明は実際はかなり分かりにくいので、安心しました。

はい。お終いとしようとしたら、ある疑問にぶつかりました。

Dot Productって内積だったっけ?

ここからが本題になります。

何となく、Dot Productの日本語訳は内積と思っていましたが、一応確認したんです。そしたらGoogle Translatorは

f:id:kazuhironagai77:20211024232405p:plain

って。更にWeblioでは点乗積。

f:id:kazuhironagai77:20211024232422p:plain

英辞郎では

f:id:kazuhironagai77:20211024232436p:plain

ドット積、点乗積と出ています。

え、Dot Productって内積じゃないの?

内積、英語で検索すると

まずGoogle Translateでは

f:id:kazuhironagai77:20211024232502p:plain

と出て来ます。

そしてWeblioでも

f:id:kazuhironagai77:20211024232517p:plain

となってDot Productではないです。

えー。ですよ。

ただ私、Dot Productは良く聞きますが、Inner Productって正直、聞いた覚えがないです。本当の英語なんでしょうか?

何か、非常に怪しい。

内積を直訳した造語なんじゃないのって気がします。

それで今度はInner Productを調べました。

f:id:kazuhironagai77:20211024232531p:plain

Inner Productと言う言葉自体はあるんですね。

じゃDot ProductとInner Productはどう違うのか調べて見ました。

色々な人が色々な所で答えていますが、私にはこの解答が一番分かり易かったです。

What's the difference between inner product, dot product and scalar product? [1]より

f:id:kazuhironagai77:20211024232545p:plain

Euclidean Spaceと言うのは実数のみ存在する空間と言う意味でしょう。つまり複素数がない世界です。

その場合はDot Productと言います。答えが実数でなくVector複素数を含んでいる場合はInner Productと言います。

分かりました。

まとめ直します。

まず、Inner ProductとDot Productの計算方法も定義も全く同じです。

違いは扱う数字にあります。

実数のみを扱う場合はDot Productと言い、実数に加えて虚数も扱う場合はInner Productと言うのが正確な定義のようです。

つまり全てのDot ProductはInner Productですが、Inner ProductはDot Productではない場合もあるわけです。

うーん。

理解はしましたが、私Inner Productを実際に大学で習った記憶がないんです。電気とかで複素数をガンガン使う人には当たり前の事なんでしょうか?

あ、量子化学の計算で複素数の計算を沢山してました。これを調べれば実際に複素数のDot Productの時はInner Productと言うのか確認できるはずです。

量子化学の教科書で調べて一番最初に出て来たヤツ[2]を

f:id:kazuhironagai77:20211024232600p:plain

Dot Productで検索しました。14頁に以下の文章がありました。

f:id:kazuhironagai77:20211024232615p:plain

流石に今これを読んですぐに何を言っているのか思い出すのは無理ですが確か

f:id:kazuhironagai77:20211024232629p:plain

この部分の計算は複素数を含んでいたはずです。

でもDot Productって言っています。

うん。

更に検索で調べた限りでは、この教科書にはInner Productと言う言葉は一回も使用されてなかったです。

やっぱり虚数の計算をする時もDot Productって言っています。

つまり英語ではInner Productって言葉、あんまり聞いた事がないという私の感覚は結構合っています。

厳密に言えば、日本語の内積の訳はInner Productかもしれませんが、実際に英語に訳す時はDot Productの方が理解されやすいというかInner Productだと下手すると理解されない可能性もあるかもしれません。そんくらい聞いた事がないです。

内積を英語に訳す時は、Dot Productと言っておいた方が無難な気がします。

次に、Dot Productを日本語に訳す時は内積と訳しても大丈夫か調べます。つまり今度は日本語でドット積と内積についての違いを述べている文献を当たります。

Noteにそのものずばりの解説がありました。「ドット積と内積の違い」[3]です。

f:id:kazuhironagai77:20211024232649p:plain

いや、そんな事は無いんじゃない。行列って結局はVectorの表現を変えただけだから。と思って読み進むとなんと、

f:id:kazuhironagai77:20211024232703p:plain

マジで!

Pythonちゃん。本当なの!

一応、公式の文献で確認します。NumPyのAPI中にあるnumpy.dot [4] をみると

f:id:kazuhironagai77:20211024232726p:plain

f:id:kazuhironagai77:20211024232732p:plain

本当に行列を返しています。

これ以上は前文でやるには長くなり過ぎるため、一端中止にして続きは来週します。

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

<本文>

1.今週の予定

今週も以下の内容でやっていきます。

  • Niagara : 何かやる。
  • Material : Ben Cloward氏のTutorialを勉強する
  • NPCAIを作成するためのAIの復習の続き
  • World CompositionによるMap1の作成(バグの直し)
  • UE5におけるWorld Partitionの勉強の続き

2.Niagara : 何かやる。

2.1 先週までの復習

今週、何を勉強するのかを決める前に、先週までずっとやっていたStatic MeshからParticleを発生させるEffectの勉強がきちんと区切りがついたのかを一応確認します。

2021-10-10のblogを見直すとStatic MeshからParticleを発生させるEffectの勉強の目的は

f:id:kazuhironagai77:20211024232817p:plain

であると述べていました。

<Meshが消える技術>

Meshが消える技術は、MaterialのOpacity Maskにどういう値をPassするかです。

f:id:kazuhironagai77:20211024232835p:plain

Building advanced effects in Niagara | Unreal Engine [5]では、

f:id:kazuhironagai77:20211024232849p:plain

Dither Temporal AA ノードを使用していますし、

先週まで勉強していたCGHOW氏のDisintegration in UE5 Niagara Tutorial | Download Files [6]では

f:id:kazuhironagai77:20211024232903p:plain

Sphere Maskノードが担当してます。

<Particle をMeshに沿って発生さえる技術>

Particle をMeshに沿って発生さえる技術は、先週のBlogに良くまとめられていますが、Particle Spawn SectionのInitialize Mesh Reproduction Sprite ModuleやSample Static Mesh Moduleが担当しています。

更に深く解説すると

f:id:kazuhironagai77:20211024232922p:plain

Random Tri Coordノードを使用して指定したStatic MeshからMeshを一個だけ選択します。そのMeshの位置をGet Tri Positionノードを使用して特定します。最後にその位置をParticle のPositionにセットします。

Particle のPosition変数はParticleを発生する位置を指定するための変数なので、上記のやり方で指定したStatic Meshに沿ってParticleを発生させる事が出来ます。

<発生したParticleを動かす技術>

Disintegration in UE5 Niagara Tutorial | Download Files [6]ではStatic MeshからParticleを発生させているので単にCurl Noise Force Moduleを使用するだけでParticleが動きます。

Building advanced effects in Niagara | Unreal Engine [5]では

f:id:kazuhironagai77:20211024232941p:plain

を使用していました。どちらにしてもParticleが発生した後は、普通のParticleを動かすのと変わらないと言う事でした。

<Particle をMeshの消えた部分に沿って発生さえる技術>

後、今回はまとめませんが、このEffectで最も複雑なのはParticle をMeshの消えた部分に沿って発生させる技術です。この部分を理解するのは結構大変です。

<まとめ>

一応は、勉強の目的は達しています。このEffectで最も複雑なParticle をMeshの消えた部分に沿って発生させる技術の部分のまとめはまた今度やります。

2.2 今週は何を勉強するのかを決める

もうしばらくはMeshからParticleを発生させるタイプのEffectはやりたくないです。

何か面白いEffectはないかなと探そうと思った矢先にUnreal CG氏のTime Distortion Effect - UE4 Tutorial [7] がお勧めで表示されていました。

f:id:kazuhironagai77:20211024233010p:plain

凄い!

これに決めました。

ただBen Cloward氏のTutorial でDistortion Shader - UE4 Materials 101 - Episode 4 [8] のTutorialで

f:id:kazuhironagai77:20211024233036p:plain

こんなのを作成しているのがあります。

と言う事は、もしかすると80%位、Materialが主で20%位しかNiagaraを使用していないかもしれません。

まあそれでもやってみる事にしました。

2.3 Unreal CG氏のTime Distortion Effect - UE4 Tutorial [7]を勉強する

CascadeのEffectの製作をした時に、Unreal CG氏のTutorialに非常にお世話になりました。

ただその当時の私はあんまりVFXというモノが何なのか理解していなかった事と、Cascadeの仕組みをParticleを発生させるための観点から理解するという概念を全く持ってなかったため全然、身に付かず単にUnreal CG氏の言われた通りのEffectを制作するだけでした。

今回はもう少し深堀りして仕組みまできちんと理解出来るようにしたいです。

UE4を使用して作成しています。Versionまでは分からないですね。いつもの4.26でやる事にします。

Unreal CG氏のTutorial用に別のLevelを作成しました。

f:id:kazuhironagai77:20211024233100p:plain

Third Person Example Mapとはちょっとだけ違いますが、まあ許容範囲でしょう。

NSをFountain Templateを使用して作成しました。

f:id:kazuhironagai77:20211024233117p:plain

まずParticle Spawn SectionのAdd Velocity Cone Moduleの値を

f:id:kazuhironagai77:20211024233130p:plain

以下の様に変更します。

f:id:kazuhironagai77:20211024233150p:plain

Particleが全然上に飛ばなくなっちゃいましたね。

f:id:kazuhironagai77:20211024233208p:plain

Particle Update SectionのGravity Force Moduleを切ってCurl Noise Force Moduleを追加します。

f:id:kazuhironagai77:20211024233222p:plain

こんな感じです。

f:id:kazuhironagai77:20211024233236p:plain

この後M_FlakeをSprite RendererのMaterialにセットしますが、M_Flakeの作成方法が分かりません。

と思ったらこの動画最初から見てなかったです。途中から見てました。最初にM_Flakeの作成方法が出てました。

指定された場所からTextureをDown Loadしました。

f:id:kazuhironagai77:20211024233252p:plain

こんなトコまで無料で提供してくれているのか。感服です。

f:id:kazuhironagai77:20211024233306p:plain

M_Flake出来ました。

Render SectionのSprite Renderer ModuleのMaterialにセットします。

f:id:kazuhironagai77:20211024233319p:plain

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

f:id:kazuhironagai77:20211024233334p:plain

Spawn Rateですが、

f:id:kazuhironagai77:20211024233347p:plain

に新しいFloat 型の変数、Flake Amountを作成してSpawn Rate ModuleのSpawn Rate変数にセットします。

f:id:kazuhironagai77:20211024233401p:plain

こうする事でLevel上に配置されたこのNSのInstanceのSpawn Rateを

f:id:kazuhironagai77:20211024233414p:plain

Flake Amountから調節出来るようになります。

f:id:kazuhironagai77:20211024233428p:plain

更にFlake Amount変数のDefault値は

f:id:kazuhironagai77:20211024233442p:plain

System Settings SectionのUser Parameters Moduleを選択すると、以下の様に表示されるので

f:id:kazuhironagai77:20211024233455p:plain

そこで設定出来ます。

これは言われてみればその通りですが、新しい技ですね。覚えました。

この後で、Static MeshからのParticle のSpawnをやっています。

f:id:kazuhironagai77:20211024233509p:plain

はい。

お馴染みのやり方です。

f:id:kazuhironagai77:20211024233524p:plain

こんな感じです。

この後、CubeにInheritedするやり方を紹介しています。

f:id:kazuhironagai77:20211024233538p:plain

あれ

f:id:kazuhironagai77:20211024233552p:plain

頭の中心からしかParticleが発生していません。

Tutorialでは

f:id:kazuhironagai77:20211024233606p:plain

こんな感じで全身からParticleが発生しています。

その後の例で、Static Meshの設定からAllow CPU Accessにチェックを入れないと駄目と言っていたのでこのCubeのAllow CPU Accessにチェックを入れてみました。

f:id:kazuhironagai77:20211024233646p:plain

そしたらTutorialと同じ様にCubeの全体からParticleが発生するようになりました。

f:id:kazuhironagai77:20211024233707p:plain

一応Tutorialと同じModelでも試しました。

f:id:kazuhironagai77:20211024233721p:plain

今度はParticleに発生する箇所の色を付けます。

f:id:kazuhironagai77:20211024233736p:plain

新しいScratch Moduleを作成してG buffer Colorと名付けます。

f:id:kazuhironagai77:20211024233811p:plain

ここの名称ですが最初のScratch Pad Moduleを作成した時しか名前の入力が出来ません。

f:id:kazuhironagai77:20211024233827p:plain

こっちの名称は変更出来ますが、この名前を変更してもModuleの方の名前はScratch Moduleのままです。

名前の変更方法あるんでしょうか?

INPUTであるNew GBuffer変数を追加しました。

f:id:kazuhironagai77:20211024233841p:plain

GBufferを使用するのは多分始めてです。GBufferが何を指しているのかは後でしっかり復習します。

f:id:kazuhironagai77:20211024233856p:plain

Decode Base Color ノードを繋げました。

このノードも初めて使用します。後でこのノードについても調べます。

Decode Base ColorのScreen UVに値をセットします。

f:id:kazuhironagai77:20211024233909p:plain

Particle のPositionをWorld Position to Screen UVノードを使用してCoordinateを変換します。そしてScreen UVに値をパスします。

これも初めて見る実装です。Coordinateの変換は話には沢山聞いていましたが、実際にNiagaraで使用したのは初めてです。

Screen UVはカメラが撮影したImageを指していると思われます。

f:id:kazuhironagai77:20211024233923p:plain

OpenGLだと以下に示した様なCoordinateに分けられますが、

f:id:kazuhironagai77:20211024233939p:plain

Learn OpenGLCoordinate Systems [9] より

NiagaraのScreen UVは、最後のScreen Spaceに当たるみたいですね。

CLIP SPACEとSCREEN SPACEの違いを忘れてしまったんですがCoordinate Systems [9]に説明がありました。

f:id:kazuhironagai77:20211024234003p:plain

座標軸が、-1~1だったのが、0からPixel数に変化しているのが違いみたいですね。すっかり忘れていました。

UEのNiagaraにおけるScreen UVの座標はどこが0なんでしょうね。左上か左下か?

これも後で調べます。

採取した色をParticle Colorにセットします。

Tutorialでは以下の方法でセットしていますが

f:id:kazuhironagai77:20211024234017p:plain

Alphaの値をZで代用してるのは良いんでしょうか?

1を入れた方がマシじゃないでしょうか?

f:id:kazuhironagai77:20211024234103p:plain

でもMaterialの色と同じ色になっています。

こんな方法でStatic Meshの色をParticleに移植出来るんですね。驚きです。

もし○○したかったら、とTutorialで言っていますが、何をしたいのか早口過ぎて聞き取れません。Particleをカメラ寄りに発生したいなら、と言っている気もしますがどうでしょう?分かりませんね。

兎に角やります。

Camera Offset ModuleをGbuffer Colorの前にセットします。

f:id:kazuhironagai77:20211024234118p:plain

値は30にセットします。

f:id:kazuhironagai77:20211024234132p:plain

こんな感じです。

f:id:kazuhironagai77:20211024234145p:plain

正直何が変わったのか分かりません。

Camera Offsetを200にしてみました。

f:id:kazuhironagai77:20211024234200p:plain

Particle がカメラの前で発生する様になりました。

f:id:kazuhironagai77:20211024234215p:plain

何で今、こんな機能を追加したのかは不明ですが、Camera Offset Moduleの機能は大体理解しました。後でもっと詳しく調べますが。

次の実装の目的を説明していますが、また聞き取れません。

実装部を先に見た所、カメラとEffectの配置された位置によって発生するParticleの量を0から100%まで変化させる機能を追加しているようです。

この機能は興味深いです。やってみましょう。

Emitter Update SectionにScratch Moduleを新しく作成します。

f:id:kazuhironagai77:20211024234229p:plain

Emitter Update SectionにScratch Moduleを作成するのも初めてですね。何気に興味深いです。

f:id:kazuhironagai77:20211024234243p:plain

Map Get ノードにInput New Camera Queryを追加しました。

あれ、今回はScratch Moduleの名前を変更しませんでしたね。後から変更するんでしょうか?そしたらどうやって名前を変更するのか習えますね!

Camera Queryってどんな変数タイプなんでしょう。後で調べる事にします。

f:id:kazuhironagai77:20211024234255p:plain

Get Camera Properties CPU/GPUノードを追加します。

Camera Queryが初めて使用する変数のタイプなので、そのタイプが持つ関数も勿論初めて使用するモノばかりです。Get Camera Properties CPU/GPUノードも勿論初めて使用します。

Get Camera Properties CPU/GPUノードのCPU/GPUってどういう意味なんでしょう?

普通にGet Camera Propertiesノードで良いと思うのですが、敢えてその後にCPU/GPUを付ける位だから何か意味が有るんでしょうね。

出力もCamera Position World以外は不明ですね。

f:id:kazuhironagai77:20211024234308p:plain

まあ、このノードも後でじっくり調べましょう。

今度はMap GetノードにENGINE OWNER Position変数を追加します。

f:id:kazuhironagai77:20211024234321p:plain

ENGINE OWNER Position変数は、このNSのInstanceがLevel上に配置された時のWorld Spaceにおける位置の情報を保持しているはずです。

f:id:kazuhironagai77:20211024234335p:plain

このENGINE OWNER Position変数の値をDistance Based FallOffノードのStart Positionに繋ぎました。

あ。もう分かりました。

Get Camera Properties CPU/GPUノードのCamera Position Worldの値をこのDistance Based FalloffノードのEnd Positionに繋ぐ訳です。そしてNormalized Falloffで出力すればカメラとNSの距離によって0から1の値が得られます。

途中までは合ってましたが、Distance Based FallOffノードのDistanceの値をMap GetノードのINPUT Distance変数から取っています。

f:id:kazuhironagai77:20211024234349p:plain

Start PositionがあってEnd Positionがあれば、その距離は計算で出ます。その距離を0から1に変換するためには、計算した距離に対する100%の距離が必要でした。それをここでPassしているんですね。

f:id:kazuhironagai77:20211024234404p:plain

Map SetノードにFloatタイプの新しい変数、EMITTER SpawnProを追加します。この変数に先程のDistance Based FallOffノードのNormalized Distance Invertedの値をパスします。

これでこのScratch Moduleは完成のはずです。

Applyボタンをクリックします。

f:id:kazuhironagai77:20211024234417p:plain

何かWarningが表示されています。

TutorialでScratch Moduleから名前を変更しました。クリックしたら名前の変更が出来るようになっていたんですが、あれさっきは何回もクリックしても出来なかったんですが。

試してみます。

f:id:kazuhironagai77:20211024234430p:plain

普通に出来ましたね。???です。

Spawn Rate ModuleのSpawn Probability変数に先程作成したEMITTER SpawnProをセットします。

f:id:kazuhironagai77:20211024234443p:plain

TutorialではDistance Check ModuleのDistance変数に1000を代入してテストしてます。

f:id:kazuhironagai77:20211024234458p:plain

離れるとParticleが発生しなくなり、近づくとParticleが発生しています。

同様のテストを試してみます。

Distance Check ModuleのDistance変数の値を500に変更します。

f:id:kazuhironagai77:20211024234512p:plain

こんな感じです。

f:id:kazuhironagai77:20211024234527p:plain

カメラを近づけます。

f:id:kazuhironagai77:20211024234544p:plain

Particleが発生しました。

おお。出来ました。

今度は発生するParticleのサイズを大きい破片と小さい破片に変更します。

今あるEmitterを大きい破片用にします。

Initialize Particle ModuleのSprite AttributesのSprite Size を以下の様に変更します。

f:id:kazuhironagai77:20211024234558p:plain

EmitterをDuplicateして

f:id:kazuhironagai77:20211024234612p:plain

設定を少し変えます。

f:id:kazuhironagai77:20211024234626p:plain

f:id:kazuhironagai77:20211024234631p:plain

こんな感じです。

f:id:kazuhironagai77:20211024234646p:plain

凄い綺麗です。

次の機能を作成します。

またどんな機能を作成するのか聞き取れません。本当にインド人の英語は早口です。

あ。

そうだ。再生速度を0.75に設定して聞きなおしてみます。

うーん。

Prismatic? Effectを作成しますって聞こえますね。

床のグネグネを作成するんでしょうか?

まあやっていくうちに分かるでしょうね。

新しいMaterialを作成します。名前はM_Prismと名付けました。

f:id:kazuhironagai77:20211024234703p:plain

Blend ModeをTranslucentにセットします。

f:id:kazuhironagai77:20211024234716p:plain

Rotatorノードを使用しています。

f:id:kazuhironagai77:20211024234730p:plain

Materialの勉強でTexture Coordinateに掛け算したり足し算したりしましたが何で、回転させる事はしないのか不思議に思っていましたが、やっぱり回転させる機能を持つNodeはあるんですね。

また新しい事を学びました。

Materialの内容はここでは全部載せる必要ないな。と思って作成していたら

f:id:kazuhironagai77:20211024234745p:plain

上記の実装で以下のMaterialが出来ました。

f:id:kazuhironagai77:20211024234801p:plain

凄い。これは後でしっかり勉強し直します。

これで床のEffectを作成するのかと思ったら違ったみたいです。

またEmitterをDuplicateして今度はRefractionを作成しました。

f:id:kazuhironagai77:20211024234817p:plain

Render SectionのSprite Renderer ModuleのMaterialに先程作成したMaterialであるM_Prismをセットします。

f:id:kazuhironagai77:20211024234832p:plain

後は、他のParameterを微調整して以下の様になりました。

f:id:kazuhironagai77:20211024234847p:plain

更に微調整します。

f:id:kazuhironagai77:20211024234901p:plain

Cubeが少しですが崩壊しているように見えますね。

f:id:kazuhironagai77:20211024234917p:plain

更に微調整しました。

うーん。

微妙ですね。

Tutorialと同じように階段にこのEffectを付けてみました。

f:id:kazuhironagai77:20211024234936p:plain

Tutorialと比べると何か違います。

f:id:kazuhironagai77:20211024235000p:plain

今週はここまでですね。

結構時間がかかりました。

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

3.1 Detail Normal Mapping - Shader Graph Basics - Episode 13 [10] を勉強する

まず、パラっと見たんですが、これってTutorialで使用しているTextureと同じモノがないと、自分で確認するのは無理だと思いました。

Quixelから岩の3DモデルとTextureそしてその岩に使用しているMaterialなどは手に入りました。

f:id:kazuhironagai77:20211024235049p:plain

このTutorialで使用しているもう一つのTextureですが、

f:id:kazuhironagai77:20211024235104p:plain

RとGには通常のNormal Mapが入っていて、Blue channelにはRoughnessのためのMultiplierがあり、

f:id:kazuhironagai77:20211024235117p:plain

Alpha ChannelにはColorのためのOverlayが入っています。

f:id:kazuhironagai77:20211024235131p:plain

これはどうやって手に入れるんでしょうか?

自分で探すにしてもどういう基準でこれらのTextureがそれぞれの使用のために選ばれたのが不明です。

今までずっと神回だったのですが、今回のMaterialのTutorialはかなりガックリな内容になるかもしれませんね。

それはそれでパッとやってしまいましょう。

先程のTextureの様に色々なDataを一個のTextureにまとめている場合はCompression SettingはBC7を選ぶべきと言っていました。

f:id:kazuhironagai77:20211024235144p:plain

流石にこういう話は役に立ちます。

今回、自分で実装出来ない場合は講義を簡単にまとめるだけにするかもしれません。それはそれで後から読んだときに役に立つでしょうし。

もう一つ大切な事はTextureがColorのDataを保持していない時はsRGBは外しておく事だそうです。

f:id:kazuhironagai77:20211024235157p:plain

これは知っていました。

講義のMaterialを真似て以下のMaterialを自作しました。

f:id:kazuhironagai77:20211024235210p:plain

Roughnessは以下のGreenのChannelに入っているためそこだけは変更しました。

f:id:kazuhironagai77:20211024235223p:plain

ただDpRFの残りのChannelに入っているDataが何なのかが分かりません。

作成したMaterialを使用したRockが以下のものです。

f:id:kazuhironagai77:20211024235237p:plain

確かに近づくと単なる写真になります。

f:id:kazuhironagai77:20211024235252p:plain

拡大しても写真に見えないようにこれからしていくわけです。

この近づいたときに使用するためのTextureですが、

f:id:kazuhironagai77:20211024235305p:plain

これで代用する事にします。

と言ってもこのNormal TextureのRGだけ使用します。

以下の実装を作成しました。

f:id:kazuhironagai77:20211024235320p:plain

動画ではMaskノードが抜けていましたが、どう考えても講義の解説通りに解釈するとMaskノードでRGを指定する必要があります。のでそこは追加しました。

よく動画の解説を聞いたら以下の部分はNormal MapがNormal MapとしてTextureに保持されていない場合に必要な工程だそうです。

f:id:kazuhironagai77:20211024235335p:plain

Normalの範囲は-1から1です。しかし通常のTextureの値は0から1です。ので通常のTextureをNormal Mapとして使用する場合は、上記の様に2を掛けて1引く必要があります。ただしTextureがNormal Mapとして指定されている場合はその必要はないそうです。

うーん。こういう情報は本当に勉強になります。

やっぱ凄いです。

でもMaterialはどこでこのTextureはNormal Mapじゃないと判断するんでしょうか?

f:id:kazuhironagai77:20211024235349p:plain

ここでしょうか?

兎に角、以下のように直しました。

f:id:kazuhironagai77:20211024235403p:plain

Derive Normal Zノードですが、TutorialのTextureはNormal MapがRGしかなくてBは計算から求めるしかないです。

Derive Normal Zノードの機能を公式のDocumentで調べるとVector Operation Expressions [11] に以下の説明があります。

f:id:kazuhironagai77:20211024235417p:plain

この計算をしても良いんですが、今私が使用しているNormalにはBの値も提供されているので、

f:id:kazuhironagai77:20211024235430p:plain

これでいく事にします。

最後のBlend Angle Corrected Normalノードは先週、勉強したRNM方式によるBlendingのはずです。

最終的に以下の様な実装になりました。

f:id:kazuhironagai77:20211024235447p:plain

これでテストします。

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

f:id:kazuhironagai77:20211024235503p:plain

比較ためにBlendする前のMaterialも撮影しました。

f:id:kazuhironagai77:20211024235523p:plain

DetailのNormalをBlendした場合、細かい部分の陰影が存在しています。

後、結構重要なのが、DetailをBlend してない方の画面を長時間眺めていたら、結構な3D酔いが起きました。脳が平面なのか立体なのか混乱するからでしょうか?兎に角、酔いました。

今度はRoughnessにDetailを追加します。

一番近そうなTextureを探してきました。

f:id:kazuhironagai77:20211024235754p:plain

これのB Channelを使用します。

f:id:kazuhironagai77:20211024235809p:plain

RoughnessにDetailを追加する場合は簡単で、以下に示した様にお互いの値を掛けるだけです。

f:id:kazuhironagai77:20211024235825p:plain

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

f:id:kazuhironagai77:20211024235839p:plain

何か銀でも含んでいるようなキラキラの粒が散在している岩になりました。

最後にColorとBlendする方法です。

このColorとBlendするためのTextureには条件があって以下に示した様に、

f:id:kazuhironagai77:20211024235852p:plain

値の大部分が‐0.5から0.5の間である必要があるそうです。

そんな事言われても、あるTextureで対応するしかないので、またこれで代用します。

f:id:kazuhironagai77:20211024235905p:plain

ColorのBlend方法だけ勉強出来ればまあOKとします。

ColorのBlendの仕方は以下に示した様にBlend_Overlayノードを使用します。

f:id:kazuhironagai77:20211024235919p:plain

Blend_Overlayノードは以下の解説が出て来ました。

f:id:kazuhironagai77:20211024235932p:plain

結果です。

f:id:kazuhironagai77:20211024235946p:plain

確かに岩の陰影が濃くなりました。

Materialに細部の表現を追加する時、Baseの色、Roughness、そしてNormalに細部のDataをBlendします。今回はその方法について学びました。

ただし、別に細部の情報は単純に足しても掛けてもある程度は表現出来る訳で、今回のやり方は今の所、コストと精度の関係から最もよく使用されているTechniqueと言うだけの事でもあります。

更にLandscapeとは違い、単なる岩のTextureにそこまで近づく理由もない訳で、今回の技術がどこまで実戦で必要になるかは疑問です。

今回の技術は、むしろ、あまり精度の良くないTexture2枚を使用して精度の高いMaterialを作成する時とかの方が役に立ちそうです。

以上です。

3.2 UE4 - Materials and UV Rotation [12] を勉強する

2021-10-03のBlogでTextureに対する加算と乗算を行いました。これは言い換えれば、Textureに対する移動と拡大・縮小です。となると後は回転があればTextureを自在に動かす事が出来ます。

そして今週のNiagaraの勉強中にTextureに対する回転も出来る事が分かりました。

f:id:kazuhironagai77:20211025000023p:plain

所が、この回転はTextureをずっと回転させています。私が欲しいのは一回だけ回転させる機能です。

そしたらgameDev Outpost氏のUE4 - Materials and UV Rotation [12]にそのものずばりがありました。

f:id:kazuhironagai77:20211025000040p:plain

ボっとこれを見てたんですが、これってひょっとしてOpenGLのZ軸回転に使用した行列のXYを計算しているだけじゃないの?と思って確認しました。

以下にLearn OpenGLのTransformation [13]にあるZ軸回転に使用する行列を示します。

f:id:kazuhironagai77:20211025000105p:plain

何かそんな気がします。

急遽ですが、これを確認する事にします。

このMaterialにRotationを実装します。

f:id:kazuhironagai77:20211025000120p:plain

こんな感じです。

f:id:kazuhironagai77:20211025000133p:plain

まず実装結果を示します。

f:id:kazuhironagai77:20211025000148p:plain

解説をします。

最初にTextureの中心をずらします。回転軸をTextureの中心に移動させます。ここは‐0.5を追加しているんですが、0.5が正しいんじゃないのかと思っています。後で詳しく検討します。

次が回転の実装です。これも後で詳しく検討します。

その次が、移動したTextureの中心を戻すための実装です。何故かUE4 - Materials and UV Rotation [12]では移動させた値をもう一回加算していました。足したら引くべきだと思います。結果は同じでした。

<回転について>

Learn OpenGLのTransformation [13]にあるZ軸回転に使用する行列をもう一回見ていると

f:id:kazuhironagai77:20211025000207p:plain

x軸の値は、

f:id:kazuhironagai77:20211025000220p:plain

です。Rotationの実装の計算は、

Cos θ*x + Sinθ*y

でした。

Y軸の値は、

f:id:kazuhironagai77:20211025000253p:plain

Cos θ*y-Sinθ*x

でした。

似てるけどちょっと違う。

うーん。ひょっとしてDirectXだから計算がちょっと違うとか?

DirectX Factor : 3D Transforms on 2D Bitmaps [14]をみると

f:id:kazuhironagai77:20211025000317p:plain

となっていました。

うーん。

これだと、Tutorialの計算と同じですが。

単純にこの行列が出て来たからと言って「はい。出来ました。」とは言えないです。何故かと言うとDirectXには詳しくないのですが、行列の計算がOpenGLと違ったような気がしていて、確か行と列が逆になった気がするからです。

これ行と列を逆にするとOpenGLと同じなんですよね。

この二つの行列、等価な気もして来ました。

Learn OpenGLのTransformation [13]にあるZ軸回転に使用する行列と同じ式で実装してみました。

f:id:kazuhironagai77:20211025000332p:plain

Degree = 0の時です。

f:id:kazuhironagai77:20211025000356p:plain

Degree = 60の時です。

f:id:kazuhironagai77:20211025000421p:plain

Degree = 90の時です。

f:id:kazuhironagai77:20211025000435p:plain

Degree = 120の時です。

f:id:kazuhironagai77:20211025000448p:plain

Degree = 180の時です。

f:id:kazuhironagai77:20211025000500p:plain

Degree = 240の時です。

f:id:kazuhironagai77:20211025000513p:plain

Degree = 300の時です。

f:id:kazuhironagai77:20211025000525p:plain

Degree = 360の時です。

f:id:kazuhironagai77:20211025000537p:plain

普通に回転しています。

あっ!

もう一回、Tutorialの式に戻して回転させます。

Degree = 0の時です。

f:id:kazuhironagai77:20211025000550p:plain

Degree = 60の時です。

f:id:kazuhironagai77:20211025000602p:plain

回転する方向が違う!!!

このTutorialのやり方だと時計回りに回転しますが、OpenGLの式だと反時計回りに回転しています。

ああ、Z軸の向きが違うと言う事か。

どっちの回転が正しいんでしょうか?

Rotatorノードを使用してTextureを回転させてみます。

f:id:kazuhironagai77:20211025000615p:plain

このノードが回転させる方向が正と考えて問題ないでしょう。

f:id:kazuhironagai77:20211025000827g:plain

反時計回りじゃないですか。

と言う事はOpenGLの回転の行列をそのまま適応できると言う事ですね。

ああ、4年。

約4年間もかかって、やっと一部ですがOpenGLの理論とUEの理論が繋がりました。長かった。

<中心の移動について>

これが納得出来ないんです。

なんで‐0.5を加えると絵の中心が軸になるんでしょう。0.5なら納得するんですが。

以下の実装で色々実験してみます。

f:id:kazuhironagai77:20211025000928p:plain

f:id:kazuhironagai77:20211025000934p:plain

0.5、0.5を追加します。

f:id:kazuhironagai77:20211025000946p:plain

はい。想定した通りです。

回転軸は左上にあるはずですから、これで回転させれば綺麗な回転をするはずです。

因みに‐0.5、‐0.5の場合は

f:id:kazuhironagai77:20211025001001p:plain

こうなります。

0.5、0.5の状態のまま回転させてみます。

Degree = 0

f:id:kazuhironagai77:20211025001016p:plain

Degree = 30

f:id:kazuhironagai77:20211025001029p:plain

え。

何で?

何でずれるの?

‐0.5、‐0.5の状態でテストします。

Degree = 90

f:id:kazuhironagai77:20211025001043p:plain

えー。

こんな回転してるんですか?

これについては1週間時間を置いてまた考えます。

考えるためのヒントとしてDegreeの代わりにTimeノードをつけた場合のScreen shotを残しておきます。

f:id:kazuhironagai77:20211025001110g:plain

4.NPCAIを作成するためのAIの復習の続き

公式のDocumentであるArtificial Intelligence [15]のAI Perceptionを勉強しようとしたら

f:id:kazuhironagai77:20211025001149p:plain

まだNavigation Systemの復習を一個もしてない事に気が付きました。

どうせ全部復習し直すのですから、Navigation Systemもきっちり勉強し直します。

と言う事で今週はNavigation System [16]の復習をします。

Navigation Systemを見たら以下に示した様に沢山のTutorialがありました。

f:id:kazuhironagai77:20211025001205p:plain

Basic Navigation [17]の勉強の前にNavigation System [16]で述べられていた重要そうなキーワードを書き残しておきます。

Navigation System には以下に示した3つのGeneration Modesがあるそうです。

  • Static,
  • Dynamic
  • Dynamic Modifiers Only

Navigation System は更にAgentを避ける為に二つのSystemを提供しているそうです。

  • Reciprocal Velocity Obstacles (RVO),
  • The Detour Crowd Manager

両方とも何の話をしているのか全く分かりませんね。

ここで紹介されているTutorialを勉強して行くうちに理解出来るでしょう。

4.1  Basic Navigation [17]の勉強

何と、このTutorial、Behavior Treeを使用していません。

先週まで、UE_AIは単なるIF節。しかしBehavior Treeを採用したから4つのクラスを使用しない非常に複雑な形になった。と断言して来たので、Behavior Treeを使用しないで作成するAIはとても興味深いです。

<Overview

Agentって何を指しているのかとおもったらAIにコントロールされるNPCの事でした。

簡単にまとめるとNavigation SystemはNPCが(障害物があっても)到達したい場所への行き方を見つける事を可能にします。と言っています。

<Goals

特に重要な事は言っていません。

<Objectives

このTutorialから学べる事がまとめられています。

私にとっては特に重要な事はないです。

<1 - Required Setup

このTutorial用の新しいProjectを作成しています。

勿論、私は前に作成したProjectを使用します。

ただし、新しいLevelだけは作成しました。

f:id:kazuhironagai77:20211025001309p:plain

<2 - Building the Navigation Mesh

Nav Mesh Bound Volumeを使用してNPCが移動出来る領域を作成します。

f:id:kazuhironagai77:20211025001330p:plain

この緑の領域はPを押すと表示されます。(知らなかった。)

以下に示したように緑が切れている箇所の直し方が解説されていました。

f:id:kazuhironagai77:20211025001344p:plain

Recast Nav Mesh – Defaultを選択します。

f:id:kazuhironagai77:20211025001357p:plain

Draw Offsetの値を増やします。

f:id:kazuhironagai77:20211025001410p:plain

私が自作した階段も緑が切れかけています。Draw Offsetの値を50に増やして直るか確認します。

f:id:kazuhironagai77:20211025001423p:plain

50にしました。

f:id:kazuhironagai77:20211025001436p:plain

以下の様になりました。

f:id:kazuhironagai77:20211025001449p:plain

こんな技術がある事すっかり忘れていました。

復習は大切ですね。

<3 - Visualizing the Navigation Mesh

緑の部分がどういうMeshで構成されているかを可視化するそうです。

正直言ってあんまり必要な技術ではない気がします。

以下に示したDraw Poly Edgesにチェックを入れると

f:id:kazuhironagai77:20211025001509p:plain

こんな感じに表示されました。

f:id:kazuhironagai77:20211025001522p:plain

<4 - Creating your First Agent

Third Person CharacterをCopyし以下の実装をしました。

f:id:kazuhironagai77:20211025001542p:plain

うーん。AI Controllerすら作成しないんですね。

ホントにこれで動くのか試したら普通に動きました。

f:id:kazuhironagai77:20211025001556p:plain

Basic Navigation [17]のまとめ>

初心者向けのTutorialですが、それなりに勉強になりました。

Draw Offsetの機能なんですっかり忘れていました。

それよりもこのTutorialが私の興味を引き付けるのは、私が主張している「UEのAIはBehavior Treeを採用したからこんな複雑な形になったしまったが、実際は単なるIF節である。」を強力にSupportする内容です。

Behavior Treeを使用しないで作成したAIで動くNPCはCharacterクラス内で全ての処理を実行しています。

非常に単純な実装で、Randomな場所に移動するという行為を実行しています。

私が作成するUEのAIのTutorialにこのBehavior Treeを使用しないAIは一個は追加したいです。

4.2 Modifying the Navigation Mesh [18]

何これ。中に更に二つに分かれています。

f:id:kazuhironagai77:20211025001620p:plain

あ。あの緑の部分の名前が分かりました。Navigation Meshと言うそうです。

ここではそのNavigation Meshの編集方法について習うそうです。

Modifying the Navigation Mesh Preparation Guide [19]

ここでは次のTutorialで使用するためのLevelを作成するようです。Navigation Meshの編集方法を習うための準備ですね。

f:id:kazuhironagai77:20211025001639p:plain

出来ました。

ここは単に初心者でどうやってLevelの作成をしたらいいのか分からない人向けに次のTutorialで使用するためのLevelの作成方法を教えるだけでした。

ただ、ここでもBehavior Treeを使用しないAIを作成してNPCをボールに向かって動かしています。

その点は面白かったです。

Modifying the Navigation Mesh [20]

<< Overview >>

特になしです。

<< Goals >>と<< Objectives >>

以下の使用方法を勉強します。

  • Navigation Modifier Volumesを使用してNav Meshの編集
  • Navigation Proxy Linksを使用して2つのNav Meshを繋げる
  • Smart Proxy Linksを使用してNPCが2つのエリアをジャンプして移動出来るようにする
  • ActorBPからRun Time中にNavigation Meshを再構成する方法

Navigation Modifier VolumesとNavigation Proxy Linksは一回位は使用した事がありますが、やり方はもう忘れました。Smart Proxy Linksについては全く覚えていません。

<< 1 - Required Setup>>

これはさっきやったところです。

<< 2 - Using Navigation Modifier Volumes>>

Navigation Modifier VolumeをNav Mesh内に配置しました。

f:id:kazuhironagai77:20211025001725p:plain

配置した所の緑が消えましたね。

更にもう一個Navigation Modifier Volumeを追加しました。

f:id:kazuhironagai77:20211025001739p:plain

この時点で本当にNPCがボールを追いかける事が出来るのかかなり疑問です。

それを確認します。

f:id:kazuhironagai77:20211025001753p:plain

階段を登ってボールにつきました。

f:id:kazuhironagai77:20211025001806p:plain

Navigation Modifier Volumeで出来た溝を避けてボールにつきました。

出来ています。

f:id:kazuhironagai77:20211025001827p:plain

これだけ出来ていませんでした。

橋の下を潜ろうとしていますがNPCの方が大きすぎて潜れません。

新しいNavigation Modifier Volumeを追加しました。

f:id:kazuhironagai77:20211025001840p:plain

今度の場所はArea ClassにNavArea_Obstacleをセットしました。

f:id:kazuhironagai77:20211025001853p:plain

Nav Area Obstacleはその場所を通らなければ目的地に到達できない場合のみにその場所を通るようにNPCに指定出来るそうです。

他の選択肢についても解説されていました。

f:id:kazuhironagai77:20211025001908p:plain

ここで気になるのは、NavArea_LowHeightです。

これってさっきの天井が低くて動けない時に、天井の下の部分に配置しておけば、NPCは自動的にこの下の部分は潜れないと判断して別なルートを選択するんでしょうか?

f:id:kazuhironagai77:20211025001923p:plain

これは後で調べる事にします。

後、Area ClassはUE4C++を使用すれが自作出来そうなんですが、Programmer向けのTutorialかなんかでそのやり方も別途説明してもらえると有り難かったです。

最後に全般的な感想ですが、初心者向けというより、作業者向けって感じで、自分で考えて問題を解決する箇所がないです。これがとてもTutorialを続行するのを辛くしています。

<< 3 - Using Navigation Link Proxies>>

以下に示した様にNav Link Proxyで二つのNav Meshを繋げました。

f:id:kazuhironagai77:20211025001941p:plain

Link DirectionをLeft to Rightにセットしました。

f:id:kazuhironagai77:20211025002040p:plain

同じモノを反対側に作成する時にこのNav Link ProxyをAltで複製しました。そしたらWorld Outlinerには表示されるのですがLevel上から認識出来ませんでした。

何でなんでしょう?

今度はJumpさせます。

f:id:kazuhironagai77:20211025002100p:plain

これでJumpしてくれるんでしょうか?

f:id:kazuhironagai77:20211025002128p:plain

はい。Jumpする少し前のScreen shotしか取れませんでしたがJumpしました。

<<<Using a Nav Link Proxy to Allow Your Agent to Jump to Its Goal>>>

今度はSmart Linkの使用方法について勉強します。

パッと読んだんですが良く分かりません。取りあえずやってみます。

Jumpするための場所を作成します。

f:id:kazuhironagai77:20211025002150p:plain

ここであえてJumpと言っているんですから、先程の飛び降りるのとは違うはずです。

つまり飛び降りる時より、一寸だけ高い所とか一寸だけ遠い所にたどり着けるはずです。

f:id:kazuhironagai77:20211025002204p:plain

ので少しだけ高い位置かつ

f:id:kazuhironagai77:20211025002219p:plain

遠い位置に作成しました。

Nav Link Proxy BPから新しいBPを作成します。

f:id:kazuhironagai77:20211025002232p:plain

BPを開いてEvent Receive Link Reachedノードを追加します。

f:id:kazuhironagai77:20211025002244p:plain

このノードの機能は大体想像付きますが、以下のような説明がありました。

f:id:kazuhironagai77:20211025002256p:plain

想像した通りでした。

以下に示した様な実装をしました。Tutorialと全く同じはずです。

f:id:kazuhironagai77:20211025002309p:plain

このBPをLevel内に配置して以下に示したように先程作成した板とつなぎます。

f:id:kazuhironagai77:20211025002322p:plain

Tutorialの次の指示でCopy End Points From Link to Smart Linkボタンを押せとあります。

f:id:kazuhironagai77:20211025002335p:plain

が私のNav Link Proxy BPにはそのボタンがありません。

多分、私のVersionが4.27だからだと思います。

試してみます。

f:id:kazuhironagai77:20211025002347p:plain

Jumpはしましたが届かないで落っこちてしまいました。

仕方ないので高さなどを微調整しました。

f:id:kazuhironagai77:20211025002405p:plain

あんまりJumpはしている感じはありませんが隣の床に飛び乗る事は出来るようになりました。

人数を増やすと見てるだけでも楽しいです。

f:id:kazuhironagai77:20211025002420p:plain

でも問題もあります。

この位置に来ると必ず動かなくなります。

f:id:kazuhironagai77:20211025002432p:plain

他の人もここに捕まるとどんどん詰まってしまいます。

f:id:kazuhironagai77:20211025002453p:plain

何か喧嘩が始まったみたいです。

f:id:kazuhironagai77:20211025002511p:plain

移動中に他のNPCとぶつかると動けなくなるみたいです。

f:id:kazuhironagai77:20211025002526p:plain

途中からまったく動かない一体が誕生しました。

f:id:kazuhironagai77:20211025002538p:plain

何なんでしょうかこいつは。

後、Jumpしないで落ちています。

f:id:kazuhironagai77:20211025002551p:plain

何故かScreen shotの絵はjumpしています。

Navは結構奥が深いですね。

<< 4 - Generating the Navigation Mesh at Runtime>>

ここは軽くやる事にします。

Action Gameを作成するならこの辺は厳しく追及しないといけないかもしれませんが、村人のAIを作るのにあんまり必要な技術とは思えませんから。

Tutorialの通りに設定を変更します。

f:id:kazuhironagai77:20211025002615p:plain

回転する板を追加しました。

f:id:kazuhironagai77:20211025002628p:plain

SimulateをしたらMeshだけ回転してます。

Nav Modifierを追加しました。

f:id:kazuhironagai77:20211025002641p:plain

板の回転に吊られてNav Meshの形状が変化しました。

f:id:kazuhironagai77:20211025002708p:plain

<<<Using the Runtime Generation (Dynamic)>>>

今度は、Dynamicを選択した場合のやり方でしょうか?

Tutorialの通りにBP_Moving Actorを作成しました。

f:id:kazuhironagai77:20211025002727p:plain

f:id:kazuhironagai77:20211025002731p:plain

ボールが動いていますが、Nav Meshは動きません。

f:id:kazuhironagai77:20211025002745p:plain

Project SettingのRuntime GenerationをDynamicに変更します。

f:id:kazuhironagai77:20211025002757p:plain

テストします。

f:id:kazuhironagai77:20211025002812p:plain

微妙ですがNav Meshは変化しています。

こんなにNavの復習に時間がかかるとは思ってなかったです。

と言うか復習じゃないて初めて知る内容も結構ありました。

今週のAIの勉強はこれでお終いです。

5.World CompositionによるMap1の作成(バグの直し)

今週やる事はこれだけです。

f:id:kazuhironagai77:20211025002836p:plain

この変なバグを直す。

5.1 Streaming Distanceの変更

一番簡単にStreaming Distanceをもう少し大きくしてみます。200mに変更しました。

f:id:kazuhironagai77:20211025002855p:plain

当然、変な山は現れません。

f:id:kazuhironagai77:20211025002911p:plain

直ったと言えば直りました。

他の場所もチェックします。

以下の赤丸の部分に同様のバグが見られます。

f:id:kazuhironagai77:20211025002926p:plain

が、あまり目立たない言えなくもないです。

こういう事をして大丈夫なのか分かりませんが、Sub Level1-2だけStreaming Distanceを500mに変更してみました。

f:id:kazuhironagai77:20211025002940p:plain

一瞬だけBugが見えますが、本当に一瞬だけです。

f:id:kazuhironagai77:20211025002954p:plain

山に登ってみましたが、僅かにバグが確認出来ます。

f:id:kazuhironagai77:20211025003007p:plain

UE5ならこのバグは自然と消えるので諦める事にします。

5.2 Alt Key + CursorでLoad されているSub Levelが分かる件

もう止める。と言ったんですが、Alt Key + CursorでLoad されているSub Levelが見れる事が分かりました。

こんな感じです。

f:id:kazuhironagai77:20211025003032p:plain

これ使ったらどのSub LevelがBugをおこしているのか分かります。

Cursorの位置が見えないので大体の場所を赤点で示しています。

f:id:kazuhironagai77:20211025003046p:plain

赤で四角に囲った部分が消えます。

f:id:kazuhironagai77:20211025003100p:plain

この重なっている部分がbugを引き起こしているんじゃないでしょうか?

ここだけ確認してみます。

f:id:kazuhironagai77:20211025003117p:plain

重なっているActorを小さくして移動させました。

テストします。

f:id:kazuhironagai77:20211025003131p:plain

全然、駄目でした。

5.3 Monsterなどの動的なActorの生成をWorld Compositionでする為の検討をする

今週は検討だけします。

現状ではItemやMonsterはLevel BPで動的に生成します。

f:id:kazuhironagai77:20211025003153p:plain

これをそれぞれのSub Levelでやれば良いだけのはずです。

そしてItemやMonsterのSpawn用のDataはGame Instanceで管理しています。

f:id:kazuhironagai77:20211025003207p:plain

f:id:kazuhironagai77:20211025003212p:plain

これもData Tableで管理してGame Instanceで管理するのはSpawnするかどうかだけの方が管理し易いですね。今回は直しませんが次回のGame 制作ではそうします。

これを見ただけでではどのSub Levelに属しているのか不明ですので、ここで示されているLocationに静的にItemやMonsterを配置して位置を確認します。

そして静的なMonsterやItemがUnload やLoadしても大丈夫な事を確認します。

それが終わったら、それぞれのSub Level様にItem Spawn Dataを作成します。

f:id:kazuhironagai77:20211025003243p:plain

BPの変数にはCategoryを指定する場所があるのでMap1を指定します。それで管理出来るはずです。

Sub LevelからMonster やItemをSpawnする実装を作成します。

この実装方法はSpawn Items関数やSpawn Monsters関数を見れば分かります。

f:id:kazuhironagai77:20211025003259p:plain

f:id:kazuhironagai77:20211025003307p:plain

Monsterの配置を知るのと、それぞれのSub Level用のSpawn Monsterのデータを作成するのが大変そうですが、それ以外は簡単そうです。

5.4 戦闘が終わってBattle Field Mapから帰還した時

今、気が付いたんですが、戦闘が終わって、戦闘Mapから帰還した時、World Compositionで作成されるMapはCharacterが生成されてから1秒か2秒経ってから生成されますよね。

そうすると今までの方法だと戦闘が終わって、元のMapに戻ると、Landscapeから落ちて死んでしまう可能性が高いです。

調べるとPlayerの操作するキャラはRPG Game Mode Base BP内で生成されています。

f:id:kazuhironagai77:20211025003327p:plain

最初、このキャラの発生時間を遅らせれば良いと考えましたが、LandscapeはPlayerの操作するキャラの位置を知ってからSub Levelを生成するのでそのやり方だと永遠にLandscapeが発生しない可能性があります。

このキャラが生成して3秒間位重力の影響を受けないで浮いているようにしないといけないかもしれませんね。

<重力を切る方法の検討>

以下の方法で試してみました。

f:id:kazuhironagai77:20211025003347p:plain

かなり3D酔いしますがキャラは空中に浮いていて落ちません。

f:id:kazuhironagai77:20211025003402p:plain

3D酔いする理由がわかりました。キャラを浮いた状態で移動させる事が出来るからです。

f:id:kazuhironagai77:20211025003416p:plain

しかもこの状態で移動すると、一回方向を入れるとずっとその方向に進みます。

これが気持ち悪さを引き起こしているです。

この問題はひとまず置いておいてEを押すとキャラの重力が戻る仕組みを実装します。

f:id:kazuhironagai77:20211025003430p:plain

試してみます。

f:id:kazuhironagai77:20211025003443p:plain

出来ていました。

今度はCustom Eventを追加して1.5秒後に地面に落下する様にしました。

f:id:kazuhironagai77:20211025003458p:plain

こんな感じです。

f:id:kazuhironagai77:20211025003510g:plain

あんまりスムーズに撮影出来ませんでした。

これも来週試します。

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

今週はもう時間がなくなってしまったので、一個だけ確認します。それはLoading Rangeの確認です。Loading Range外のLandscapeはUnloadされているのかが知りたいです。

以下の条件でテストします。

f:id:kazuhironagai77:20211025003538p:plain

Playを押した後にwp.Runtime.ToggleDrawRuntimeHash2Dをcmdから入力しました。

f:id:kazuhironagai77:20211025003555p:plain

この白い円がLoading Rangeを示しているんでしょうか?

良く分かりませんね。

Loading Rangeを100mに変更しました。

f:id:kazuhironagai77:20211025003610p:plain

一マスが32mだとすると6マスと1/5マス位でしょうか。

32*6=92と1/5マス=6.4 なので98.4、まあ100mですね。

f:id:kazuhironagai77:20211025003642p:plain

Landscapeの端に来ました。

f:id:kazuhironagai77:20211025003659p:plain

黄色の線がLandscapeを表していると思ったんですが違いそうですね。円の中にある白い線がキャラが向いている方向を示してると思っていたんですが。この線は黒線のタイルに平行ですね。

このテストに使用しているLevelのLandscapeが2個重なっていました。

新しく作り直してもう一回テストします。

今、端っこにいます。

f:id:kazuhironagai77:20211025003722p:plain

中央に戻ります。

白い円の端が黒い線のマスの端と重なっています。

f:id:kazuhironagai77:20211025003746p:plain

最初に立っていた位置が、白い円の端になりました。

f:id:kazuhironagai77:20211025003804p:plain

山が消えました。

f:id:kazuhironagai77:20211025003825p:plain

4マスと半分位です。4.5*32=144mです。

円から外れたら消える訳ではないですね。

f:id:kazuhironagai77:20211025003847p:plain

今度は確認の為にActorを配置してみます。

f:id:kazuhironagai77:20211025003903p:plain

Actorが配置されているCellはまだ円の中にあります。

そしてActorも見えます。

f:id:kazuhironagai77:20211025003924p:plain

Actorは円の外に出ました。

Actorが配置されているCellはまだ円の中にあります。

Actorは表示されています。

f:id:kazuhironagai77:20211025003943p:plain

Actorが配置されているCellが円の外に出ました。

Actorは消えました。

これを見るとやっぱりWorld Partitionで設定出来るのは配置されているActorだけでLandscapeには何か別の基準が適応されているみたいです。

今週は時間がもうないのでまた来週、勉強する事にします。

7.まとめと感想

今週は、腰が痛くなってしまってあんまり集中出来なかったです。

結構、腰痛って集中力を削ぎますね。

まあ、こういう時のあると納得するしかないですね。結局、コツコツやってる方が最終的にはデカイ成果を出せる場合が多いですし。駄目な時は駄目なりに課題をこなしていくだけですね。

<参照(Reference)>

[1] Takeshi, A. (n.d.). What’s the difference between inner product, dot product and scalar product? Quora. Retrieved October 24, 2021, from https://www.quora.com/Whats-the-difference-between-inner-product-dot-product-and-scalar-product

[2] PDF file cannot be cited. It’s from http://ursula.chem.yale.edu/~batista/classes/vvv/v570.pdf

[3] Kzooma K. (2021, September 16). ドット積と内積の違い. note(ノート). Retrieved October 24, 2021, from https://note.com/kzooma/n/n65c4eff99610

[4] The NumPy community. (n.d.). numpy.dot — NumPy v1.21 Manual. NumPy. Retrieved October 24, 2021, from https://numpy.org/doc/stable/reference/generated/numpy.dot.html

[5] Epic Games [Unreal Engine]. (2020, May 27). Building advanced effects in Niagara | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=syVSRDQxrZU

[6] CGHOW. (2021, September 20). Disintegration in UE5 Niagara Tutorial | Download Files [Video]. YouTube. https://www.youtube.com/watch?v=4dYg4bvf4Rc

[7] UnrealCG. (2021, October 14). Time Distortion Effect - UE4 Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=3ejuQVasl7w

[8] Cloward, B. [Ben Cloward]. (2019, December 12). Distortion Shader - UE4 Materials 101 - Episode 4 [Video]. YouTube. https://www.youtube.com/watch?v=gwx2NOZJ5CE

[9] LearnOpenGL - Coordinate Systems. (n.d.). LearnOpenGL. Retrieved October 24, 2021, from https://learnopengl.com/Getting-started/Coordinate-Systems

[10] Cloward, B. (2021, September 2). Detail Normal Mapping - Shader Graph Basics - Episode 13. YouTube. Retrieved October 24, 2021, from https://www.youtube.com/watch?v=SvtTx5jDjuQ&list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl&index=13

[11] Epic Games. (n.d.-f). Vector Operation Expressions. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Materials/ExpressionReference/VectorOps/#derivenormalz

[12] gameDev Outpost. (2020, May 4). UE4 - Materials and UV Rotation [Video]. YouTube. https://www.youtube.com/watch?v=4ITTsrm-MDo

[13] Vries, J. (n.d.). LearnOpenGL - Transformations. LearnOpenGL. Retrieved October 24, 2021, from https://learnopengl.com/Getting-started/Transformations

[14] Microsoft. (2015, July 1). DirectX Factor - 3D Transforms on 2D Bitmaps. Microsoft Docs. Retrieved October 24, 2021, from https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/april/directx-factor-3d-transforms-on-2d-bitmaps

[15] Epic Games. (n.d.-a). Artificial Intelligence. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/

[16] Epic Games. (n.d.-e). Navigation System. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/NavigationSystem/

[17] Epic Games. (n.d.-b). Basic Navigation. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/NavigationSystem/BasicNavigation/

[18] Epic Games. (n.d.-c). Modifying the Navigation Mesh. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/NavigationSystem/ModifyingTheNavigationMesh/

[19] Epic Games. (n.d.-d). Modifying the Navigation Mesh Preparation Guide. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/NavigationSystem/ModifyingTheNavigationMesh/ModifyingtheNavigationSystemPreparationGuide/

[20] Epic Games. (n.d.-d). Modifying the Navigation Mesh. Unreal Engine Documentation. Retrieved October 24, 2021, from https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/ArtificialIntelligence/NavigationSystem/ModifyingTheNavigationMesh/ModifyingtheNavigationSystem/