UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 全体の改善 Part 2

f:id:kazuhironagai77:20210627215343p:plain

<前文>

これは日米共に同じですが世の中にはデータを読める人と読めない人がいます。

データを読めない人には原理主義なタイプと回りの人が悪いタイプが多い気がします。

原理主義なタイプは信念や信仰は科学に勝ると信じているタイプです。日本なら「努力すれば何でも出来る。」とかアメリカなら「聖書に書いてあるから絶対中絶は反対。」と主張する人達です。

周りの人が悪いタイプは「○○さんのせいでこうなった。責任とって」と言う人です。日本だと精々口頭で文句を言うくらいですが、アメリカだと「アジア人(ユダヤ人)のせいで失業した。殺す。」と言って本当に実行する人達も結構います。

なんで唐突にこんな話をし始めたのかと言うと、今回の話はデータを読める人にしか納得してもらえない内容だからです。

最近Minimal Pairのアプリを制作するに当たって音声学を独学しています。

今回のデータを読める人にしか納得してもらえない内容とはɑの音についてです。

cot-caught mergerが起きていている(law をロウではなくラーって発音する)典型的なアメリカ人のɑの音についてなんです。

このɑの音オアーって聞こえる時とアーって聞こえる時があるんです。

<アーに聞こえるɑの音>

law, claw, flaw, saw, paw, pawn, fawn, jaw, draw, dawn, hawk, raw, straw, awesome, audio, Australia, automatic, autumn, August, author, calm, caller, hot, got, God, drama, father, swamp, water, caught, bought.

<オアーに聞こえるɑの音>

Walk, talk, always, honest, off, Ron, bond, rot, pot, lot, job, rob, lock, rock, sock, shop, stop, top, drop, dog, fog, long, song, wrong, strong, toss, loss, Ross, bomb, doll, follow, October, watch, want, knowledge.

<どっちにも聞こえるɑの音>

Taller, all, call, also, on, con, not, cot, pop, boss, coffee, daughter, taught, cough, awning, moss, Pawl.

こんな事を主張していると変なヤツと思われてしまいますが、データからキチンと分析出来る人なら私の言っている事が正しいと分かると思うんです。と言うかそういうレベルの専門家しか分からんと思います。

やっぱりアメリカ人ɑの音の時、オアーっていう時とアーって言う時がありますよ。この音、日本人には全く違う音です。

Minimal pairを作るに当たってこのfatherとOctoberのɑの音を同じ音にしていいのか、とっても悩んでいます。違う音なんじゃないの?分けないといけないんじゃないのと。

どんくらい悩んでいるかと言うと、散歩してた時にカラスが鳴いていたんですがKar、Kerと聞こえてくる位です。もう病気です。

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

<本文>

1.今週の予定

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

  • Niagaraの勉強
  • Cascadeの勉強
  • Landscape4の直し
    • 戦闘後にLevelが上がった場合
    • PickUpItemクラスにItemを追加
    • Monsterがアイテムを落とすようにします
    • Warp Passの作成
    • Landscape4good skyを追加

Landscape4の直しは全部は出来ないでしょうが出来るだけやります。

2.Niagaraの勉強

先週からNiagaraのRenderingに注目して勉強する事に変更しました。NiagaraのRenderingには以下の種類があります。

f:id:kazuhironagai77:20210627215647p:plain

Component Rendererは使用した事がないです。

2.1 Component Rendererについて

公式のDocumentであるNiagara Renderers [1]に以下の説明がありました。

f:id:kazuhironagai77:20210627215715p:plain

当たり前といっちゃ当たり前ですね。

でもこれが出来ると何が得なんでしょうか?

後、このサイトにそれぞれのRenderingのparameterの種類とその機能が説明されていました。

f:id:kazuhironagai77:20210627215731p:plain

これは見やすいです。Ribbon RenderingのParameterについてもちょっと見てみます。

あれ。UV0とUV1についてのparameterがあります。

f:id:kazuhironagai77:20210627215748p:plain

先週のCascadeRibbonの勉強で、UV0とUV1のTextureの貼り方が違うと主張するTutorialがあったけど実際に試したら同じだった事がありました。ひょっとするとこの辺のParameterを弄る必要があるのかもしれませんね。でもまあ。私がそんなに他人の作成したTutorialに気を遣う必要はないですが。

Component Rendererはどんな特殊効果に使うと便利なのかが知りたいです。

Component Example Projectを開いてComponent Rendererを使用しているNiagara Systemを探してみます。

ありました。

f:id:kazuhironagai77:20210627215804p:plain

あったんですけど、Niagara じゃなくてNiagara Advanceの方のしかも4.1という後ろの後ろにありました。

これはComponentRendererExampleと言う名前で作成されたサンプルでした。

それを開いて見ると

f:id:kazuhironagai77:20210627215819p:plain

Skel Mesh ComponentがRenderingされていました。

解説には

f:id:kazuhironagai77:20210627215909p:plain

と書かれていました。

そしてPreviewには

f:id:kazuhironagai77:20210627215923p:plain

実際にNiagara Systemのparticleとして生成されたSkeletal Meshが、Niagara system内でアニメーションを実行しているところがRenderingされています。

分かりました。Component Rendererは分身の術に使用出来るんです。

全然関係ないですが、分身の術の英語名はNARUTOの影響でshadow clone jutsu (影分身の術)がほとんど同じ意味で定着してしまいました。

Black Myth: Wukongのトレーラーで分身の術を使用したシーンがありましたが、ほとんどのアメリカ人が「shadow clone jutsuじゃん。」と叫んでいました。影じゃなくて毛分身の術じゃねえの?という突っ込みをしたアメリカ人は私の知る限り一人もいませんでした。

まあNARUTOの影分身の術自体が影から分身を作成したり分身したら影が無くなったりするシーンはないですからShadow Clone自体が分身を意味するようになっちゃったんでしょうね。

影と言えば、この生成されたSkeletal Meshには影が無いですね。

これだとかなり小さく作成しないと変に見えるかもしれませんね。まだ実験中というのはその辺の問題もあるのかもしれませんね。

Component Rendererに関してはこんだけ理解出来れば今回は十分です。

2.2 UE4 - Niagara Ribbons [2]の勉強

もうちょっとだけRibbon Renderingについて勉強したいと思っていたらちょうどいいTutorialがありました。gameDev Outpostが制作したRibbon RenderingのTutorial、UE4 - Niagara Ribbons [2]です。

これを勉強します。

<stretched Textureについて>

一番最初にTextureとしてNon StretchedとStretchedを用意しています。

f:id:kazuhironagai77:20210627220014p:plain

この違いが分かりません。どの位重要なのかを確認するためにこのTutorialを最後まで見てみました。

そしたらTutorialの最後でNon Stretched Textureを使用した場合は以下の様にカーブを描いて動かした時にTextureがRibbon いっぱいに広げられていないためにArtifactが起きているが、

f:id:kazuhironagai77:20210627220030p:plain

Stretched Textureを使用した場合はArtifactが起きていません。

f:id:kazuhironagai77:20210627220047p:plain

と紹介されていました。

結構重要みたいです。

まだ脱線しますが、この場合のArtifactはイメージ自体の歪みやその歪みによって得られた間違った解釈の事を意味しています。人工物と言う意味ではないです。

例えばですが、滅茶苦茶小っちゃく犯人が移った写真があったとします。その写真を拡大したら犯人の顔に傷がありました。その傷を元に犯人を特定し逮捕したらその人は無罪で、実は真犯人は顔に傷のない人でした。写真を拡大した時に、元があまりに小さかったのでイメージに歪みが生じて顔に傷があるように見えてしまったらしいです。

この場合の顔の傷のような間違った解釈を生む歪みの事をArtifactと呼びます。

上記のTextureの歪みは数字が間違って読める事はないのでArtifactとしては大したことはないのかもしれません。

一応、Stretched Textureについて調べます。

どこにもそれに関する情報はありませんでした。単に数字を精一杯、縦方向に伸ばしたのがStretched Textureと言う意味な気がしてきました。

f:id:kazuhironagai77:20210627220104p:plain

単に数字を精一杯、縦方向に伸ばしたのがStretched Textureであると仮定して続きをやって行きます。

以下に示したTextureを二つ作成してImportしました。

f:id:kazuhironagai77:20210627220121p:plain

f:id:kazuhironagai77:20210627220127p:plain

Materialもほぼ同じに作成しました。

f:id:kazuhironagai77:20210627220143p:plain

f:id:kazuhironagai77:20210627220151p:plain

Ribbon Emitter

EmptyのNiagara Emitterを一個作成しました。

NE_Ribbonと名付けました。

f:id:kazuhironagai77:20210627220212p:plain

gameDev Outpost氏のTutorialは本当に必要最低限のModule以外全部削ぎ落として教えてくれるので勉強する側としてはありがたいです。今回もEmptyのEmitterからRibbonを作成するようです。

Ribbonを作るのでInitialize Particle Moduleは要らないから消します。

f:id:kazuhironagai77:20210627220242p:plain

やっぱり先週勉強したSpawn Beam Moduleを使用したヤツはRibbon Renderingは使用していますが厳密にはRibbon Effectには入らないみたいですね。完全にInitialize Ribbon Moduleを使用する準備に入っています。

更にSprite Renderer Moduleも消します。

f:id:kazuhironagai77:20210627220302p:plain

これはRibbon Rendererを使用するんだから当然です。

消しました。

f:id:kazuhironagai77:20210627220320p:plain

Ribbon Rendererを追加しました。

f:id:kazuhironagai77:20210627220336p:plain

先程作成したMaterialをセットします。

f:id:kazuhironagai77:20210627220352p:plain

次にParticle Spawn GroupにInitialize Ribbon Moduleを追加します。

f:id:kazuhironagai77:20210627220406p:plain

はい。予想通りでした。

Tutorialではここでまだ何も生成出来ていない事に触れています。

f:id:kazuhironagai77:20210627220423p:plain

この辺がgameDev Outpost氏が非凡な所です。

先週、私も何時Ribbonが表示されるのか心配でPreviewの画面をModuleを一個追加するたびに確認していました。そういう視聴者の不安を的確に予測してコメントしています。凄いです。

そして「まだ何もSpawnしていないからだよ。」と優しく教えています。

はい。そしてSpawn Rate ModuleをEmitter State Groupに追加します。

f:id:kazuhironagai77:20210627220458p:plain

何でここでSpawn Burst Instantaneous ModuleじゃなくてSpawn Rate Moduleを追加するのかの説明が欲しかったです。

私が補足するとRibbon は移動するParticleのケツから生成されるので、移動するParticleに沿ってRibbonを生成するためには時間毎にRibbonを生成する必要があります。のでSpawn Rate Moduleを追加する必要があります。

更に、Spawn Rate ModuleのSpawn Rateを10にセットしました。

f:id:kazuhironagai77:20210627220519p:plain

これは1秒間に10回Particleを生成すると言う意味です。

でもPreviewを見ると何も見えません。

f:id:kazuhironagai77:20210627220537p:plain

先週の、私の感覚だと、この時点で視聴者はかなり不安なはずです。

兎に角、何も表示されないのは一番不安になります。先週の私もPreviewに何も表示されない時はかなり不安でした。

「先生何も表示されません。」と画面に向かって発言してる視聴者もいるかもしれないレベルで不安なはずです。

所がここでもgameDev Outpost氏は完全にその辺の視聴者の心理を読んで素早くその理由を説明しています。

gameDev Outpost氏の説明によると、

f:id:kazuhironagai77:20210627220554p:plain

f:id:kazuhironagai77:20210627220601p:plain

Ribbonって奴は結局動きの一種なんでPreviewに表示させるためにはある種の動きを追加する必要があるんだ。」と簡潔に答えています。

そしてこれはDebug目的だけどRibbonに動きを追加するためにAdd Velocity ModuleをParticle Update Groupに追加します。

f:id:kazuhironagai77:20210627220620p:plain

更にAdd Velocity ModuleのVelocityを以下の様な設定にします。

f:id:kazuhironagai77:20210627220637p:plain

ギシギシしていますがPreviewRibbonが表示されました。

f:id:kazuhironagai77:20210627220845g:plain

おお。ついにRibbonが表示されました。

コメント欄でもAdd Velocity Moduleをdebugとして使用する方法を紹介した事を称賛されています。

f:id:kazuhironagai77:20210627220915p:plain

この説明は流石です。

次にInitialize Ribbon ModuleのRibbon WidthとLife timeについての解説をしています。

f:id:kazuhironagai77:20210627220933p:plain

Ribbon WidthはRibbon の高さを表します。

これは私も先週の勉強で知っています。

Life timeですが、

f:id:kazuhironagai77:20210627220951p:plain

f:id:kazuhironagai77:20210627220957p:plain

値を低くすると

f:id:kazuhironagai77:20210627221013p:plain

f:id:kazuhironagai77:20210627221021p:plain

Ribbon の長さが短くなります。

今度はSpawn Rateについてです。

f:id:kazuhironagai77:20210627221035p:plain

このSpawn Rateの値が大きくなるほどRibbonの数字が滑らかに表示されます。

良く考えるとこの部分がまだ良く分かっていないんです。先にTutorialを終わらせてから考察します。

Debugに使用したAdd Velocity Moduleを消してSaveします。

f:id:kazuhironagai77:20210627221132p:plain

<Level上のRibbon

NE_RibbonからNiagara Systemを作成します。

f:id:kazuhironagai77:20210627221158p:plain

Niagara Systemの名前をNSに変えるのを忘れていました。直します。

f:id:kazuhironagai77:20210627221219p:plain

Level上に配置して動かします。

f:id:kazuhironagai77:20210627221504g:plain

はい。

ここでTutorialでは数字とRibbonの上下の隙間が大きいからArtifactが生まれています。StretchしたTextureを代わりに使用しましょう。とあります。

その結果、

f:id:kazuhironagai77:20210627221602p:plain

Ribbonと数字の上下の隙間が無くなりました。

私が以下の解釈で

f:id:kazuhironagai77:20210627221617p:plain

作成したTextureを使用して試してみると

f:id:kazuhironagai77:20210627221634p:plain

数字とRibbonの上下の隙間が無くなっています。Stretched Textureの解釈は合っているみたいですね。

2.3 Ribbon Renderingの謎を解明する

f:id:kazuhironagai77:20210627221657p:plain

やっとRibbon Renderingが何をしているのか分かりました。

その説明をここに書いておきます。

まずRibbonが一個だけ生成される場合です。

これはSpawn RateとLife timeの関係によって決定されます。両方の数字が小さい必要があります。

この場合は前節のTutorialの説明の通りのRenderingがされます。

Life timeの間に移動した分がRibbonの幅、そしてLife timeの間だけRibbonが表示されます。以下の例のようになります。

f:id:kazuhironagai77:20210627221714p:plain

次に前に作成されたRibbonが残っている状態で新しいRibbon が作成された以下の図のような場合です。

f:id:kazuhironagai77:20210627221731p:plain

この場合は現在存在するすべてのリボンを一つに統一してその統一したリボン上にTextureを貼り付けます。

以下に示した例のようになります。

f:id:kazuhironagai77:20210627221752p:plain

だからSpawn Rateの数を多くしてRibbon RenderingのNiagara Systemを動かすと最初のLife timeが終了するまでRibbonが長くなりますが、Lifetime以上になると今度は長さは一定になってNiagara Systemの動きについて移動するようになります。

f:id:kazuhironagai77:20210627221938g:plain

分かり易くポンチ絵で示します。

最初のRibbonです。

f:id:kazuhironagai77:20210627222018p:plain

Life TimeとSpawn Rateの関係から前のRibbonが消滅する前に次のRibbonが作成されます。

f:id:kazuhironagai77:20210627222033p:plain

その結果、Textureはその二つのRibbonを合成したRibbon上にRenderingされます。つまりRibbonが長くなります。

どんどんRibbonは長くなります。

f:id:kazuhironagai77:20210627222049p:plain

しかしある程度長くなると、最初のRibbonはLife timeを終えて消滅します。

以下の図だと黄色で示した最初のRibbonは消滅します。しかし濃い青で示した新しいRibbonも生成されるため全体の長さは変わらなくなります。

f:id:kazuhironagai77:20210627222106p:plain

これを理解すると最初の疑問である

f:id:kazuhironagai77:20210627222128p:plain

の理由も分かります。

Spawn Rateの数が大きくなればなるほどRibbon上にTextureを表示するRenderingを一秒間に行う回数も増加します。つまりFPSが増える訳です。FPSが増えればTextureが滑らかに動くのは当然です。

Ribbon Renderingについて完全に理解しましたね。

2.4 Ribbon RenderingのTextureの貼り方について

先週のCascadeのTutorialでUV0を使用すると以下の様なTextureの貼り方になるが、

f:id:kazuhironagai77:20210627222151p:plain

UV1を使用すると以下の様なTextureになると説明されていました。

f:id:kazuhironagai77:20210627222220p:plain

しかし実際にはこの通りにはならず、UV1であるTexCoord[1]を使用してもTextureは

f:id:kazuhironagai77:20210627222237p:plain

と表示されただけでした。

それで先週はUV1のようなTextureの貼り方は出来ないので、それは嘘なんじゃないのと結論づけました。

しかし今週Niagara ですが、以下のようなRibbonが構成されている場合、その全てのRibbonを一枚のRibbonとしてTextureを貼り付けている事が判明しました。

f:id:kazuhironagai77:20210627222256p:plain

と言う事は、それぞれのRibbonにTextureを貼り付ける方法も必ずある気がしてきました。

Niagaraの勉強に関しては今週はここまでとします。かなりRibbon Renderingについては基礎というか根本が分かって来ました。

3.Cascadeの勉強

今週勉強したい事は一個は決まっています。

先週、一寸だけ勉強した公式のTutorialであるIntro to Cascade: Creating a Ribbon Emitter | 08 | v4.2 Tutorial Series | Unreal Engine[3]をキチンと勉強する事です。

ただしこれを勉強する前にBeamのTutorialを先にやります。NiagaraではBeamとRibbonは共にRibbon Renderingを使用して作成していますが、CascadeではどうやってBeamを作成しているのかの確認をしておきたいからです。

Intro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [4]を最初に勉強します。

そしてもし時間が余ったらRibbon RenderingのUV0とUV1について調査します。

3.1 Intro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [4]の勉強

Intro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [4]を勉強します。

<Beamに使用するMaterialの作成>

Beamに使用するMaterialを作成します。

Mat_Beamと名付けました。

f:id:kazuhironagai77:20210627222343p:plain

Parameterの設定を以下の様に変更します。

f:id:kazuhironagai77:20210627222400p:plain

Blend ModeをTranslucentにセットするのは他のTutorialでも良くやっていますね。これって使用するTextureの透明な部分をMaterialでも透明にする機能でしょう。Shading ModelのUnlitは良く知らない機能です。

以下に示したScreenshotの赤丸内のAssetの様にある種のAssetが全く光の影響を受けないのが不思議だったんですが、それらのAssetが使用するMaterialってここがUnlitにセットされているんでしょうか?

f:id:kazuhironagai77:20210627222417p:plain

ちょっと脱線しましたが、上記のオレンジ色の液体の入った瓶のMaterialを調べて見ました。

f:id:kazuhironagai77:20210627222436p:plain

普通にDefault Litでした。

f:id:kazuhironagai77:20210627222452p:plain

本当に脱線しまくっていますが、もう少しだけ調べました。

光の影響を全く受けないAssetのMaterialを何個か調べました。全ての光の影響を全く受けないAssetのMaterialはNormalに値をパスしていませんでした。

f:id:kazuhironagai77:20210627222508p:plain

それぞれのverticesがNormalの値も持っているじゃなかったでしたっけ。それ以外に特別にNormal Vectorの情報をパスしたい時にNormalは使用されると思っていました。この結果だけ見るとNormalに値をパスしない場合はNormal Vectorがないとみなされるようですね。その結果、光の影響が計算出来なくなるみたいですね。でもこれだけじゃ何の結論も出せませんね。後でMaterialの勉強をする時にもっと調べる事にします。

Mat_Beamの作成に戻ります。

Beamのmaterialを作成するそうですがTextureは使用しないでTexCoord[0]から作成するそうです。

f:id:kazuhironagai77:20210627222526p:plain

まずTexCoord[0]の縦軸つまりV軸が緑で表されています。上から下に向かって0から1となっています。この緑の部分だけMaskで抽出したのでMask(G)のような下に行くにしたがって明るくなるイメージになります。

ただ、なんで赤く色づけされているのか分かりませんね。Mask(G)の場合、一点が持っている情報は一個だけでTexture Sampleの様にRGBAの4つもしくはRGBの3つの情報を持っている訳ではないはずです。それを敢えて赤く表すとRGBAの4つもしくはRGBの3つの情報を持っているかのような錯覚を感じてしまいます。

 Tutorialの方はグレイスケールになっています。

f:id:kazuhironagai77:20210627222544p:plain

昔のVersionはグレイスケールだったのを赤に敢えて変えた。と言う事は何かしらの理由があると思います。がその理由は分かりません。

というかTexCoord[0]ノード自体もあんまり理解しないで使用していました。

例えばUTilingとVTilingが1の時は

f:id:kazuhironagai77:20210627222600p:plain

以下のような配色になっていますが、

f:id:kazuhironagai77:20210627222617p:plain

UTilingの値を10に変更すると

f:id:kazuhironagai77:20210627222634p:plain

以下の配色になります。

f:id:kazuhironagai77:20210627222651p:plain

UTilingやVTilingの値を変える事でTextureのSizeを拡大縮小する事が出来るのは承知していますが、実際どんな値がTexCoord[0]からTextureSampleに伝えられているのかまでは考えた事なかったです。上記の配色の変化を見ればある程度、実際にどんな値がTexCoord[0]から発せられているのかも分かると思います。今度Materialの勉強をする時はその辺りを含めて勉強します。

ここでTexCoord[0]ノードを使用しているのは単に以下に示したような配色のTextureがほしいから使用しているだけだと思います。

f:id:kazuhironagai77:20210627222732p:plain

別にTextureで同じモノがあればそれを使用しても全く同じ結果を得られるはずです。

次に行きます。

今度はSineノードを繋げました。

f:id:kazuhironagai77:20210627222826p:plain

これが良く分からない。何で下半分が0になるの。

Mask(G)の値は場所によっては違うとしても0 から1の範囲の値のどれかを示しているはずです。

Mask(G)の値をxとしてsin xを計算するとxの値がRadianとしても以下の様にしかならないです。

f:id:kazuhironagai77:20210627222904p:plain

つまり最大値の1でもSin(1)は0.841で0になる事はありません。

公式のDocumentのMath Expressions [5]のSineの所に完璧な説明がありました。

f:id:kazuhironagai77:20210627222953p:plain

f:id:kazuhironagai77:20210627223001p:plain

はい。凄く分かりました。

Sinに使用されるXの値の0から1はそのままRadianとして使用されるのではなかったです。0は0度、1は360度に対応してそれぞれの割合に応じて値が変換されます。

以下の図のように値が変換される訳です。

f:id:kazuhironagai77:20210627223150p:plain

これなら下半分が0になるのも納得です。-の値は存在しないですから。

じゃあCosineなら上半分が0になるんでしょうか?

試してみます。

f:id:kazuhironagai77:20210627223211p:plain

あれ?

くそ。Cosineのグラフの形すっかり忘れていました。

f:id:kazuhironagai77:20210627223227p:plain

Sineから半分ずれるんじゃなくて四分の一ずれるんでした。

兎に角Sineノードの意味は分かりました。

次にMask(G)ノードとSineノードの間にMultiplyノードを追加しました。MultiplyノードのBの値は0.5です。

f:id:kazuhironagai77:20210627223313p:plain

はい。Sin(x)のxの値が0から1だったのが0から0.5に変更された訳です。その結果、以下のような計算結果になります。

f:id:kazuhironagai77:20210627223329p:plain

実際のSineノードのイメージも半分黒だった部分が無くなりました。

f:id:kazuhironagai77:20210627223348p:plain

はい。やっとこのイメージを導出するための数学的な計算方法の意味が理解出来ました。

今度はそれを3乗します。Tutorialによるとこれはメリハリをもっとつけるために行ったと言う事です。

f:id:kazuhironagai77:20210627223404p:plain

何で3乗する事がメリハリをつける事になるのか良く分からないので自分で計算してみました。

f:id:kazuhironagai77:20210627223421p:plain

成程。Sin(x)の値が1以下の数字のため累乗すると値が小さくなるんですね。よってもっと暗くなると。

この計算、このTutorialだけではなくて沢山のMaterialで見ます。しかし別に絶対この方法で作成する必要もないですよね。特に今回はMaterialの勉強じゃなくてCascadeの勉強ですから。

例えばTextureでこんな感じの絵を描いたの読み込んでも全く問題ないはずです。

要はみんな分かってないんですよ。何でこういう計算しなくてはいけないのかと言う事を。目的があってそれを達成するための一手段として今回の計算方法もある訳です。

今回の目的は以下に示したイメージに似たモノを作成する事です。

f:id:kazuhironagai77:20210627223439p:plain

別にこの計算方法じゃなくても出来ます。Textureを読み込むのが重いとしてもこの計算方法を使用しなくても幾らでも同様のイメージを作成する事は可能です。

これかなり陳腐な言い方になってしまうんですが、UE4のTutorialって手段が目的化してしまっているんですよ。

だから初心者がUE4のTutorialを見ても全く意味が分からなくなるんですよ。

<P_Beamの作成>

Particle Systemを使用してCascade のBeamを作成します。

こっからはTutorialの説明通りにやって行きます。

まずType DataからNew Beam Dataを選択します。

f:id:kazuhironagai77:20210627223508p:plain

CascadeではBeam とRibbonは全く別のタイプとして分類されているんですね。

Required ModuleのMaterialにMat_Beamをセットします。

f:id:kazuhironagai77:20210627223524p:plain

BeamにはSourceとTargetを指定する必要があります。

その為にSource ModuleとTarget Moduleを追加します。

f:id:kazuhironagai77:20210627223541p:plain

Source ModuleとTarget Moduleそれぞれに値を指定します。

f:id:kazuhironagai77:20210627223600p:plain

f:id:kazuhironagai77:20210627223607p:plain

すると少しだけPreviewにBeamらしきものが表示されます。

f:id:kazuhironagai77:20210627223630p:plain

Beam Data ModuleのBeamのSpeedを0にセットします。

f:id:kazuhironagai77:20210627223646p:plain

するとPreviewのImageが以下のようになります。

f:id:kazuhironagai77:20210627223710p:plain

何でよ?

またこれです。

何の説明もない。

f:id:kazuhironagai77:20210627223727p:plain

はい。Cursor乗せるだけで説明が出て来ました。

Beam Data ModuleのSpeedはBeamがSourceからTargetに移動するのに必要な時間を指定するParameterです。ここに0をセットするとBeamはSourceからTargetに一瞬で移動するようになります。

つまりBeamの形状は以下の様になる訳です。

f:id:kazuhironagai77:20210627223753p:plain

ここだって上記のイメージのようなSourceとTargetの地点をBeamで結んだ形を作りたいです。その為に今回はBeam Data ModuleのSpeedを0にセットする方法を採用します。Beam Data ModuleのSpeedは…。と説明すれば一瞬で済みます。

Moduleの値を弄ってBeamの形状を以下のように変化させました。

f:id:kazuhironagai77:20210627223810p:plain

この辺のやり方は既に知っているModuleの値を弄っているだけなのでスキップします。

今度はこのBeamを曲げて曲線を描いてSourceからTargetに向かうようにします。

以下の様にです。

f:id:kazuhironagai77:20210627223825p:plain

SourceとTargetに傾きを付ける事でこれを達成します。

Source ModuleのSource Tangent MethodをUser Setにします。

そしてSource TargetのConstantで傾きを指定します。

f:id:kazuhironagai77:20210627223840p:plain

Targetも同様にします。

その結果、

f:id:kazuhironagai77:20210627223857p:plain

何も変わりません。

それはInterpolationとSheetの数を増やさないと指定した傾きにBeamが曲がれないからです。それらはBeam Data Module内で指定出来ます。

f:id:kazuhironagai77:20210627223914p:plain

はい。以下の様にBeamが曲線を描くようになりました。

f:id:kazuhironagai77:20210627223931p:plain

ちょっと時間的にこれ以上Cascadeの勉強をするわけにはいかないので、ここで一端中止します。残りは来週やります。

InterpolationとSheetが具体的に何をしているのかについても来週調べます。

4.Monster Zoneのバグの直し

先週やり残したMonster Zoneの二つ目のバグを直します。

f:id:kazuhironagai77:20210627223956p:plain

あ、このバグは直っています。

直っているはずです。確認します。

4.1 バグの確認

以下の図に示した様に平らな石をTerritoryのすぐ外ですがBlockの内側に敷きました。

f:id:kazuhironagai77:20210627224025p:plain

この石板の上でMonsterと戦闘します。

戦闘から戻って来ました。

f:id:kazuhironagai77:20210627224055p:plain

Monsterは生成されています。

はい。このバグは直っています。

4.2 先週、私が言いたかった事

私が、先週言いたかったバグはこの部分で戦闘になるとモンスターを倒しても倒したモンスターが消滅しないバグについてでした。

つまりRemove Defeated Monster from Landscape 4関数は

f:id:kazuhironagai77:20210627224121p:plain

RPGGameInstanceBPの変数、Monster Territory Numberを使用して倒したMonster を消去します。

f:id:kazuhironagai77:20210627224135p:plain

このMonster Territory NumberはTerritoryに侵入して初めて値が変更します。

ので、上記の条件だとMonster Territory Numberは0のままです。ので倒したモンスターは消滅しません。

4.3 このバグについて

消滅しないMonsterもそのTerritoryに侵入して倒せば消滅します。

そのTerritoryに侵入しないでMonsterを少しずつ倒すのも戦術としてはありかもしれませんが、そのTerritory内に存在する宝箱が取り易くなってしまったりするかもしれません。

のでこのバグは今は直さない事にします。

5.Level upした時のコメントの追加

はい。それではLevel upした時のコメントを直していきます。

先週、どうやってセリフを管理しているのかとか「読みましたボタン」を表示したのかなどを復習しました。

そしてどのように直すのかのアイデアもそれから一週間の間に考えましたのでそれに基づいて直していきます。

5.1 Level upした時に「読みましたボタン」を表示させる

取りあえずLevelが上がった時に「読みましたボタン」を表示させるコードを追加しました。

f:id:kazuhironagai77:20210627224210p:plain

何故か逆にボタンが表示されなくなりました。

f:id:kazuhironagai77:20210627224246p:plain

色々調べましたが原因が分かりません。

色々やっている内にDelayを入れると直る事が分かりました。

f:id:kazuhironagai77:20210627224302p:plain

この事から想像すると「読みましたボタン」をクリックした時に実行する以下のコードの内、Set Visibilityノードの実行が、

f:id:kazuhironagai77:20210627224319p:plain

次の「読みましたボタン」を表示させるノードの実行より後に呼ばれているからのようです。

f:id:kazuhironagai77:20210627224334p:plain

なので「読みましたボタン」をクリックした時に実行する以下のコードの順番を変えてみました。Event DespatcherであるCall Confirm Button is Clickedは「読みましたボタン」を消した後に呼ぶ事にしました。

f:id:kazuhironagai77:20210627224350p:plain

今度は、普通に表示されました。

f:id:kazuhironagai77:20210627224405p:plain

Delayノードで時間を止めなくても「読みましたボタン」は表示されます。

f:id:kazuhironagai77:20210627224420p:plain

原因を見れば記録するに値しない小さなミスかもしれませんが、この原因を発見するために30分以上奮闘しました。結構疲れました。

後学のために敢えて記録しておきます。

5.2 Level upした時に「読みましたボタン」を押したらLevel upの詳細を表示する。

どうやってセリフを管理するか色々検討しましたが、結局以下に示した様に関数に値をパスしてその関数内で適切なセリフが選択されるようにしました。

f:id:kazuhironagai77:20210627224442p:plain

Get Dialogue from Level Up Dialogue関数の中身です。

f:id:kazuhironagai77:20210627224511p:plain

セリフを追加するだけなんですが、こんな複雑なコードになってしまいました。

これ以上整理するためには更なるHelper関数を作成する必要があります。今回はこれでテストしてみます。

以下の値でテストします。

f:id:kazuhironagai77:20210627224535p:plain

以下のコメントが表示されました。

f:id:kazuhironagai77:20210627224550p:plain

はい。出来ています。

魔法がない場合です。

f:id:kazuhironagai77:20210627224605p:plain

魔法のコメントだけ消えました。

f:id:kazuhironagai77:20210627224636p:plain

今度はLevel upした時の値をこの関数にパスするためのコードを作成します。

結局、それも関数で作成しました。

f:id:kazuhironagai77:20210627224651p:plain

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

f:id:kazuhironagai77:20210627224707p:plain

テストします。

f:id:kazuhironagai77:20210627224722p:plain

出来ていますが、魔法名が日本語化していません。

そこを直します。

直しました。

f:id:kazuhironagai77:20210627224749p:plain

以下の部分を変更しました。

f:id:kazuhironagai77:20210627224804p:plain

出来ました。

今度はテストします。

5.3 テスト

レベル10まで上げてみます。そしてその後の様子もチェックします。

f:id:kazuhironagai77:20210627224826p:plain

魔法も日本語名で表示されています。問題ありません。

Level 3になった時です。

f:id:kazuhironagai77:20210627224842p:plain

修得した魔法の名前は日本名で表示されています。

Level 4になった時です。

Level 4 以降は魔法は覚えません。

f:id:kazuhironagai77:20210627224858p:plain

魔法を修得しない時は「魔法、○○を覚えました。」が表示されないように実装しました。

実際に表示されていません。

f:id:kazuhironagai77:20210627224917p:plain

Levelを最大まで上げます。

f:id:kazuhironagai77:20210627224933p:plain

これ以上の戦闘をした場合、Level云々のコメント自体が表示されなくなりました。これも想定通りです。

出来てますね。

6.PickUpItemクラスにItemを追加

先週、Level upした際のセリフは作成しませんでしたが、コメント欄に表示するセリフの仕組みや「読みましたボタン」の仕組みを前もって調べておきました。その結果、今週実際にLevel upのコメントを作成する時非常に楽になりました。

これは個人的には結構大変な発見でした。

恐らくですが、一週間の間に色々な検討を頭の中で行っていてその結果、実際にコードを書く時にはある程度の構想が完成していたからだと思います。

これは使えます。今週も調査だけやっておきます。

6.1 PickUpItemウィジェットについて

PickUpItem WidgetがどうやってWeaponを拾うのかの確認をします。

f:id:kazuhironagai77:20210627225007p:plain

Widgetのデザインは以下の様になっています。

f:id:kazuhironagai77:20210627225022p:plain

落ちているアイテムの特徴を示す右上の欄が武器、防具専用になっています。これの道具バージョンを作成する必要があります。

拾うボタンをクリックした場合どうなるのかも調べます。

f:id:kazuhironagai77:20210627225037p:plain

まず拾うものがItemか武器/防具かを聞いています。Itemだった場合のコードは全く書かれていません。この部分にItemを拾った時に実行する内容を実装する事になりそうです。

武器を拾った場合は何をしているのかを確認します。

f:id:kazuhironagai77:20210627225053p:plain

Dropped Item BaseクラスからName変数を呼び出しています。

f:id:kazuhironagai77:20210627225108p:plain

思い出してきました。このDropped Item BaseクラスのTerritoryに侵入した状態で、Eを押すとPickUpItem Widgetが開く仕組みになっているんでした。

となるとDropped Item Baseクラスも調べる必要がありますね。

取りあえずDropped Item BaseクラスのName変数だけ調べておきます。

Dropped Item BaseクラスのName変数は以下に示したようにInstance EditableでそれぞれのInstanceで別の名前を付ける事が出来ます。

f:id:kazuhironagai77:20210627225124p:plain

f:id:kazuhironagai77:20210627225131p:plain

しかしこのName変数の値で表示されるItem(Weapon)が変化する重要な変数でした。

f:id:kazuhironagai77:20210627225146p:plain

以下のコードでどのStatic Meshを表示するのかを決定しています。

f:id:kazuhironagai77:20210627225201p:plain

今は直しませんがこの方法だと間違った名前の武器や防具を入れた時に対応出来ません。Enumで作り直すべきです。これは全部完成した後で直す事にします。

ちなみにここでもItemは選択出来ません。

これを作成した時はItemを示すAssetを一個も持っていなかったので作成出来なかったんでした。

今なら以下のようなAssetがあるんでこれらを使用します。

f:id:kazuhironagai77:20210627225217p:plain

PickUpItem Widgetの話も戻ります。

f:id:kazuhironagai77:20210627225234p:plain

これって一体何が目的でやっているのか不明です。

別に武器や防具を拾うためにそれらの個別の性能を知る必要はないです。実際、何のデータも使用していません。

思い出しました。武器や防具の種類はこれから増えるかもしれないのでEnumを作成しない代わりにここで本当に存在する武器かどうかを確認したんでした。

次に拾った武器の名前をRPGGameInstanceBPのArrayであるWeaponsに追加しています。

f:id:kazuhironagai77:20210627225251p:plain

これでData TableのWeaponsに記録されていない武器や防具がRPGGameInstanceBPの配列であるWeaponsに追加されるのを防いでいるわけですね。

本来ならば、Enumで管理するんでしょうが、まだ武器や防具が全種類完成している訳ではないのでこういう方法を採用した訳ですね。

次の関数は何をしているんでしょうか?

全く覚えていません。

f:id:kazuhironagai77:20210627225310p:plain

中身を見てみます。

f:id:kazuhironagai77:20210627225325p:plain

はい。分かりました。どんなItemをmap上に配置するのか、RPGGameInstanceBPのItem Spawn Dataで管理していたんでした。そのDataに二度とこのItemは生成しないようにセットするための関数でした。

このやり方、MonsterをMap上に動的に生成するために考え出したと思ったんですが、実際はItemを動的に生成するために考えた方法だったんですね。すっかり忘れていました。

この後は、Playerが操作しているキャラが今侵入しているDropped Item BaseのInstanceを破壊したり、Game Pausedを解除したりしています。

f:id:kazuhironagai77:20210627225341p:plain

このやり方が正しいかどうかは不明ですが、Itemを拾うのは関係ないのでこの辺はそのままにしておきます。

今週はこの辺で終わりにして残りは来週行います。

7.来週以降

以下の改善点は来週以降やります。

  • Monsterがアイテムを落とすようにします
  • Warp Passの作成
  • Landscape4にgood skyを追加

8.まとめと感想

今週は以下の事を行いました。

  • Niagaraの勉強。
    • Component Rendererについて
    • UE4 - Niagara Ribbons [2]の勉強
    • Ribbon Renderingの原理についての考察
  • Cascadeの勉強。
    • Beamについて
  • Level upした時に具体的に何がレベルアップしたのかを示すセリフの追加。
  • Itemを拾う機能を追加するために何が必要なのかの調査

Particle Systemの勉強が楽しすぎてあんまりRPGの作成が進みません。でももう少し頑張ったら芸術と技術がシナジーを発揮する領域に入り込めそうな気がしています。CascadeのBeamはRibbon Renderingを使用していなくてRibbon とは全く別に分類されているのは驚きでした。Level upした時のセリフを追加して思ったのは、UIの作成は奥が深いです。ただあまりprogramming の技術的な能力は要求されない気がします。代わりに、報告、連絡、相談のようなManagementに必要な技術をどうやってUI上に落とし込むのかが重要になってくる気がします。

以上です。

9.参照(Reference

[1] Epic Games. (n.d. -b). Niagara Renderers. Unreal Engine Documentation. Retrieved June 27, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/RenderModules/

[2] gameDev Outpost. (2020, November 12). UE4 - Niagara Ribbons [Video]. YouTube. https://www.youtube.com/watch?v=5laJ0OMUix4

[3] Epic Games [Unreal Engine]. (2014b, July 8). Intro to Cascade: Creating a Ribbon Emitter | 08 | v4.2 Tutorial Series | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=jBUF6at1s1o&list=PLZlv_N0_O1gYDLyB3LVfjYIcbBe8NqR8t&index=8

[4] Epic Games [Unreal Engine]. (2014a, July 8). Intro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=ywd3lFOuMV8&list=PLZlv_N0_O1gYDLyB3LVfjYIcbBe8NqR8t&index=7

[5] Epic Games. (n.d.-a). Math Expressions. Unreal Engine Documentation. Retrieved June 27, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Materials/ExpressionReference/Math/#sine