UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 最初のmapの作成 Part2

f:id:kazuhironagai77:20210919220518p:plain

<前文>

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

しかし今週だけはお休みしてEpic とAppleの訴訟の判決に対して調査した結果をまとめておきたいと思います。

この訴訟は、日本のSmart Phoneアプリの開発の方向性を決定する大きな事件であるはずなのに、日本ではあまり大きなニュースになっていません。

その結果、この裁判の結果がどうなっているのか日本語のニュースを追っているだけでは良く分からないです。

それで私が勝手に調べて見ました。

ただし最初に断っておきますが、私は毎週UE4の勉強をしていて、もう4年近く経ちます。その間Epic Games社にはこんな凄いGame Engineを無料で提供してくれて感謝しかありません。のでかなり私はEpic Game社を応援する側になります。なるだけ公平かつ客観的な意見を述べようと心がけますが、少しはバイアスが入ってしまうかもしれません。

まずCNBCのニュース [1]です。

f:id:kazuhironagai77:20210919220539p:plain

とまとめられています。

まず2番目の文章ですが、これをそのまま解釈すると今までIOSのアプリで課金する場合はAppleの提供した課金システムを絶対に使用する必要がありましたが、これからはそれ以外の方法で課金しても良いと解釈できます。

これはCNBCに限らず他のニュースサイトでもほぼ同じ解説をしていました。

ところがですね。

Richard Hoeg氏がEpic v Apple: Judgment Day - Who Won? Who Lost? ...and Why? (VL538) [2]のThe Court on Commissions(4分31秒位)で述べていますが、IOSのAppはAppleの提供した課金システムを使用する必要はありませんが、AppleはappをStore に載せる時の契約でAppleの提供した課金システムを使用してない課金に対しても今まで通りの30%(15%)の使用料を請求する権利があるそうです。

Richard Hoeg氏の解釈が絶対、正しいとは限りません。

事実、彼はUnityで検索するとUnreal Engineが一番最初に検索結果が現れると言ってTim Sweeney氏のビジネス手法が偽善的であると批判しています(Epic's CEO Just Called Me Out: A Response (VL289) [10]) 。しかし彼がその時に検索に使用した単語はUnity ではなくUnity Engine でした。

そりゃUnity Engineで検索したらGoogleのAIだってUnreal Engineの打ち間違いと思うでしょう。

このような事から推測すると、Richard Hoeg氏の主張は事実に基づかないで(もしくは極めて限定的な状態のみで通用する事実に基づいて)言っている可能性はかなりあります。

しかしRichard Hoeg氏はIT関連の会社法?専門の弁護士だそうですので、彼の解釈はTake Noteはしておくべきです。

つまり、今の時点では30%もしくは15%の使用料については変化なし。と考えておいた方が無難です。

(ここでBlu-Ray Discなどのおまけでゲーム内通貨が貰える場合についても調べたんですが、それについては分かりませんでした。)

更に、3番目の文章で語られているApple独占禁止法に違反していないと言う判決に対しても、Yong Yea氏がBoth Epic & Apple Lose Big After Court Rules On Their Legal Battle [3]の11分12秒位から解説していますが、判決文を読むと、携帯ゲーム機に限って言えば「Apple独占禁止法に違反していない」と言う意味なんだそうです。つまりこれからの裁判でやっぱりApple独占禁止法に違反しているよね。と言う判決が出る可能性は十分にあるわけです。

はい。

ここまでの調査で理解した事をまとめますと、まだ何も結論は出ていない。となりました。

うん。調べたけどあんまり意味なかったですね。

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

<本文>

1.今週の予定

今週は以下の事をやります。

  • Particle Systemの勉強
  • RPGの作成
    • Map1の作成の続き
    • Loading Screenの勉強の続き
    • Good Skyの復習

2.Niagara : Building advanced effects in Niagara | Unreal Engine [4]の総括

先週やっとNiagara : Building advanced effects in Niagara | Unreal Engine [4]のTutorialが終わりました。

今週はNiagara : Building advanced effects in Niagara | Unreal Engine [4]についての総括、特に以下の点についての検討

  • 目的は?
  • 出来なかった事は?
  • 学んだ事は?
  • 目的は達成出来たのか?
  • Tutorial通りに作れたのか?
  • このTutorialの改善点について

を行います。

その後でNiagara : Building advanced effects in Niagara | Unreal Engine [4]とCGHOW氏のTutorialを比較してこれからNiagaraの勉強をするのにCGHOW氏のTutorialを使用すべきかどうかを検討します。

2.1 Niagara : Building advanced effects in Niagara | Unreal Engine [4]の総括

<目的は?>

先週も書きましたが、Tutorialのサンプルそっくりに再現する事が目的です。

以下に先週の結果を示しますが、かなりそっくりに再現出来たと思います。

f:id:kazuhironagai77:20210919220711p:plain

<出来なかった事は?>

唯一出来なかった部分がMaterialです。

f:id:kazuhironagai77:20210919220728p:plain

これはどう直せば良いのか全く分からなかったです。

<学んだ事は?>

先週、まとめた学んだ事に追加して以下の事を学びました。

  • Force Moduleが速度を追加しているだけだと言う事。
  • Edit Valueについて

f:id:kazuhironagai77:20210919220757p:plain

  • Light RendererUse Inverse Squared Falloffについて
  • Initialize Mesh Reproduction Sprite ModuleUpdate Mesh Reproduction Sprite Moduleについて
  • SpriteMeshNormal Vectorに垂直に面するようにする設定方法(Sprite Renderer ModuleAlignmentFacing Modeの値を以下に示した値に変更)

f:id:kazuhironagai77:20210919220827p:plain

  • Spriteを丸くする

f:id:kazuhironagai77:20210919220858p:plain

  • Objectに触った部分のキャラのMaterialが消える方法
  • Distance To Nearest Surfaceノードの機能

f:id:kazuhironagai77:20210919220927p:plain

  • 生成したParticleをバラバラに飛ばす方法
  • 以下の名称がNam Spaceだった件

f:id:kazuhironagai77:20210919220955p:plain

  • Scratch Pat Moduleの作成方法(2回目)

以上です。

これらの中で、先週学んだけど実際はよくわかっていない箇所が沢山あります。それらは次で復習します。

2.2 先週、勉強した事で分からなかった部分の勉強

Link InputTransient

TransientがどのName Spaceを指しているのか分かりません。

f:id:kazuhironagai77:20210919221042p:plain

調べます。

公式のDocumentであるNiagara Script Editor Reference [5] には

f:id:kazuhironagai77:20210919221057p:plain

と書かれていました。と言う事はそのModule内にしか存在しないLocal Variableなんでしょうか?

CursorをTransientに重ねたら以下の説明が出て来ました。

f:id:kazuhironagai77:20210919221113p:plain

説明が微妙に違いますね。こっちの説明だとTransient Valueの値は、同じSectionに属するModuleからModuleの場合は変化しませんが、別なSection のModuleに移ったら変わると説明してあります。

この説明だとLocal Variableとの違いが分かります。

Dither Temporal AA ノードについて

そのものズバリのTutorialがありました。Dither Temporal AA Node | 5-Minute Materials [UE4] [6] です。

滅茶苦茶分かり易いです。こんなTutorialを作成する人が今まで一回も検索に引っかからなかったのは不思議です。

Dither Temporal AA ノードは、偽の透明をMasked Materialに作成する機能だそうです。Translucent はコストが高いMaterialですが、Dither Temporal AA ノードを使用する事でこのコストを下げる事が出来るそうです。

PrismaticaDev氏の説明が非常に分かり易いので同じ事をここでやってみたいと思います。

以下の様なMaterialを作成します。

f:id:kazuhironagai77:20210919221222p:plain

Blend ModeはTranslucentです。

f:id:kazuhironagai77:20210919221236p:plain

PlaneにこのMaterialを貼り付けると

f:id:kazuhironagai77:20210919221250p:plain

こんな感じの半透明になります。

f:id:kazuhironagai77:20210919221304p:plain

Shader Complexityを見ると

f:id:kazuhironagai77:20210919221317p:plain

うーん。

あんまり差が見えませんね。

PrismaticaDev氏の解説に出て来るサンプルは

f:id:kazuhironagai77:20210919221338p:plain

結構真っ赤です。

まあ、Translucentを使用すれば最低でも2回Renderingをしなければならない訳でコストがOpaqueに比べて高くなるのは理論的には確かです。

仕方ないです。3枚重ねてみました。

f:id:kazuhironagai77:20210919221352p:plain

今度は赤くなりました。これで行きます。

Litに戻すとこんな感じになってました。

f:id:kazuhironagai77:20210919221527p:plain

今度はDither Temporal AAノードを使用したMaterialを作成します。

Blend ModeをMaskedに変更して

f:id:kazuhironagai77:20210919221544p:plain

以下に示した様にDither Temporal AAを追加します。

f:id:kazuhironagai77:20210919221559p:plain

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

f:id:kazuhironagai77:20210919221614p:plain

うーん。

まずTranslucentとそっくりとは言えませんね。

でもある程度は後ろのImageも見えますので全く駄目と言うわけでもないですね。

PrismaticaDev氏の解説によればDither Temporal AAはMaterialを虫食い状態にするそうです。

そしてコストですが、

一枚ではこんな感じです。

f:id:kazuhironagai77:20210919221629p:plain

3枚ではこんな感じになりました。

f:id:kazuhironagai77:20210919221642p:plain

これは!

コストの面からはDither Temporal AAの方が圧倒的に有利ですね。

ただし、3枚重ねた実際のImageは以下の様です。

f:id:kazuhironagai77:20210919221657p:plain

100%、Translucentの代わりになる訳ではないさそうです。適所適材で行く必要がありますね。

PrismaticaDev氏のTutorialでは更にDither Temporal AAノードを使用した時に発生するへんな影の直し方についても別なTutorialで解説しています。

f:id:kazuhironagai77:20210919221711p:plain

うーん。まあこれは別な機会に勉強する事にします。

先週、使用したDither Temporal AAもOpacity Maskに繋がっていました。

f:id:kazuhironagai77:20210919221725p:plain

f:id:kazuhironagai77:20210919221731p:plain

<Distance To Nearest Surfaceノードについて

Distance To Nearest Surfaceノードについて調べます。

f:id:kazuhironagai77:20210919221749p:plain

これって名前から想像するとそのMeshから最も近い距離にあるAssetまでの距離を測るノードですよね。

公式のDocumentであるUtility Expressions [7] によるとDistance To Nearest SurfaceノードのRemarkには

f:id:kazuhironagai77:20210919221803p:plain

と書かれています。

Global Distance Fieldって何の事でしょう?

多分ですが、この公式のDocumentで述べられているMesh Distance Fields [8] の事と同じだと思います。

f:id:kazuhironagai77:20210919221818p:plain

つまり、Global Distance Fieldに、そのMeshから最も近い距離にあるAssetまでの距離が記録されている。と考えられます。

あ。分かった。

The signed distance …to the nearest occludes in the sceneがシーン内の最も近い距離にある遮蔽物からの距離、つまりMeshから最も近い距離にあるAssetまでの距離を指しているんです。その値がDistance fieldに入っているんです。

Distance To Nearest Surfaceノードの続きの実装部は何をしているのか?

次なんですがその後に

f:id:kazuhironagai77:20210919221837p:plain

こんな説明をして以下の実装をしているんです。

f:id:kazuhironagai77:20210919221851p:plain

これの意味が分からない。

うん。分からないなら実験してみます。

先程のMaterialを以下の様に改良しました。

f:id:kazuhironagai77:20210919221904p:plain

<<Subtract = 0、Divide = 30>>

f:id:kazuhironagai77:20210919221922p:plain

ぴったしガラス玉の内側に入っている部分だけ消えています。

<<Subtract = 10、Divide = 30>>

f:id:kazuhironagai77:20210919221940p:plain

なんと、1マス手前の位置からPlaneが消えています。1マスは10cmですのでSubtract=10は10cm手前で消滅すると言う事でしょうか?

<<Subtract = 30、Divide = 30>>

そんなに上手くは行かなかったです。

f:id:kazuhironagai77:20210919221959p:plain

Subtract = 30で5マス手前からPlaneが消滅しています。

しかしSubtractが何を表しているのかは分かりました。この数字が大きい程離れた所からPlaneが消えます。

<<Subtract = 10、Divide = 1>>

今度はSubtractを固定してDivideを変化させます。

f:id:kazuhironagai77:20210919222017p:plain

はい。Planeの曖昧な部分が全くなくなりました。

<<Subtract = 10、Divide = 10>>

f:id:kazuhironagai77:20210919222035p:plain

少しだけ曖昧な部分が出来ました。何となくですが曖昧な部分の大きさが10cmのような気がします。

<<Subtract = 10、Divide = 30>>

Divideを30にしたら曖昧な部分がもっと増えました。

f:id:kazuhironagai77:20210919222053p:plain

はい。DivideはPlaneの曖昧な部分の太さを担当しているようです。

先週の全く意味の分からなかった一文の意味が分かりました。

f:id:kazuhironagai77:20210919222241p:plain

このFadeはPlaneの消える部分を表しています。つまりSubtractする数字の事です。その次の黒いBandはPlaneの曖昧な部分を指しています。つまりDivideの部分です。

はい。これで完璧に理解しました。

<Get Level of Dissolveについて>

今度は先週、Scratch Pat Moduleより作成したGet Level of Dissolve Moduleについてです。

f:id:kazuhironagai77:20210919222305p:plain

ここで分からない事は一つだけです。

何でInput New Collision QueryとSample PositionをQuery Mesh Distance Field GPU ノードにパスするとDistance To Nearest Surfaceの値が返って来るのかだけです。

f:id:kazuhironagai77:20210919222318p:plain

これについてはGoogleで検索しても何も出て来ません。

唯一出て来たのがGithubにあるAdvanced Niagara Effects | Inside Unreal [9] で、そこには

f:id:kazuhironagai77:20210919222331p:plain

と書かれていました。

ここから推測すると、New Collision QueryがDistance Fieldを保持していてSample PositionがParticleの位置を保持しているんでしょうか?

それよりも

f:id:kazuhironagai77:20210919222346p:plain

これを読むとDistance Fieldって空間中にvoxelとして充満しているんでしょうか?

そう言えばMesh Distance Fields [8]に合った図(以下に示している)でも何もない空間中から木への距離を表しています。

f:id:kazuhironagai77:20210919222404p:plain

この図をよーく見ると四角の図が全体を覆ってますね。

とするとUnreal Engineでは全ての空間がVoxelで充満していてそれぞれのVoxelがDistance Field値を保持してると考えられます。

すると先程述べた

f:id:kazuhironagai77:20210919222420p:plain

は、「Meshから」ではなく「何もない空間に配置されているVoxel」からがより正確に近い言い方になります。

<Lerp Particle Attribute Module

このModuleは2つの値のLinear Interpolationをするのは間違いないです。

f:id:kazuhironagai77:20210919222441p:plain

f:id:kazuhironagai77:20210919222447p:plain

でもこの二つの値って同じじゃ…

f:id:kazuhironagai77:20210919222501p:plain

その後でVortex Velocityを追加していました。

うーん。でもやっぱり良く分からない。

Lerpした値はどの変数が保持するんでしょうか?

2.3 Niagara : Building advanced effects in Niagara | Unreal Engine [4]の総括の続き

目的は達成出来たのか?>

目的は取りあえずTutorial通りに作成出来る事だったのですが、Material以外は出来ましたね。

100%理解出来たかどうかはまた別な問題ですが。

Tutorial通りに作れたのか?>

上記で述べた通りです。

<このTutorialの改善点について>

CrunchのMaterialが新しくなっているのでその場合の直し方を示してほしいです。それ以外は無いです。

 2.4 Niagara : Building advanced effects in Niagara | Unreal Engine [4]CGHOW氏のTutorialを比較して

はい。

それでは今回のメインである。これからのNiagaraの勉強をどうするかについて、今までの勉強を踏まえて考えていこうと思います。

それで色々まとめて検討するより、徒然なるままに好きな事を述べた方が本質に迫れる気がしています。のでダラダラと思った事を書いていきます。

3週間かけてUnreal Engine公式のTutorialであるNiagara: Building advanced effects in Niagara | Unreal Engine [4]を勉強しました。

  • 一応、Tutorial通りの再現は出来る。
  • MaterialなどVersionが変わると何をやっているのか不明。
  • 理解出来ない箇所はあった。

一方でCGHOW氏のTutorialは

  • Tutorial通りの再現は出来ない。
  • 全部の解説はしていない事が多い。
  • 理解出来ない所は、いくらがんばっても理解出来ない。
  • 自分でStatic Meshを作成する必要がある箇所がある。

となっています。

これだけ見ても、CGHOW氏のTutorialを主にNiagaraの勉強を進めるのは危険過ぎます。

後、VFXに詳しくなるメリットがどれだけあるのかも不明です。Userから見れば買ったVFXを追加すれば同じに見えるだけかもしれません。

ただしNiagaraにはかなり可能性を感じています。ModuleやDynamic InputをVisual Scriptingで自在に組めるのはとても可能性を感じます。

後、CascadeだとEffectの前後関係がオカシイ時があります。私はEffectはもっとゆっくり動くべきと思っていますが、Cascadeをゆっくり動かしたらEffectの前後がオカシイ部分もUserにばれてしまいます。今までやった分だけですがNiagaraではEffectの前後関係でオカシイ部分は見つかっていません。この部分にもNiagaraの可能性を感じます。

炎、煙、雷、水、氷、魔法陣、雪、砂、風、光、闇、爆発、回復、状態異常や呪いのEffectの作成方法位は基本として知っておきたいです。

この中で一応、今の所、一部でも作り方が分かっているのは、炎、煙、雷、水、氷、魔法陣、雪、光、闇、爆発、回復、状態異常や呪いでしょうか?結構分かって来ましたね。砂はあれだけ勉強したのに直接の作成方法はまだ不明です。

この辺のEffectの作成方法を自分で追及するのも面白いかもしれません。

CGHOW氏のTutorialはこれらのVFXの作り方を直接学ぶ事は出来ないかもしれませんがその過程で今まで知らないModuleやDynamic Inputの使用方法の勉強やどんなEffectを追加すべき、などは学べます。その辺の勉強はかなり役に立つと思います。

後、考えているのはVFXの勉強は一端終わりにしてMaterialかBlenderの使用方法を勉強する事です。

MaterialのTutorialにはBen Cloward氏が作成したTutorial [11]があってとても良い出来のような気がしています。

後、たまたま見つけたんですがKurt Kupser氏のAdvanced UE4 Shaders [12]もちょっと興味があります。

2.5 これからの勉強法について

やっぱりNiagaraの勉強をここで止めるのは勿体ないですので、こうする事にします。

  • CGHOW氏のTutorialを勉強する時は同じEffectが完成しなくても良い。そのTutorialを勉強する事で新しいModuleDynamic Inputなどの使用方法が学べたらOKと考えておく。
  • 自分でEffectを作成してみる。
  • Content ExamplesSampleを自分で勉強してみる。
  • Materialの勉強も開始する。よってCascadeの勉強は一端中止する。

CascadeのEffectは前後関係がオカシク表示されるので、頑張って勉強する価値はこの中では最も低いと思われます。唯一の問題は今作成しているRPGのUEのVersionは4.24なのでNiagaraが使用出来ない事ですが、今まで勉強した知識で対応する事にします。

うん。

これで行きます。Niagaraの勉強は

  • CGHOW氏のTutorialを勉強する
  • 自分でEffectを作成
  • Content ExamplesのSampleを自分で勉強

のどれかをする事にします。そしてCascadeの勉強は一端中止して、Materialの勉強を開始します。特にBen Cloward氏が作成したTutorial [11]をやっていくことにします。

2.6 Static Mesh Sampling in UE5 Niagara Tutorial [13] を勉強する

なんとCGHOW氏のTutorialでContent ExamplesのSampleの解説をしている動画がありました。

f:id:kazuhironagai77:20210919222703p:plain

今週はこれを勉強しましょう。

UE5で作成すると言うので一応UE5をInstallしました。このパソコンでどこまで動くのか分かりませんが、出来る所までやっていき、出来なかったらUE4.26 か27でやり直します。

f:id:kazuhironagai77:20210919222723p:plain

新しいLevelを作成した後でSphere Reflection Captureを消しています。何か理由があるんでしょうか?

f:id:kazuhironagai77:20210919222738p:plain

<Cone、球、ドーナツ型のMeshの作成>

Cone、球、ドーナツ型のMeshを作成してUE5にImportしていますが、自分で作る事が出来ないのでStarter kitにあるやつをそのままCopyしてきました。

f:id:kazuhironagai77:20210919222756p:plain

Niagara Systemの作成>

Niagara SystemにTemplateのFountainを追加して新しいNSを作成しました。

f:id:kazuhironagai77:20210919222817p:plain

この辺はUE4と全く同じですね。

要らないModuleを全部消去しました。

f:id:kazuhironagai77:20210919222831p:plain

一応、要らないModuleの意味も理解出来ますね。

Emitter Update SectionのEmitter State ModuleやParticle Spawn SectionのInitialize Particle ModuleそしてParticle Update SectionのParticle State ModuleはどのEmitter Stackでも必ず必要なはずです。

<Cornの生成>

Emitter sectionにSpawn Burst Instantaneous Moduleを追加しました。Spawn Countは50にセットしました。

f:id:kazuhironagai77:20210919222850p:plain

f:id:kazuhironagai77:20210919222856p:plain

この辺はまだ理解出来ますね。50個のParticleを一辺に生成すると言う意味なはずです。

f:id:kazuhironagai77:20210919222912p:plain

Particle Spawn SectionのInitialize Particle Moduleの設定を以下のように変更しました。

f:id:kazuhironagai77:20210919222927p:plain

それぞれのParticle の寿命は2秒になりました。

当然、Mesh RendererをRender Sectionに追加します。

f:id:kazuhironagai77:20210919222940p:plain

更にMeshにドーナツをセットします。

アレConeでした。Coneをセットします。

f:id:kazuhironagai77:20210919222954p:plain

TutorialではConeのサイズが小さいので、Particle Spawn SectionのInitialize Particle ModuleのMesh Uniform Scaleの値を変更しています。

f:id:kazuhironagai77:20210919223008p:plain

私のCone Meshは大きいのでScaleはそのままにしておきます。後で小さくする必要が出てくるかもしれませんが。

<Cone用Materialの作成>

この後、このCone用のMaterialを作成しています。

Tutorialと全く同じように作成しました。

f:id:kazuhironagai77:20210919223028p:plain

<Cornに色を追加>

その作成したMaterialをRender SectionのMesh Renderer Moduleの以下の箇所にセットします。

f:id:kazuhironagai77:20210919223046p:plain

Particle Spawn SectionのInitialize Particle ModuleでConeの色を赤くしました。

f:id:kazuhironagai77:20210919223100p:plain

MaterialのParticle ColorはOpacityに繋がってないですが、Aの値を変化させたらConeの色が薄くなるんでしょうか?

<Scratch Pat Moduleの作成>

このConeらをドーナツの表面で生成させて、その後、球の表面に移動させたい訳です。

そのためにはStatic Mesh Location Moduleを…使用しないで、Scratch Pat Moduleを使用して全部のやり方を解説してくれるそうです。

おお。

ひょっとするとですが、最近のCGHOW氏のTutorialはParticleを始めて学習する人達向けにかなり親切に作成されているのかもしれません。

Map Get ノードにInput New Static Meshを追加しました。

f:id:kazuhironagai77:20210919223117p:plain

成程、これで望みのMeshをModuleにパスする訳ですね。

f:id:kazuhironagai77:20210919223133p:plain

はい。しています。

今度はそのMeshのWorld SpaceにおけるTri Positionの値をGet Tri Position WS Moduleを使用して呼び出しています。

f:id:kazuhironagai77:20210919223147p:plain

Tri PositionってMeshのどの位置を指しているんでしょうか?

一個一個のMeshを指しているのかなとも思ったんですが、Meshって四角の時もありますよね。

後、World SpaceとLocal Spaceの時のEffectの挙動の違いで良く分からない時があります。World SpaceとLocal Spaceの復習も後でやります。

Get Tri Position WS ModuleのCoordにRandom Tri Coord Moduleの返し値を繋ぎます。

f:id:kazuhironagai77:20210919223225p:plain

Random Tri Coord Moduleの機能をその名前から想像するとStatic Meshの中にある沢山のMeshから一つを適当に選ぶものと想像出来ます。とするとGet Tri Position WS Moduleの機能もStatic Meshの中の一個のMeshの位置を返していると考えられます。

Map SetにNew Vectorを追加して名前を以下の様に変更しました。

f:id:kazuhironagai77:20210919223240p:plain

更にName SpaceをParticleに変更しました。

f:id:kazuhironagai77:20210919223254p:plain

Applyを押してこのModuleが使用出来るようにします。

f:id:kazuhironagai77:20210919223309p:plain

<作成したScratch Moduleを使用して球の表面にCornを発生させる>

Scratch Moduleの変数にMy SphereとMy Torusが追加されています。そこに先程のStatic Meshを追加します。

f:id:kazuhironagai77:20210919223327p:plain

正しこれだけでは何も起こりません。

f:id:kazuhironagai77:20210919223341p:plain

何故ならScratch Moduleの返し値をParticleの生成する位置に指定していないからです。

そのためにParameterのParticle AttributeにあるParticle PositionをDragして

f:id:kazuhironagai77:20210919223354p:plain

Particle Update Sectionにセットします。

f:id:kazuhironagai77:20210919223409p:plain

へえー!こんな事が出来るんですね。

これが出来ると何が出来る様になるんでしょう?楽しみです。次に進みましょう。

なんと、Particle のPositionの値を先程作成したParticleのMy Sphere Locationに指定しました。

f:id:kazuhironagai77:20210919223425p:plain

あ、分かりました。

単に

Position = My Sphere Location;

を実装したのと同じ事をここでしたんです。

Cornの位置が球の表面に沿ってバラバラになりました。

f:id:kazuhironagai77:20210919223500p:plain

成程。

これは分かり易いです。

ただTutorialのCornと比較すると私のCornはかなり大きいです。

Particle Spawn SectionのInitialize Particle Moduleの設定を以下のように変更します。

f:id:kazuhironagai77:20210919223513p:plain

大分、TutorialのImageに近づきました。

f:id:kazuhironagai77:20210919223534p:plain

当然、Cornはドーナツ状に配置されるようになりました。

f:id:kazuhironagai77:20210919223550p:plain

分かり易い。

非常に分かり易いです。

<Lerp Particle Attribute Moduleを使用してドーナツの表面に発生させたCornを球の表面に移動させる>

そしたらParticle のPositionを消してしまいました。

f:id:kazuhironagai77:20210919223608p:plain

そしてParticle Update Section にLerp Particle Attribute Moduleを追加しました。

f:id:kazuhironagai77:20210919223626p:plain

おお!

この今一、良く分からないModuleの使用方法について詳しく教われそうです。

まずPositionにチェックを入れました。

f:id:kazuhironagai77:20210919223640p:plain

Position AにMy Sphere LocationをセットしてPosition BにMy Torus Locationをセットします。

f:id:kazuhironagai77:20210919223653p:plain

これなら意味が分かります。

やっとLerp Particle Attribute Moduleの機能が理解出来ました。

後はどの程度のBlendをPosition AとPosition Bでするかと言う事でしょう。

それはこのLerp Alphaで設定するそうです。

f:id:kazuhironagai77:20210919223713p:plain

0だと100% Position Aの値になり1だと100% Position Bの値になるそうです。

試しにLerp Alphaの値を0から1に変えてみました。

f:id:kazuhironagai77:20210919223841p:plain

f:id:kazuhironagai77:20210919223847p:plain

球の表面に発生したコーンがドーナツの表面に発生したコーンに変化しています。

Lerp Alphaの値をFloat from Curveに変更してCurveの値は以下の様に変更しました。

f:id:kazuhironagai77:20210919223901p:plain

上手く映像で撮れなかったんですが、ドーナツから球に変化しています。

なんで逆と思ったら、このCurveが1から0に変化しているからでした。

これでLerp Particle Attribute Moduleの機能が理解出来ました。

今週は時間がないのでやりませんが、来週、この機能を分かり易く説明する簡易Effectを作って、自分で解説し直します。

<コーンの向きをMeshの表面に合わせる(球だけ)>

今度はコーンの向きをMeshの表面に合わせます。

そのためには、Get Tri Normal WS Moduleを使用します。

f:id:kazuhironagai77:20210919223920p:plain

全体はこんな感じです。

f:id:kazuhironagai77:20210919223938p:plain

そしてParticle Update SectionにOrient Mesh To Vector Moduleを追加します。

f:id:kazuhironagai77:20210919223953p:plain

このModuleは初めて使用します。

My Sphere Normalをセットします。

f:id:kazuhironagai77:20210919224007p:plain

向きが少しだけオカシイみたいです。

f:id:kazuhironagai77:20210919224022p:plain

Particle Spawn SectionにInitial Mesh Orientation Moduleを追加します。

f:id:kazuhironagai77:20210919224036p:plain

Initial Mesh Orientation ModuleのRotationに0.25を追加します。

f:id:kazuhironagai77:20210919224051p:plain

その結果、

f:id:kazuhironagai77:20210919224106p:plain

向きが直りました。

ただし最初のドーナツ型の時はコーンの方向は滅茶苦茶なままです。

f:id:kazuhironagai77:20210919224126p:plain

<コーンの向きをMeshの表面に合わせる(ドーナツも)>

それを直すためにOrient Mesh To Vector ModuleのLook At DirectionのAとBに以下の値をセットします。

更にAlphaにセットされたFloat from CurveのGraphはLerp Particle Attribute のグラフをそのままPasteして使用しています。

f:id:kazuhironagai77:20210919224206p:plain

その結果、ドーナツ形でもコーンがドーナツに沿っています。

f:id:kazuhironagai77:20210919224224p:plain

はあ。成程。

Orient Mesh To Vector ModuleのLook At DirectionにLerp VectorをセットしたのでVector AとVector Bがセット出来るようになりました。更にAlpha値のFloat From Curveもセット出来きます。

<Content Exampleのサンプルのような位置の移動も追加する>

今度はContent Exampleのサンプルのように、球とドーナツが離れた位置に配置された状態でCornに形状の変化だけでなく位置の変化も追加します。

Scratch ModuleのMy Sphereの以下の赤線で囲った部分をクリックして

f:id:kazuhironagai77:20210919224243p:plain

Read from New User Parameterを選択します。

f:id:kazuhironagai77:20210919224304p:plain

My SphereにUser My Sphereが表示されました。

f:id:kazuhironagai77:20210919224320p:plain

ドーナツも同様にします。

f:id:kazuhironagai77:20210919224335p:plain

UE5のEditorに戻り、作成したNSをLevel上に配置します。

f:id:kazuhironagai77:20210919224351p:plain

この時点ではNSのCornはその場で形状の変化をしているだけです。

NSのSourceに配置されている球とドーナツを追加します。

f:id:kazuhironagai77:20210919224405p:plain

Tutorialではこの部分の作業がカメラに写っていません。この部分のやり方を判明させるのにちょっとだけ苦労しました。

f:id:kazuhironagai77:20210919224423p:plain

こんな感じにNSが移動するようになりました。

f:id:kazuhironagai77:20210919224441p:plain

f:id:kazuhironagai77:20210919224453p:plain

f:id:kazuhironagai77:20210919224504p:plain

結構な勉強になったので、今週はここまでとします。(Tutorialの10分33秒位)

このTutorialは比較的初心者向けに作成されているためか、分かり易かったです。私でも問題なく再現出来ました。

新しく習ったModuleなどの機能の調査やTutorialの残りは来週やります。

3.Cascade: 先々週の続き

はい。

先程、述べた通りCascadeの勉強は中止にします。そしてMaterialの勉強をやる事にします。

Ben Cloward氏が作成したTutorial [11]の中からどれかを選んで勉強します。

3.1 それぞれのTutorialについて

Ben Cloward氏が作成したMaterialのTutorialは沢山の種類があります。どれから勉強すべきなのか分かりません。軽くそれぞれのTutorialを見てそこで何を教えているのかを理解します。その後でどのTutorialを最初に勉強するかを決定します。

Shader Graph Basics [14]

このTutorialは本当の基礎の基礎を教えるそうです。

f:id:kazuhironagai77:20210919224845p:plain

ぱっと見ましたが、確かに基本中の基本を教えていますね。でも復習や抜けの確認のためにこのTutorialからやるのが良いかもしれません。

UE4 Material Editor - Shader Creation [15]

こっちのTutorialも初心者向けみたいです。

f:id:kazuhironagai77:20210919224927p:plain

Shader Graph Basics [14]とどこか違うのか調べたらこっちのTutorialの方が古いんです。そのため30個も動画があります。

ただ今までの経験から言うと、Tutorialは新しい方が何倍も優れています。

Rain Materials in Unreal Engine 4 [16]

これは文字通り、雨を表現するために必要なMaterialの作成方法を教えています。

f:id:kazuhironagai77:20210919224958p:plain

まあ、応用編ですね。

Procedural Noise - UE4 Materials 101 [17] >

これはPerlin Noise についての勉強のようです。

f:id:kazuhironagai77:20210919225022p:plain

UE4 Water Material Tutorial [18] >

これは水のMaterialの作成方法のTutorialのようです。

f:id:kazuhironagai77:20210919225044p:plain

3.2 Shader Graph Basics [14]を勉強する

まあ、これだけ調べたら当然ですがShader Graph Basics [14]を勉強します。

ハッキリ言ってこのTutorial、かなり簡単に見えます。どんどんやっていきます。

Announcing What's Next! - Shader Graph Basics [19] >

ここでは今まで勉強した内容の簡単なまとめと、このTutorialについての解説がされていました。

特に自分でImplementしなければならない事はなかったです。

一つだけ特に記録しておくべきと考えられる重要な内容は、Unreal Engine 5だけでなくUnityも同時にやるそうです。Material の実装はUnrealもUnityもそんなに変わらないそうです。

The Graphics Pipeline - Shader Graph Basics [20] >

前半部分は、一般的なGraphicsのPipelineについての解説です。一応、大学では3d Graphicsが専門だったのでこの辺は知ってる事でした。

後半部分でUE5のMaterialの実装部分の一部をPixel Shader ではなくVertex Shaderで行う方法が解説されていました。これは自分で試してみます。

面白かったのがUnityとの比較です。

以下のUnityのMaterialを示しますが、これってGLSLそのままじゃないですか。

f:id:kazuhironagai77:20210919225108p:plain

これはProgrammer friendlyです。GLSLで書いていたCodeをほぼそのままで書き写せそうです。

こりゃ、UE負けている。

と思ったら、以下に示したTextureを動かす実装ですが、Unityはこの部分をUEのようにVertex Shaderで行う方法がないそうです。

f:id:kazuhironagai77:20210919225124p:plain

ほお。

これは一長一短で、UnityとUEがGame Engine業界で覇権を争っている理由が分かります。優劣つけがたいです。

それではこのTutorialでやっている実装を実際にUE5で試してみます。

作成しました。これはTextureをSine Curveに沿って移動させる実装です。

f:id:kazuhironagai77:20210919225146p:plain

Statsを見ます。

f:id:kazuhironagai77:20210919225200p:plain

Vertex Shaderが111 instructionsで、それ以外のShaderが152 instructionsです。

これにVertex Interpolator ノードを追加します。

f:id:kazuhironagai77:20210919225221p:plain

Statsの結果が変わりました。

f:id:kazuhironagai77:20210919225248p:plain

Vertex Shaderが115 instructionsで、それ以外のShaderが148 instructionsです。

ここでそれ以外のShaderはPixel shaderしかないのでPixel shaderの工程が4つも減ったらかなり作業工程が減っているはずです。

成程、分かりました。

後、大切な事はUser InterpolatorsでCustom が0から2にセットされている事です。

User Interpolatorsの数は限られており、その中の2つが使用されていると言っています。勿論Texture CoordのUとVとして使用されていると言う事です。

Position、Normal、そしてUVに関してはVertex Shaderで計算した方がコストが下がるのでVertex Interpolator ノードの使用を考えるべきだそうです。

ここからは私の意見ですが、Normal VectorをVertex Shader内で計算してFragment Shaderで単純にInterpolateするとVertex Shader内では正規化したにもかかわらず、Fragment Shaderで1より大きい数字になってしまったりします。ので無条件で納得は出来ませんが一つの手段としてPosition、Normal、そしてUVに対しての計算はVertex Interpolator ノードの使用を考えるべきは納得出来ます。

今度は、以下の部分をWorld Position Offsetに繋ぎます。

f:id:kazuhironagai77:20210919225305p:plain

Statsを見ます。

f:id:kazuhironagai77:20210919225319p:plain

Vertex Shaderが121 instructionsで、それ以外のShaderが148 instructionsのままです。

つまりWorld Position OffsetはVertex Shaderで計算されていると言う事です。

はい。

今週のMaterialの勉強はここまでとしておきます。

4.Map1の作成の続き

4.1 Landscapeの調整

地面が平ら過ぎるのでLandscapeでデコボコを追加します。

f:id:kazuhironagai77:20210919225345p:plain

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

f:id:kazuhironagai77:20210919225400p:plain

f:id:kazuhironagai77:20210919225408p:plain

地面ですが多少デコボコする位に留めました。

f:id:kazuhironagai77:20210919225434p:plain

何故か、この部分で色が変わっています。

f:id:kazuhironagai77:20210919225449p:plain

直したいですが理由が分かりません。

4.2 Light Mass Important Volume と Post Process Volumeについて

以下の二つのAssetが

f:id:kazuhironagai77:20210919225515p:plain

初期状態のまま残っていました。

f:id:kazuhironagai77:20210919225530p:plain

一応Light massとPost Processの機能は知っていますが、あんまり詳しくはないです。

一回きちんと復習しておくべきでしょう。

これらの勉強をします。

<Light Mass Importance Volume

WTF Is? Volume - Lightmass Importance in Unreal Engine 4 [21] に使い方といつ使うべきなのかについての解説がありました。

後、これは日本語の資料ですがライトマップの最適化 にLight Mapを可視化するためのToolの使用方法の詳しい解説がありました。ただこのサイト、作者名が書かれていないので参照からは外しました。

またUnreal Sensei氏がHow to Make Unreal Engine 4 Render Lighting Faster! - UE4 GPU Lightmass Tutorial [22] でGPUを使用したLight Massについての詳しい解説を作成していますが、今回はGPUは使用しないのでこれは見ませんでした。

それでStationary Lightが配置されていてかつそのLightのIndirectな明るさが欲しい所にLight Mass Importance Volumeを配置すれば良いと考えています。

このGameは中世の世界観を出したいので暗いほうが良い訳です。

出来るだけLight Mass Importance Volumeは外していきます。

Light Mass Importance Volumeを外しました。

朝です。

f:id:kazuhironagai77:20210919225557p:plain

別に変な所はありません。と言うかどこが変わったのかも分かりません。

Directional LightもMovable にセットしてるのでSky LightしかLight Massに影響を与える光がないからかもしれません。

昼です。

f:id:kazuhironagai77:20210919225635p:plain

これも今までとほとんど同じに見えます。

夕方です。

f:id:kazuhironagai77:20210919225705p:plain

普通ですね。

夜です。

f:id:kazuhironagai77:20210919225719p:plain

問題ないです。

Indirectな光の影響と言えば最初の村で家が同じ様に並んでいるのに片方だけ真っ黒な所があります。

f:id:kazuhironagai77:20210919225737p:plain

これってLight Mass Importance Volumeを配置したら変わるんでしょうか?

試してみます。

f:id:kazuhironagai77:20210919225800p:plain

変わってないですね。

Light Mass Importance VolumeはこのMapにはいらないですね。ただし全部外してしまうとUE4が勝手にLight Massを配置してしますので適当な所に一個だけ配置しておきます。

<Post Process Volume

これは勉強すべき範囲が多すぎです。Loading Screenの勉強が終わったらやる事にします。

4.3 最初の村の作成

Playerの操作するキャラが銀河鉄道に乗ってMap1に到着したら、村長と話しをします。

f:id:kazuhironagai77:20210919225841p:plain

すると魔物がうろついているので、武器を手に入れる必要がある。その為には奥の村に進む必要が在る事を知ります。

あ。

最初の村の住人のMeshがSK_Mannequinのままでした。

f:id:kazuhironagai77:20210919230001p:plain

これを直しましょう。

<村の住人のMeshの変換>

まず、この前買った

f:id:kazuhironagai77:20210919230011p:plain

の付属のキャラの色違いを全部作成しました。

これをそれぞれのNPCに追加して以降と思います。

f:id:kazuhironagai77:20210919230358p:plain

これをそれぞれのNPCに追加して以降と思います。

<Old Man

f:id:kazuhironagai77:20210919230428p:plain

小さくしてみました。

f:id:kazuhironagai77:20210919230444p:plain

UWidgetのキャラとは全く違いますね。

f:id:kazuhironagai77:20210919230505p:plain

後で調節します。

<Magic Researcher

これに近いImageのキャラを探します。

f:id:kazuhironagai77:20210919230526p:plain

これが一番近いImageですかね。

f:id:kazuhironagai77:20210919230552p:plain

頭の大きさが全然違います。エルフとドワーフみたいな種族の違いを導入しないと厳しそうです。

<Mountain Man

うーん。この爺さんに似てるキャラはいませんね。

f:id:kazuhironagai77:20210919230623p:plain

全然、見た目は違いますが取りあえずこのキャラを使用しておきます。

f:id:kazuhironagai77:20210919230648p:plain

やっぱりこっちの方がMountain Manって感じがしますね。

f:id:kazuhironagai77:20210919230720p:plain

こっちにしましょう。

<Head Man

今度は村長です。

f:id:kazuhironagai77:20210919230744p:plain

先程の王様と同じでいいでしょう。

f:id:kazuhironagai77:20210919230808p:plain

サイズは違いますがこれで行きます。

<Business Man

Business Manだそうです。

f:id:kazuhironagai77:20210919230841p:plain

これですかね。

f:id:kazuhironagai77:20210919230944p:plain

<Fortune Teller

占い師です。

f:id:kazuhironagai77:20210919231016p:plain

これですかね。

f:id:kazuhironagai77:20210919231059p:plain

<Retired Warrior

退役した戦士です。

f:id:kazuhironagai77:20210919231130p:plain

赤い色がありません。これで我慢します。

f:id:kazuhironagai77:20210919231150p:plain

<Talking NPC Political

政治の事ばかりおしゃべりする男性のNPCです。

f:id:kazuhironagai77:20210919231223p:plain

見た目から何か何まで違いますがこれで行きます。

f:id:kazuhironagai77:20210919231342p:plain

<Village Princes

村長の娘です。

f:id:kazuhironagai77:20210919231410p:plain

これにします。

f:id:kazuhironagai77:20210919231427p:plain

<Sheriff

村の保安官です。

f:id:kazuhironagai77:20210919231457p:plain

王様を大きくしました。

f:id:kazuhironagai77:20210919231518p:plain

<Back Pack

旅行者ですね。

f:id:kazuhironagai77:20210919231552p:plain

Blender使えたら自分で3Dモデル作成するんですが…

自分で言うのもあれですがこの2Dのデザインかなり良いですよね。

しかしこのデザインなら3Dの製作もそんなに難しくないですよね。

f:id:kazuhironagai77:20210919231625p:plain

もうどれでも同じでしょう。使ってないキャラを選択しました。

<Hunter

Hunterと言っていますが実際は傭兵ですね。

f:id:kazuhironagai77:20210919231813p:plain

体を大きくしました。

f:id:kazuhironagai77:20210919231835p:plain

<Weather Cast

天気予報する人です。

f:id:kazuhironagai77:20210919231901p:plain

老人はこれしかないです。

f:id:kazuhironagai77:20210919231938p:plain

これにします。

<Poet

詩人です。

f:id:kazuhironagai77:20210919232016p:plain

全然imageが違う。けど詩人っぽくはあります。

f:id:kazuhironagai77:20210919232034p:plain

<Henchman

f:id:kazuhironagai77:20210919232055p:plain

ちっこくしてみました。

f:id:kazuhironagai77:20210919232115p:plain

<Scientist

科学者の卵です。

f:id:kazuhironagai77:20210919232209p:plain

色だけ同じキャラにしました。

f:id:kazuhironagai77:20210919232238p:plain

これでNPC全てにキャラ振りを終わりました。

5.最初の村の村人のセリフを直す

最初の村で村人に話かけたら変なセリフを言っている所があります。

セリフを直します。

f:id:kazuhironagai77:20210919232306p:plain

完璧ではないですが何とか直しました。

細かい点ではおかしな所がありますが、来週以降、順次直していきます。

6.Loading Screenの勉強の続き

今週でLoading Screenの勉強は終りにします。今週やる事は3つです。

一つ目はUE4.24 にAsync Loading Screen plug-inを追加して、Ch4_3にLoading Screenを作成する事です。

2つ目はAsync Loading Screenを追加したEngineは必ず Open Level NodeでLoading Screenを呼び出しますが、この呼び出すLoading Screenの種類をOpen Levelの種類によって分けたいのです。具体的に言えば、銀河鉄道に乗って移動する場合は、5秒以上の鉄道に乗っているLoading Screenを表示し、宿屋で寝ている時は、睡眠中のLoading Screenを表示したいのです。

最後はAsync Loading ScreenがどうやってOpen Levelノードが呼ばれる度に呼ばれるようにしてるのかを調べます。これさえ分かれば後はコードが全部読める気がしています。

この方法について調べます。

6.1 別なLoading Screenを表示する方法

Async Loading Screen [23] に以下の解説がありました。

f:id:kazuhironagai77:20210919232450p:plain

この機能を使用すれば別なLoading Screenの表示が出来そうです。

試してみます。

先週、Async Loading Screen用に作成したLevelにSet Display Backgroundノードを追加します。

f:id:kazuhironagai77:20210919232526p:plain

f:id:kazuhironagai77:20210919232533p:plain

試してみます。

出来ませんでした。

調べたら以下の様に書かれていました。

f:id:kazuhironagai77:20210919232606p:plain

しました。

f:id:kazuhironagai77:20210919232633p:plain

もう一回テストします。

Play ScreenからPlay Screen 1に移動します。

f:id:kazuhironagai77:20210919232925p:plain

Play Screen 1 からPlay Screenに移動します。

f:id:kazuhironagai77:20210919232941p:plain

Background Imageの設定は以下の様になっています。

f:id:kazuhironagai77:20210919232959p:plain

出来ました。

6.2 Loading Screenを作成する。

ここでLoading Screenも作成してしまいます。

完成品を4.24に移動した方が簡単であるのと、何か問題が発生した時にここの方が直しやすいからです。

Background Imageを以下のように作成しました。

f:id:kazuhironagai77:20210919233023p:plain

4ステップで描く! 星空の描き方メイキング [24] を参考にして描きました。

電車のイラストはhttps://illustimage.com/?dl=3165 のものを使用さえて頂きました。

利用規約をみると

f:id:kazuhironagai77:20210919233050p:plain

f:id:kazuhironagai77:20210919233057p:plain

と書かれていて加工しても良いし、このゲームを後で販売しても問題ない訳です。

f:id:kazuhironagai77:20210919233127p:plain

しかもコピーライトの表記も要らないとあります。

f:id:kazuhironagai77:20210919233202p:plain

え?

一番最初に、商業利用可能な無料のイラスト…て言っていましたよね。

何これ?

定食屋で「お代わり無料」と書かれていたからお代わりしたら「ご飯は別です。」とか言われて代金余計に取られた的な扱いは。

面倒臭そうなので電車の絵は消します。

これって「有利誤認表示」になりますよね。最初の文を一部商用利用可能に変更しておかないと、もし問題になった時に致命傷になる気がします。

電車の絵はhttps://www.irasutoya.com/2016/03/blog-post_625.html [25]から使用させてもらいました。

利用規定を確認します。

f:id:kazuhironagai77:20210919233251p:plain

私が制作しているゲームのLoading Screenに使用する事に対しては特に問題はなさそうです。

f:id:kazuhironagai77:20210919233316p:plain

編集や加工のOKと言っています。

f:id:kazuhironagai77:20210919233340p:plain

商業に利用したとしても1個だけしか使用していないのでOKと解釈しました。

クレジット表記も要らないとありました。

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

f:id:kazuhironagai77:20210919233428p:plain

銀河鉄道に乗らない場合のLoading Screenも考えておきます。

f:id:kazuhironagai77:20210919233509p:plain

そしてLevel Of DetailのTexture GroupをUIにセットします。

f:id:kazuhironagai77:20210919233527p:plain

こんな感じです。

f:id:kazuhironagai77:20210919233619p:plain

f:id:kazuhironagai77:20210919233627p:plain

Boarder Backgroundを改良します。

f:id:kazuhironagai77:20210919233651p:plain

f:id:kazuhironagai77:20210919233703p:plain

隙間を追加します。

f:id:kazuhironagai77:20210919233757p:plain

Loading のCircular throbberをThrobberに変更しました。

f:id:kazuhironagai77:20210919233818p:plain

セリフも直しました。

f:id:kazuhironagai77:20210919234041p:plain

f:id:kazuhironagai77:20210919234049p:plain

スタート画面用のLoading Screenも作成します。

作成したんですが、表示されません。

色々調べたら以下のShow Widget Overlayにチェックを入れないと駄目みたいです。

f:id:kazuhironagai77:20210919234104p:plain

こんな感じです。

f:id:kazuhironagai77:20210919234125p:plain

6.3 Async Loading ScreenUE4.24 に追加する

作り方が分かったのでCh4_3に実装します。

f:id:kazuhironagai77:20210919234147p:plain

Async Loading ScreenをUE4.24 に追加します。

f:id:kazuhironagai77:20210919234203p:plain

Plug Inを選択してEditorを再起動します。

Startup Loading Screenから作成していきます。

f:id:kazuhironagai77:20210919234219p:plain

こんな設定にしました。

f:id:kazuhironagai77:20210919234240p:plain

f:id:kazuhironagai77:20210919234247p:plain

テストします。

f:id:kazuhironagai77:20210919234303p:plain

こんな感じです。

Default Loading Screen画面も作成します。設定は4.26で作成したのとまったく同じです。

f:id:kazuhironagai77:20210919234318p:plain

開始画面です。

f:id:kazuhironagai77:20210919234337p:plain

Default Load画面です。

f:id:kazuhironagai77:20210919234355p:plain

Open Level毎に、どちらのImageとTextを読み込むのかを指定します。

Widget BPを一個開いて、そこからOpen Level ノードを使用しているBPを検索します。

f:id:kazuhironagai77:20210919234414p:plain

これらを一個ずつ検討していきます。

<Game Over Screen Falling Widget

Game Over Screen Falling WidgetのRe-Start ボタンがクリックされた時にOpen Level ノードが呼ばれていました。

f:id:kazuhironagai77:20210919234437p:plain

これ落っこちて死亡した時にやり直す時のボタンなので、Map1からやり直すのはオカシイです。この部分は後で直します。

それは兎も角、銀河鉄道に乗る訳ではないので「赤い帽子の魔女からの手紙」のLoading Screenを表示します。

f:id:kazuhironagai77:20210919234503p:plain

勿論、以下の部分のチェックをつけます。

f:id:kazuhironagai77:20210919234525p:plain

f:id:kazuhironagai77:20210919234532p:plain

Back Start Buttonがクリックされた時もOpen Levelが呼ばれていたのでそこも直しました。

f:id:kazuhironagai77:20210919234603p:plain

<Landscape 4

これは魔物と戦闘になるときですね。

f:id:kazuhironagai77:20210919234629p:plain

取りあえず「赤い帽子の魔女からの手紙」のLoading Screenを表示しておきます。

f:id:kazuhironagai77:20210919234648p:plain

<Battle Field

これは何かのテストのために作成して忘れてしまったヤツですね。

f:id:kazuhironagai77:20210919234742p:plain

消します。

<Inn

宿屋のLevelです。

f:id:kazuhironagai77:20210919234836p:plain

宿屋も作り直す必要がありますね。今はこのままにしておいて「赤い帽子の魔女からの手紙」のLoading Screenを表示する所だけ直しておきます。

f:id:kazuhironagai77:20210919234930p:plain

<Map1

f:id:kazuhironagai77:20210919235003p:plain

これも戦闘画面に移動する時ですね。

f:id:kazuhironagai77:20210919235036p:plain

「赤い帽子の魔女からの手紙」のLoading Screenを表示するようにしました。

<Map1_Test>

f:id:kazuhironagai77:20210919235121p:plain

Map1と全く同じです。

これで全部終りな訳ありません。

Game Mode BPを開いてもう一回、Open Level ノードを検索します。

今度はこれだけ表示されました。

これって全部のBPを一辺に調べる検索方法はないんでしょうか?

必ず漏れが生まれてしまうと思います。

最後のUWSは水のサンプルのMapなので無視していいですが、残りは全部チェックする必要があります。

f:id:kazuhironagai77:20210919235209p:plain

RPG Game Instance BP

遥か昔に作成した地図を使用して別なMapにワープする機能です。

これは勿体ないのでどこかで使用出来るようにします。

今は「銀河鉄道のLoading Screen」を入れておきます。

f:id:kazuhironagai77:20210919235336p:plain

RPG Game Mode BP

これは戦闘が終わって元のMapに戻る時ですね。

f:id:kazuhironagai77:20210919235624p:plain

「赤い帽子の魔女からの手紙」のLoading Screenを表示します。

f:id:kazuhironagai77:20210919235643p:plain

これは墜落した時のLoadingです。

f:id:kazuhironagai77:20210919235704p:plain

これ専用のLoadingが必要ですね。取りあえず「赤い帽子の魔女からの手紙」のLoading Screenを表示します。

f:id:kazuhironagai77:20210919235721p:plain

<Get Item Widget

これは戦闘が終了してかつ石像が褒美をくれた後に元のLevelに戻る時に使用するやつです。

f:id:kazuhironagai77:20210919235748p:plain

取りあえず「赤い帽子の魔女からの手紙」のLoading Screenを表示します。

<W_WarpGate Widget

はい。やっと出て来ました。銀河鉄道の駅のWidgetです。

f:id:kazuhironagai77:20210919235818p:plain

銀河鉄道のLoading Screen」を表示します。

<Game Over Screen Widget

Re-Start Button を押した時です。

f:id:kazuhironagai77:20210919235927p:plain

「赤い帽子の魔女からの手紙」のLoading Screenを表示します。

こっちはスタート画面に戻る時のEventです。

f:id:kazuhironagai77:20210919235945p:plain

「赤い帽子の魔女からの手紙」のLoading Screenを表示します。

こっちはスタート画面に戻る時のEventです。

f:id:kazuhironagai77:20210920000016p:plain

<Start Menu Widget

使用してないのが残っていました。

f:id:kazuhironagai77:20210920000134p:plain

消します。

Load Buttonがクリックされた時です。

f:id:kazuhironagai77:20210920000151p:plain

これは「銀河鉄道のLoading Screen」を表示します。

Talk with Witch Widget

f:id:kazuhironagai77:20210920000216p:plain

ゲーム開始最初の場面ですね。

銀河鉄道のLoading Screen」を表示します。

<Game Over Screen Falling Widget

Game Over してRe-Startした時です。

f:id:kazuhironagai77:20210920000238p:plain

オカシイ。これは前に直したはず。

f:id:kazuhironagai77:20210920000256p:plain

こっちは直っていました。

残りは全部直っていました。

テストします。

戦闘画面です。

f:id:kazuhironagai77:20210920000313p:plain

戦闘から戻る時です。

f:id:kazuhironagai77:20210920000331p:plain

あれ。Monsterが動いていない。

f:id:kazuhironagai77:20210920000411p:plain

あ。Level BPを別なLevelから開いたときは新たにそれぞれのLevelを開いてBuildをし直す必要がありました。

まあ、テストが終わってからやります。

銀河鉄道に乗りました。

f:id:kazuhironagai77:20210920000444p:plain

銀河鉄道が表示されています。

今度は戦闘に負けてみました。

f:id:kazuhironagai77:20210920000514p:plain

今度は崖から落ちてみました。

f:id:kazuhironagai77:20210920000553p:plain

崖から落ちた時のLoading Screenは別なのが必要ですね。

最後に宿屋に泊まった時のテストをします。

何も表示されません。

あれ?

今週も時間が無くなってしまったのでここで中止です。

宿屋は来週検討します。

6.4 Async Loading ScreenがどうやってOpen Levelノードが呼ばれるたびに呼ばれるようになっているのかを調べる

これを調査するのが今週のLoad Screenの勉強目的だったんですが、時間が無くなってしまいました。これも来週に回します。

6.Good Skyの復習

これもまた来週以降になってしまいましたね。

7.まとめと感想

Niagara SystemはCGHOW氏のTutorialで勉強をする事は取りあえず継続する事になりました。

  • Dither Temporal AAノード
  • Distance To Nearest Surfaceノード
  • Lerp Particle Attribute Module

などについて勉強しました。

Static Mesh Sampling in UE5 Niagara Tutorial [13]を参考にしながらContent ExamplesにあるサンプルのStatic Mesh Samplingについて勉強しました。ここに使用されたModuleやNodeについては来週、改めて復習します。

Cascadeの勉強は中止してMaterialの勉強をする事にしました。

Map1の作成では、今週は特にNPCの修正をやりました。一番大変だったのがセリフの修正で、ある人が300前の大戦争でと言って、別な人は5000年前の大戦争といっています。こういう統一性が全くない会話になってしまうのは年表が出来てないからなのかと思いつつ年表を作成する気は起きないです。

NPCは今の所、歩いたりはしませんが、NPC用のAIを作成すればMonsterのように歩いたり、Playerの操作するキャラに向かって走ってきたりする事は出来ます。NPC用のAIを作成するか、それとも年表を作成するか。この辺の検討も必要かもしれません。

後、Map1をStream Levelに分割する事も検討します。せっかくSeamlessなmapの読み込み方法を勉強したんだから積極的に活用していきます。

地面の色がくっきり変わってします箇所があります。その部分は絶対直したいですが、直し方が分かりません。

Light Mass Importance Volumeは出来るだけ使用しない事にしました。影が濃いほうが中世的な雰囲気が出るからです。

Post Processは後でキッチリと勉強します。

Loading Screenの勉強に関してはUE4.24 にAsync Loading Screen plug-inを追加して、Ch4_3にLoading Screenを作成しました。Ch4_3で使用した全てのOpen LevelにSet Display Background IndexノードとSet Display Tip Text Indexノードを追加しました。これでそれぞれのLoading Screenで指定した絵とセリフが表示されるはずです。

ただし、Loading ScreenのFormatは全部同じものしか選択出来ません。この辺も選択出来る様になるともっと便利になる気がします。

Async Loading Screen plug-inのコードは公開されているので自分で改良してみたいです。

今回、結構、時間を取られたのがNPCのセリフの作成とLoading Screenの絵の作成です。こういうのはどんどん分業した方が良いと思います。Gameを作成するためのProgrammingは世間一般の評価とは裏腹に、実際にやってみると英語とProgramming Skillは当然として結構深い数学や物理の知識が要求されます。

英語とC++のProgrammingが当然のように出来て、大学Levelの数学と物理をきちんと理解してる人と文章が書ける人や絵が描ける人の数を比較したら1:50:5000ぐらいにはなるでしょう。

ゲーム制作出来るProgrammerはそれ自体が激レアキャラです。

彼らにあえて文章を書いたり、絵を描く事をProgrammerに強制するのは無駄な気がします。

そう考えるとNPC用のAIを作成するか、それとも年表を作成するか。の選択で年表を作成する気力は沸いてこないですね。

<参照(Reference)

[1] Leswing, K. (2021, September 10). Apple can no longer force developers to use in-app purchasing, judge rules in Epic Games case. CNBC. https://www.cnbc.com/2021/09/10/epic-games-v-apple-judge-reaches-decision-.html

[2] Hoeg Law. (2021, September 11). Epic v Apple: Judgment Day - Who Won? Who Lost? . . .and Why? (VL538) [Video]. YouTube. https://www.youtube.com/watch?v=43CMV8KIs3E

[3] Yea, Y. [Yong Yea]. (2021, September 11). Both Epic & Apple Lose Big After Court Rules On Their Legal Battle [Video]. YouTube. https://www.youtube.com/watch?v=sCyF4Uf7Lco

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

[5] Epic Games. (n.d.-b). Niagara Script Editor Reference. Unreal Engine Documentation. Retrieved September 19, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Niagara/ScriptEditorReference/

[6] PrismaticaDev. (2021, April 5). Dither Temporal AA Node | 5-Minute Materials [UE4] [Video]. YouTube. https://www.youtube.com/watch?v=kvHh0Jd-D3Q

[7] Epic Games. (n.d.-c). Utility Expressions. Unreal Engine Documentation. Retrieved September 19, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Materials/ExpressionReference/Utility/

[8] Epic Games. (n.d.-a). Mesh Distance Fields. Unreal Engine Documentation. Retrieved September 19, 2021, from https://docs.unrealengine.com/4.27/en-US/BuildingWorlds/LightingAndShadows/MeshDistanceFields/

[9] Nilsson, M. (n.d.). LearningUnrealEngine/Inside Unreal - Advanced Niagara Effects.md at master · ibbles/LearningUnrealEngine. GitHub. Retrieved September 19, 2021, from https://github.com/ibbles/LearningUnrealEngine/blob/master/Inside%20Unreal%20-%20Advanced%20Niagara%20Effects.md

[10] Hoeg Law. (2020, August 17). Epic’s CEO Just Called Me Out: A Response (VL289) [Video]. YouTube. https://www.youtube.com/watch?v=OQkD9kIgHkQ&t=438s

[11] Cloward, B. [Ben Cloward]. (2010, July 6). Ben Cloward [Video]. YouTube. https://www.youtube.com/user/bcloward/playlists

[12] Kupser, K. (n.d.). Kurt Kupser. ArtStation. Retrieved September 19, 2021, from https://www.artstation.com/learning/instructors/Kurt-Kupser

[13] CGHOW. (2021, August 26). Static Mesh Sampling in UE5 Niagara Tutorial | Download Files [Video]. YouTube. https://www.youtube.com/watch?v=9MJ8YtEs5as

[14] Cloward, B. (n.d.-c). Shader Graph Basics. YouTube. Retrieved September 19, 2021, from https://www.youtube.com/playlist?list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl

[15] Cloward, B. (n.d.-d). UE4 Material Editor - Shader Creation. YouTube. Retrieved September 19, 2021, from https://www.youtube.com/playlist?list=PL78XDi0TS4lFlOVKsNC6LR4sCQhetKJqs

[16] Cloward, B. (n.d.-b). Rain Materials in Unreal Engine 4. YouTube. Retrieved September 19, 2021, from https://www.youtube.com/playlist?list=PL78XDi0TS4lHpIHseomZCPRm_NkyUMkPs

[17] Cloward, B. (n.d.-a). Procedural Noise Materials in Unreal Engine 4. YouTube. Retrieved September 19, 2021, from https://www.youtube.com/playlist?list=PL78XDi0TS4lE7kpna273_SUl2e0PXYZRY

[18] Cloward, B. (n.d.-e). UE4 Water Material Tutorial. YouTube. Retrieved September 19, 2021, from https://www.youtube.com/playlist?list=PL78XDi0TS4lGXKflD2Z5aY2sLuIln6-sD

[19] Cloward, B. [Ben Cloward]. (2021, June 10). Announcing What’s Next! - Shader Graph Basics - Episode 1 [Video]. YouTube. https://www.youtube.com/watch?v=OX_6_bKpP9g&list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl&index=1

[20] Cloward, B. [Ben Cloward]. (2021b, June 17). The Graphics Pipeline - Shader Graph Basics - Episode 2 [Video]. YouTube. https://www.youtube.com/watch?v=ZEXVQgbWxQY&list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl&index=2

[21] Wadstein, M. [Mathew Wadstein]. (2015, December 10). WTF Is? Volume - Lightmass Importance in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=2LEuPveQfWg

[22] Sensei, U. [Unreal Sensei]. (2021, January 15). How to Make Unreal Engine 4 Render Lighting Faster! - UE4 GPU Lightmass Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=H3PEVnRGA4s

[23] Bui, T. (n.d.). GitHub - truong-bui/AsyncLoadingScreen. GitHub. Retrieved September 19, 2021, from https://github.com/truong-bui/AsyncLoadingScreen

[24] オオタカハシ. (n.d.). 4ステップで描く! 星空の描き方メイキング. いちあっぷゼミ. Retrieved September 19, 2021, from https://ichi-up.net/2017/099

[25] いらすとや. (n.d.). いろいろな色の電車のイラスト. Retrieved September 17, 2021, from https://www.irasutoya.com/2016/03/blog-post_625.html







































「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 最初のmapの作成

f:id:kazuhironagai77:20210912211148p:plain

<前文>

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

<言霊信仰はアメリカにもある>

井沢元彦の逆説の日本史に出て来る言霊思想は、日本の文化を語る上で外せない重要な要素です。

簡単に言霊思想を説明すると、言葉には霊力がこもっていて声に出すとその霊力によって声に出した事が現実になる。と言う思想です。

この思想は科学的な根拠がないにも関わらず、日本のあちこちで、特に悪い意味で信仰されていてます。

例えば受験生の前では「スベル」とか「落ちる」、結婚式では「切る」「離れる」「分かれる」と言う言葉は使ってはならない。となっています。

後、病院では4の数字の病室がなかったりとかもあります。

これ、日本だけの文化と思っている日本人が多いですが、アメリカにもあります。多分ですがヨーロッパにもあります。

欧米では「Go* Damn you!」、「Oh my Go*」そしてもっとも良く聞く「Jesu*!」のような宗教関連の言葉が言霊化しているんです。

これキリスト教の人に言わせると、神の名を軽々しく呼ぶのはいけないから。と説明します。しかしそれはキリスト教を信じる人にとっての戒律で、キリスト教を信じない人には関係ない話です。しかし欧米人は色々な屁理屈をこねて日本人である私にもそういう言葉を使うなと強要して来ます。

最初、私はキリスト教原理主義を全ての人に強制するナチス的な思想の現れなのかと思ったんですが、そうじゃなかったんです。

彼らも言霊を信仰していたんです。

そういう言葉をお前が口に出すと、俺が呪われるから、絶対に言うな。と言うのが彼らの本音だったんです。

西洋人が4の数字に日本人が感じるような畏怖は感じませんが「Go*  Damn you!」には日本人が4の数字に感じるような畏怖を感じるんです。言霊の信仰する対象が違うだけで言霊思想はあるんです。

はい。

外国人が日本の結婚式に参加して「切る」「離れる」「分かれる」なんて言葉を使用したら普通の日本人なら気分悪いですよね。

もし日本人がアメリカで「Go* Damn you!」、「Oh my Go*」そしてもっとも良く聞く「Jesu*!」をTPOをわきまえずに使用したらアメリカ人も気分が悪くなります。

あなたがアメリカ人から常識があり、友人として付き合うのに相応しい相手と思われたいなら「Go* Damn you!」、「Oh my Go*」そしてもっとも良く聞く「Jesu*!」のような言葉は、空気を読んで言っても大丈夫な時だけ使用する事にしましょう。もしその微妙な空気が読めないなら、100%そういう言葉を使用しないのも一つの手ではあります。

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

<本文>

1.今週の予定

先週はやりたい事が多すぎて予定の時間を大幅にOverしても終わらなくて泣く泣く途中で止める羽目になってしまいました。

今週は先週終わらなかった個所をやっていきます。

  • Particle Systemの勉強
  • RPGの作成
    • Map1の作成
    • Loading Screenの勉強の続き
    • Good Skyの復習

2.Building advanced effects in Niagara | Unreal Engine [1]の勉強の続き

先週はSpriteを丸くする所までやったんでした。

それでは続きを始めます。とやると本質を見失ってしまいます。

先週、このTutorialを勉強し始めた理由は、これからNiagaraを勉強するに当たってCGHOW氏のTutorialとどれくらい真剣に向き合うべきなのかを決めるためでした。この結論を出すためには

  • 目的は?
  • 出来なかった事は?
  • 学んだ事は?
  • 目的は達成出来たのか?
  • Tutorial通りに作れたのか?
  • このTutorialの改善点について

についての考察が必ず必要になります。この辺をしっかりと認識しながら続きをやっていきます。

2.1 先週までの総括

先週やった範囲で上記の項目に対してどの程度の解答が得られたのかをまとめておきます。

<目的>

先週のBlogを見直すとこのTutorialを勉強する目的は「CGHOW氏のTutorialとの違いを見極める事」と書いてありました。

CGHOW氏のTutorialの作成したEffectは素晴らしいです。しかしそのTutorialはあまり生徒思いに作られておらず、勉強したからと言って理解出来るとは限りません。というか逆に訳わからなくなる可能性が高いです。

分かり易く言うと、CGHOW氏のTutorialは崖っぷちに落ちているダイヤモンドなんです。

ダイヤを拾えて返ってこれればこれ以上ない利益を得られるんですが、逆に崖に落ちたら死にます。そういうリスクがあるTutorialなんです。

ここで、ダイヤは拾えんかったけど、生きて帰っては来れた。と言う時はどう評価すべきかが今回、私が見極めたい所なんです。そのための比較対象としてEpic Games社が提供する今回のTutorialをやっている訳です。

Building advanced effects in Niagara | Unreal Engine [1] はEpic Games社が提供しているTutorialで、本当に生徒の立場に立って親切丁寧に作成されたTutorialです。

例えば、このTutorialで勉強しても目的のEffectが使えるようにならなかったら、その理由を徹底的に解明する必要があります。

その結果「UE4のVersionは同じにしないと駄目だ。」という結果が得られたらCGHOW氏のTutorialでもUEのVersionを同じにしてから勉強する事でダイヤモンドが手に入れられる可能性が高くなります。

処が、Materialの作成方法が良く分からないから同じEffectが作成出来なかったとなった場合は、一端、Effectの勉強は停止して今度はMaterialの勉強に移った方が良いと判断出来ます。

ここでですね。

Building advanced effects in Niagara | Unreal Engine [1] は完璧にEffectを再現出来たけど、CGHOW氏のTutorialは勉強しても全然同じものが作れない。となった時にどう判断すべきなのかが決まっていないんです。

その辺を見極めるのが今回の真の目的になると思います。

そして今回の小さい目的はBuilding advanced effects in Niagara | Unreal Engine [1]のEffectを完璧に再現する事です。

<出来なかった事は?>

先週の時点で、出来なかった事が既にあります。それらをまとめておきます。

<<サイズの全く違うParticleが生成される>>

Particle Spawn SectionにSphere Location Moduleを使用すると以下の様にTutorialのParticle のサイズとは全く違うサイズのParticleが生成されます。

f:id:kazuhironagai77:20210912211344p:plain

Particle Spawn Sectionに作成されているInitialize Particle Moduleの値を変更すれば同じに形状になるので、これは大した問題ではないと考えられています。

<<使用しているMaterialが違う>>

Tutorialで使用しているキャラであるCrunch

f:id:kazuhironagai77:20210912211406p:plain

現在のVersionではmaterialの設定がTutorialの時とは全く違っています。

f:id:kazuhironagai77:20210912211422p:plain

それで我流で直したんですが、

f:id:kazuhironagai77:20210912211437p:plain

こんな感じでTutorialのイメージとは結構違っています。この部分は全く出来ていません。しかしそれが最終的な結果にあんまり影響はない気もしています。

<学んだ事は?>

これは先週、全く考えていませんでした。兎に角、早く終わらせないとだけ思って何を学んだのかについては覚えていません。どんな新しいModuleを使用したのかとか、そのModuleの機能とか全く覚えていません。Blogを見直してみます。

  • Vortex Force ModuleやGravity Force ModuleをParticle Spawn Sectionにセットした場合とParticle Update Sectionにセットした場合の違いについて
  • Color ModuleのSimulation Position(Color ModuleのParameterの一つに使用)
  • Light RendererのUse Inverse Squared Falloff
  • 何でGPUによるSpriteの時はEmitterの境界を指定しないといけないのか
  • Initialize Mesh Reproduction Sprite Moduleについて
  • Update Mesh Reproduction Sprite Moduleについて
  • Materialの改良によるParticleの色付けについて
  • Spriteが常にカメラを向いている事を直すのに、Sprite Renderer ModuleのAlignmentとFacing Modeの値を以下の様に変更した事

f:id:kazuhironagai77:20210912211521p:plain

  • Spriteを丸くするために、以下のコードを実装した事。

f:id:kazuhironagai77:20210912211548p:plain

  • 更に色を表示するためにInitialize Particle ModuleのColor を黒にした事

これらの新しい事を学びました。

学んだんですが、これらが何故、このような結果を作り出すのかについては全く分かっていません。それは次の節で調べる事にします。

<目的は達成出来たのか?>

<Tutorial通りに作れたのか?>

<このTutorialの改善点について>

これらについてはTutorialが全部終わってからじゃないと出来ないのでそれからやります。

2.2 先週、新しく使用したModuleや機能についての調査や考察

この勉強を忘れていたのでこれをまずやります。

<Vortex Force ModuleやGravity Force ModuleをParticle Spawn Sectionにセットした場合とParticle Update Sectionにセットした場合の違いについて>

これは、ForceをParticle Spawn Sectionにセットした場合とParticle Update Sectionにセットした場合の違いについての考察で、先週もそれなりには、やっています。

f:id:kazuhironagai77:20210912211641p:plain

今回はGravity Force Moduleのみで検討してみます。

以下のEmitterを作成しました。

f:id:kazuhironagai77:20210912211656p:plain

ParticleにかかっているForceはParticle Update SectionにあるGravity Force Moduleのみです。

f:id:kazuhironagai77:20210912211711p:plain

見事に等加速度直線運動を行っています。

今度はGravity Force ModuleをParticle Spawn Sectionにセットしました。

Apply Initial Force Moduleが強制的に追加されました。

f:id:kazuhironagai77:20210912211726p:plain

Apply Initial Force ModuleはSolve Initial Force Moduleと同じような働きをするModuleなんでしょうか?

Apply Initial Force Moduleについては後で調べます。

結果です。

f:id:kazuhironagai77:20210912211743p:plain

今度は等速直線運動をしています。

はい。

ForceをParticle Spawn Sectionにセットした場合とParticle Update Sectionにセットした場合の違いについて完全に理解しました。

ForceをParticle Spawn Sectionにセットした場合は初速度になります。ForceをParticle Update Sectionにセットした場合、加速度になります。

Force Moduleは、やっぱりForceと言う名前とは裏腹に速度を追加しているModuleのようです。

Particle Update SectionにセットされたModuleは毎秒呼び出されます。Force Moduleも毎秒呼び出されるのでそのたびにParticleに指定された速度を追加します。その結果、加速度の値を表しているのと同じになります。

この後で、Force Moduleについての解説はないのか探したらありました。CGHOW氏のAll Forces Modules in UE4 Niagara Explained [2] です。

このTutorialは少しだけ見ましたが、かなり詳しくForce Moduleの実際の使用方法について説明していて分かり易かったです。

うーん。

やっぱりCGHOW氏のTutorialは崖にあるダイヤモンドです。無事にダイヤを取って来る事が出来ればこの上ない価値があります。

<Color ModuleのSimulation Position(Color ModuleのParameterの一つに使用)>

Edit ValueからSimulation Positionを検索するとDynamic Inputsに分類されている事が分かります。

f:id:kazuhironagai77:20210912211811p:plain

私はSimulation Position以前にこのModuleのParameterにセット出来るEdit Value自体の意味が良く分かってないんです。

f:id:kazuhironagai77:20210912211825p:plain

今回はこのEdit Valueについて調べる事にします。

中々、直で説明している解説が見つかりません。

ちょっとカスっているのか分かりませんが、公式のDocumentであるNiagara Overview [3] に以下の説明がありました。

f:id:kazuhironagai77:20210912211840p:plain

うーん。よく分からない。

gameDev Outpost 氏のTutorialにUE4 - Niagara Dynamic Inputs [4] がありました。

ぱっと見たのですが、まずModule内のParameterをVariableつまり変数と呼んでいました。

f:id:kazuhironagai77:20210912211908p:plain

これは言われてみれば当たり前ですが、何故か変数と言う言葉が出て来ませんでした。何故かと言うとその変数に値をパスしている訳で、その値をパスする行為が関数のParameterに当たっているからです。

それでピンと来ました。変数にEditorから値をパスする場合をDynamic Inputsと呼んでいるじゃないのかと。

ならば変数の値を上のModuleで使用した変数からPassする事も出来るはずです。

それがLink Inputなんじゃないでしょうか?

f:id:kazuhironagai77:20210912211923p:plain

因みにParticle Update SectionにあるColor ModuleのDistanceのLink InputのParticleを開いて見ると以下の様になっています。

f:id:kazuhironagai77:20210912211939p:plain

ここに表示されているParticle AttributeをParameterの方で見ると

f:id:kazuhironagai77:20210912211954p:plain

Float型のAttributeはSprite Rotation以外全て表示されています。変数、DistanceはFloat型なのでこれは納得です。

次のMakeは何なんでしょう?

f:id:kazuhironagai77:20210912212010p:plain

これは多分ですが、新しいAttributeをEmitterやParticleに作成してそのParticle の値を読むんじゃないでしょうか?

まあはっきり言えば分かりません。

最後の3つですが、New Scratch Dynamic Inputは意味が分かります。

f:id:kazuhironagai77:20210912212027p:plain

Dynamic Inputsを自作するためのものでしょう。

あ。

先週、勉強したこれですわ。

f:id:kazuhironagai77:20210912212045p:plain

f:id:kazuhironagai77:20210912212051p:plain

成程、Dynamic Inputsも自作出来るわけですね。

Local Valueは何なんでしょうね。このModule 内でしか使用出来ない変数なんでしょうか?

f:id:kazuhironagai77:20210912212109p:plain

適当なModuleを開いてNodeを見るとLocal Sphere Vectorと言う変数がありました。多分このTypeを作成するんでしょう。

最後のNew Expressionの意味は分かりません。

f:id:kazuhironagai77:20210912212124p:plain

ExpressionってC++の用語でしたっけ。覚えていません。

調べたらありました。Cppreference.comのExpressions [5] に詳しい解説がありました。

f:id:kazuhironagai77:20210912212140p:plain

この解説を読むと、例えば=(x+2)の様な計算とか、Printf(x)のような関数など、OperatorとOperandsがあってその指定に基づいて何かしらのComputationをすればそれはExpressionになるそうです。

多分、これを作成するんでしょう。

でもそうするとDynamic Inputsと同じになってしまいますよね。これもまだちょっと分かりませんね。

こんだけ理解出来れば、Simulation Positionの意味ももっとよく分かりますね。

もう一回調べて見ます。

Simulation PositionのNiagara Dynamic Inputs Scriptを開くと以下の様になっていました。

f:id:kazuhironagai77:20210912212157p:plain

おお。全く先週の説明文に合った通りの機能が実装されています。

Local Spaceにセットされている場合は0を返して、それ以外はPositionを返します。

Emitter PropertiesのLocal Spaceを見るとチェックされていませんでした。

f:id:kazuhironagai77:20210912212234p:plain

と言う事は、Engine Owner の変数であるPositionの値が返されていますね。

となると先週考えた通り、やっぱりこのDynamic InputsはEmitterの中心を返していると考えられますね。だって対になるStart positionにセットされているのがParticleのPositionなんですから。

最後に、最初に意味が分からないと言ったNiagara Overview [3] にある以下の説明についてもう一回考察します。

f:id:kazuhironagai77:20210912212251p:plain

<<Dynamic inputs are built the same way modules are built.>>

はい。これはもう言っている意味は明白です。

ModuleがModule Scriptで実装出来る様に

f:id:kazuhironagai77:20210912212312p:plain

Dynamic InputsもDynamic Input Scriptで実装できます。

f:id:kazuhironagai77:20210912212325p:plain

<<Dynamic inputs give users infinite extensibility for inheritance.>>

これは、抽象的な意味で言っているなら分かりますが、何かの機能を具体的に指して言っているとするとそれは分かりません。

<<Instead of acting on a parameter map, dynamic inputs act on a value type.>>

多分ですが、Parameter MapはModuleの事を指していると思われます。そこだけはちょっと曖昧です。

Value Typeは勿論、変数の型の事です。Dynamic inputsは常にある変数のTypeの値を返すと解釈出来ます。

f:id:kazuhironagai77:20210912212403p:plain

この例では、Curve IndexにDynamic InputであるNormalize Distance Rangeが使用されています。Normalize Distance RangeはStart Position とEnd Positionを指定する必要があります。このEnd Positionにもう一回Dynamic InputであるSimulation Positionを指定しています。

<Light RendererのUse Inverse Squared Falloff

Rendererは開けないし、先週まとめた以上の情報は入りそうにないです。

f:id:kazuhironagai77:20210912212426p:plain

と思ったら公式のDocumentにInverse Square Falloff [6] がありました。

f:id:kazuhironagai77:20210912212441p:plain

この解説を読むと実際の光の減衰と同じ公式を使用して計算しているようです。

<何でGPUによるSpriteの時はEmitterの境界を指定しないといけないのか>

これは先週調べました。

<Initialize Mesh Reproduction Sprite Moduleについて>

これは先週調べた以上の情報は分からなかったです。しかし公式のDocumentであるParticle Spawn Group [7]のUpdate Mesh Reproduction Sprite Moduleの項目にこのModuleの解説が書かれていたので、それについて<Update Mesh Reproduction Sprite Moduleについて>で解説します。

<Update Mesh Reproduction Sprite Moduleについて>

公式のDocumentであるParticle Spawn Group [7]のUpdate Mesh Reproduction Sprite Moduleの解説です。

f:id:kazuhironagai77:20210912212510p:plain

1と2は分かりますがそれ以外の意味は分かりません。

それよりもContent Examplesに例があると書かれています。こちらを確認してみます。

ありました。

Niagara Advanced の1.5です。

f:id:kazuhironagai77:20210912212528p:plain

中を開いて見ると

f:id:kazuhironagai77:20210912212543p:plain

Update Mesh Reproduction Sprite Moduleはありません。

f:id:kazuhironagai77:20210912212557p:plain

多分ですが、この辺のヤツが同じ働きをしているんでしょう。

f:id:kazuhironagai77:20210912212612p:plain

この二つのModuleは今の私の手に負えるものじゃないです。

今回はここまでとします。

<Materialの改良によるParticleの色付けについて>

私のVersionのCrunchのMaterialはいかのように7種類使用しています。

f:id:kazuhironagai77:20210912212633p:plain

先週、勉強したBuilding advanced effects in Niagara | Unreal Engine [1]では使用しているMaterialは一個でした。

それで、頭の部分だけ担当しているMaterial InstanceであるMIC_Crunch_Headを

f:id:kazuhironagai77:20210912212702p:plain

先週作成したM_Crunch_Parent_Niagaraを元に作成して

f:id:kazuhironagai77:20210912212716p:plain

Sprite RendererのMaterialにセットしたら

f:id:kazuhironagai77:20210912212730p:plain

頭の部分だけは綺麗に表示されるのでは?

と思い試してみました。

f:id:kazuhironagai77:20210912212747p:plain

駄目でした。

やっぱりMaterialはちょっと深くなるともう分からなくなります。

<Spriteが常にカメラを向いている事を直すのに、Sprite Renderer ModuleのAlignmentとFacing Modeの値を以下に示した値に変更した事>

f:id:kazuhironagai77:20210912212811p:plain

ここでTutorialより以下の説明がありました。

f:id:kazuhironagai77:20210912212825p:plain

この部分の意味だけは今なら分かるようになりました。

Update Mesh Reproduction Sprite Moduleで全てのMeshのNormal Vectorを計算しているはずです。その値をそのまま利用してFacing ModeでVectorに沿って整列させている訳です。

<Spriteを丸くするために何をしたのか>

この部分です。

f:id:kazuhironagai77:20210912212848p:plain

この中で意味が分からないのはDither Temporal AAだけです。

まあでも、丸くはなるでしょう。

<更に色を表示するためにInitialize Particle ModuleのColor を黒にした事>

f:id:kazuhironagai77:20210912212909p:plain

上記の図にあるParticleの値が

f:id:kazuhironagai77:20210912212923p:plain

に繋がっているからでしょう。

2.3 Building advanced effects in Niagara | Unreal Engine [1]の勉強の続き

CrunchがObjectに触ったらCrunchのMaterialが消えるようにします。

壁にぶつかったりするそうなので、Third Person CharacterのMeshをCrunchに変更しました。

f:id:kazuhironagai77:20210912212943p:plain

f:id:kazuhironagai77:20210912212950p:plain

Distance To Nearest Surfaceノードを使用するそうです。

f:id:kazuhironagai77:20210912213005p:plain

使用する箇所がCrunchのMaterial、つまりM_Crunch_Parentになります。

f:id:kazuhironagai77:20210912213020p:plain

ちょっとそのまま使用しただけでは出来ないかもしれませんね。

次にDistance To Nearest Surfaceノードを使用するためにProject SettingのRenderingのLightingにあるGenerate Mesh Distance Fieldsにチェックを入れます。

f:id:kazuhironagai77:20210912213036p:plain

Tutorialによると今度は以下の事を実装するそうです。

まず表面からの距離によってFadeさせます。次にFadeする前に黒いBandを生成します。

良く意味が分かりません。

そしたらこんな説明をしていました。

壁とCrunchの距離が50cmあるとします。そして30cmのbandと20cmのFadeが欲しかったら、50cmから30cmを引いて20cmで割ればいいだけです。

うーん。何を言っているんでしょうか?

全然分からない。

取りあえず先に進んでから考える事にします。やり方は見れば分かるので完成した状態から逆算して何が言いたかったのかを推測する事にします。

以下の実装をしました。

f:id:kazuhironagai77:20210912213051p:plain

うん。20を引いて30で割っていますね。

もう一回見直しましたが、やっぱり50cmから30cmを引いて20cmで割れと言っています。

まあ、先に進みます。

f:id:kazuhironagai77:20210912213108p:plain

今度はこれをOpacity Maskに接続します。

以下のようにして繋ぎました。

f:id:kazuhironagai77:20210912213121p:plain

更にMaterialのBlend ModeをMaskedに変更します。

f:id:kazuhironagai77:20210912213204p:plain

Imageが消えてしまいました。

f:id:kazuhironagai77:20210912213219p:plain

Tutorialではこれでテストしています。

f:id:kazuhironagai77:20210912213234p:plain

私も自分のを試してみました。

f:id:kazuhironagai77:20210912213249p:plain

おお。

Crunchの足にガラス玉が当たっていますが、足がFadeしています。

理由は良く分からないけど出来ていますね。

だけどこのやり方だと足首から下は常に消えてしまいますね。

今度は、このCrunchの表面に発生したParticleをバラバラにするそうです。

それをするためには、NS_DissolveEffectのそれぞれのParticle にバラバラに動く物理をBlendする必要があるそうです。更に、そのためには、現在どのくらいの量のParticle がDissolveしてるのかを記録するための変数が必要になるそうです。

うーん。

もう付いていけません。

言われた通りにやるだけです。

f:id:kazuhironagai77:20210912213312p:plain

Scratch Pat Moduleを作成しました。

名前をGet Level Of Dissolveに変更しました。

f:id:kazuhironagai77:20210912213327p:plain

この名前の変更方法は単にクリックするだけです、選択画面には名前を変更するはありません。

今度は表面からの距離を測ります。

それはNew Collision Queryを使用する事で可能だそうです。

f:id:kazuhironagai77:20210912213341p:plain

もう全然分かりません。

f:id:kazuhironagai77:20210912213446p:plain

そこにQuery Mesh Distance Field GPUを繋げます。

今度はVectorを追加して名前をSample Positionに変更しました。

f:id:kazuhironagai77:20210912213508p:plain

そして以下の赤で囲った部分の値を変更しました。

f:id:kazuhironagai77:20210912213523p:plain

こうする事でSample PositionのDefault値はParticleのPositionになるのでしょうか?

f:id:kazuhironagai77:20210912213538p:plain

あ。分かりました。これで表面とParticleの距離が判明したんです。

すると次にやる事は

f:id:kazuhironagai77:20210912213552p:plain

これです。

引き算して割り算です。

f:id:kazuhironagai77:20210912213605p:plain

引き算する値を追加します。Floatで作成してBiasと名付けました。

f:id:kazuhironagai77:20210912213618p:plain

更に割り算用の値も追加しました。

f:id:kazuhironagai77:20210912213632p:plain

値が0と1の間になるようにします。Scratch Pat ModuleにはSaturate ノードが無いからかClampを使用しています。

f:id:kazuhironagai77:20210912213858p:plain

今度は値を逆にするためにOne Minisノードを追加します。

f:id:kazuhironagai77:20210912213912p:plain

Out put用のfloat、Dissolve Amountを作成します。

f:id:kazuhironagai77:20210912213957p:plain

今度はName SpaceをLocalからOUTPUTに変更します。

f:id:kazuhironagai77:20210912214032p:plain

変更したらOUTPUTにMODULEも勝手に追加されました。

こんな機能があるなんて初めて知りました。

f:id:kazuhironagai77:20210912214047p:plain

この色付きの名前はName Spaceだったんですね。

後で詳しく勉強しましょう。

最後にApplyボタンを押してこのModuleを作成します。

f:id:kazuhironagai77:20210912214102p:plain

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

f:id:kazuhironagai77:20210912214116p:plain

Get Level Of Dissolve Moduleに値を追加します。

f:id:kazuhironagai77:20210912214129p:plain

これで後はこの値をBlendすれば終わりです。

まず最初に

f:id:kazuhironagai77:20210912214143p:plain

のWrite to Intrinsic Properのチェックを外します。

f:id:kazuhironagai77:20210912214158p:plain

この理由は、Solve Forces and Velocity ノードの後にUpdate Mesh Reproduction Sprite Moduleがあると

f:id:kazuhironagai77:20210912214213p:plain

Solve Forces and Velocity ノードの情報はUpdate Mesh Reproduction Sprite Moduleに上書きされてしまいます。

それを外すためにWrite to Intrinsic Properのチェックを外します。

次にLerp Particle Attribute Moduleを追加します。

f:id:kazuhironagai77:20210912214237p:plain

次にLerp Positionの値を以下の様にセットしました。

f:id:kazuhironagai77:20210912214254p:plain

何でこの値で良いのかは分かりません。一回復習しますのでその時に考えます。

今度はVelocityの値を指定します。

f:id:kazuhironagai77:20210912214315p:plain

何でこの値を選択したのかは後で考えます。

最後にVortex Velocityを追加します。

f:id:kazuhironagai77:20210912214348p:plain

f:id:kazuhironagai77:20210912214353p:plain

これで完成だそうです。

テストしてみます。

f:id:kazuhironagai77:20210912214410p:plain

おお、壁にぶつかった場所がParticle化して空中に舞っています。

凄いです。

Tutorialの残りを見てたらもう一個Moduleを追加していました。

終りじゃなかったです。

Color Moduleを追加しました。

f:id:kazuhironagai77:20210912214428p:plain

Testします。

Particleが光っています。

f:id:kazuhironagai77:20210912214444p:plain

少しだけ微調整します。

f:id:kazuhironagai77:20210912214500p:plain

発光している部分の幅が狭くなりました。

f:id:kazuhironagai77:20210912214517p:plain

これでBuilding advanced effects in Niagara | Unreal Engine [1]の勉強は終わりました。

2.4 Building advanced effects in Niagara | Unreal Engine [1]の総括

もう頭が一杯で何も考えられません。来週、気持ちが落ち着いたら後半部分の復習と全部の総括を行います。

3.Cascade: 先々週の続き

先週、時間がなくてCascadeの勉強は出来ませんでした。2021-08-30のブログで勉強した続きをやっていきます。

CGHOW氏のUnreal Engine Skull Aura Tutorial | Download Project Files [8] を途中まで勉強しました。

f:id:kazuhironagai77:20210912214549p:plain

今週は残りをやります。

3.1 2021-08-30のブログの復習

もう何を勉強したのか忘れてしまったので2021-08-30のブログで復習をします。

<骸骨を回転させる>

2021-08-30のブログは、区切り良くまとまってないので、勝手に区切ってまとめます。

最初の区分は、髑髏を回転させる所です。

f:id:kazuhironagai77:20210912214705g:plain

Initial Velocity ModuleでLocked Axesの値をXYZに固定し

f:id:kazuhironagai77:20210912214734p:plain

かつVelocity/Life ModuleのVelocity Over Lifeの値を以下の様にセットして骸骨を回転させています。

f:id:kazuhironagai77:20210912214749p:plain

次にRequired ModuleのScreen Alignmentの値をPSA Velocityに変更する事で、骸骨の向きが前を向くように調節しています。

f:id:kazuhironagai77:20210912214804p:plain

ただし骸骨が一瞬だけ横を向くバグが発生しています。

そして色々検討しているんですがその原因が分かっていないです。

<骸骨を光らせる>

以下の図の様に骸骨を光らせます。

f:id:kazuhironagai77:20210912214822p:plain

正し、この図の骸骨はCGHOW氏が作成したものです。

私が出来たのは以下の骸骨です。

f:id:kazuhironagai77:20210912214838p:plain

この違いは使用したMeshの違いのせいです。使用するMeshの違いによってもこんなに違う結果が生まれるとは驚きでした。

<専用のMaterialを作成する>

光る骸骨のための専用のMaterialを作成しました。

f:id:kazuhironagai77:20210912214858p:plain

そこではFresnel関数が使用されています。

Fresnel関数については以下の事を勉強しました。

Fresnel関数にはBase Reflect FractionとExponentInの二つのParameterがあります。

ExponentInは外円の大きさを管理しています。

ExponentIn = 10、

f:id:kazuhironagai77:20210912214913p:plain

ExponentIn = 5、

f:id:kazuhironagai77:20210912214928p:plain

ExponentIn = 1

f:id:kazuhironagai77:20210912214942p:plain

となっています。

Base Reflect Fractionは内円の色の濃さを管理しています。

Base Reflect Fraction = 0

f:id:kazuhironagai77:20210912214956p:plain

Base Reflect Fraction = 0.01

f:id:kazuhironagai77:20210912215011p:plain

Base Reflect Fraction = 0.04

f:id:kazuhironagai77:20210912215049p:plain

となっています。Base Reflect Fractionの値の範囲は0から0.04位が適切な値でとても小さい値の変化で内円の色が物凄く濃くなります。

3.2 Unreal Engine Skull Aura Tutorial | Download Project Files [8] の続きを勉強する

<Shock Wave Effect

今度は以下に示したようなShock Wave Effectを作成します。

f:id:kazuhironagai77:20210912215116p:plain

使用するMaterialを以下の様に作成しました。

f:id:kazuhironagai77:20210912215132p:plain

こんなイメージです。

f:id:kazuhironagai77:20210912215151p:plain

何故か端が切れています。

Materialを読むと以下の部分でTexCoord[1]に値を足しているからTextureがずれるのは当然です。

f:id:kazuhironagai77:20210912215214p:plain

Textureの白い部分を縮小しました。

f:id:kazuhironagai77:20210912215228p:plain

端が切れなくなりました。

f:id:kazuhironagai77:20210912215243p:plain

ここからTutorialはほとんど説明しないで以下の形になったと言っています。

f:id:kazuhironagai77:20210912215256p:plain

しょうがないので色々数値を弄って以下の物を作成しました。

f:id:kazuhironagai77:20210912215310p:plain

こんな感じです。

f:id:kazuhironagai77:20210912215331p:plain

CGHOW氏の作成したTrailは線がとても細いんです。何をやっても回転を加えると私のは太くなってしまいます。

Tutorialでは紫色に代えていますが、ここはスキップしておきます。

<骸骨から出る粒々のEffectの作成>

今度は骸骨から出る粒々を再現します。

f:id:kazuhironagai77:20210912215425p:plain

以下のWidgetを使用しました。

f:id:kazuhironagai77:20210912215452p:plain

f:id:kazuhironagai77:20210912215458p:plain

f:id:kazuhironagai77:20210912215505p:plain

f:id:kazuhironagai77:20210912215511p:plain

これらの機能については後で調べます。

f:id:kazuhironagai77:20210912215526p:plain

実際のLevelではこんな感じです。

f:id:kazuhironagai77:20210912215545p:plain

うーん。綺麗ですね。

<Light Effectを骸骨に追加する>

今度は骸骨にLightを追加します。

f:id:kazuhironagai77:20210912215603p:plain

床が光るようになりました。

f:id:kazuhironagai77:20210912215616p:plain

因みにPreviewではこんな感じです。

f:id:kazuhironagai77:20210912215632p:plain

これはNiagaraのLight Renderingと同じEffectですね。

<Smoke Effectの追加>

今度はSmokeを追加します。

f:id:kazuhironagai77:20210912215654p:plain

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

Smokeに関しては十分勉強したのでここでは結果のみ示します。

<Monsterに蛍光色をつける>

これはスキップします。

<Rayを作成します>

以下の様なRayを追加します。

f:id:kazuhironagai77:20210912215715p:plain

これには以下の様なMeshを使用しているので今回はパスします。

f:id:kazuhironagai77:20210912215729p:plain

<Ring を追加します>

こんな感じのヤツです。

f:id:kazuhironagai77:20210912215749p:plain

この辺から気力が尽きてしまいました。

残りはまた来週やります。

4.Map1の作成

今までは、ゲームの機能を作成するために色々なActorを無差別に配置していましたが、先週、とうとうMap1がGame用、Map1_Testがテスト用に分割出来ました。今週はMap1を整理します。

そこで今週はMap1のLevel Designを行います。

こんな感じで要らないActorは全て排除しました。

f:id:kazuhironagai77:20210912215813p:plain

まず壁から直していきます。

f:id:kazuhironagai77:20210912215829p:plain

f:id:kazuhironagai77:20210912215838p:plain

f:id:kazuhironagai77:20210912215847p:plain

f:id:kazuhironagai77:20210912215855p:plain

f:id:kazuhironagai77:20210912215904p:plain

こんな感じです。

後、何をすべきなのかが分かりません。

木を加えて、簡易的な神殿めいた物を作成しました。

f:id:kazuhironagai77:20210912215933p:plain

更にNPCを一体配置します。

f:id:kazuhironagai77:20210912215947p:plain

そのNPC用のセリフを考えます。

f:id:kazuhironagai77:20210912220011p:plain

まだ途中ですが先に、このセリフを表示出来るようにします。

EnumのVillage NameにTutorial Nameを追加します。

f:id:kazuhironagai77:20210912220026p:plain

Headman Welcome WidgetのConversation Start EventのSwitch on Village NameのTutorial Villageに追加の実装をします。

f:id:kazuhironagai77:20210912220041p:plain

ここで先程作成したNPC用のセリフを読みこみます。

f:id:kazuhironagai77:20210912220108p:plain

これでいけるはずです。

テストします。

f:id:kazuhironagai77:20210912220128p:plain

f:id:kazuhironagai77:20210912220137p:plain

出来ていますね。

それではセリフを直していきます。

f:id:kazuhironagai77:20210912220154p:plain

全部の会話に対応出来るようにしました。

5.Characterの変更

今度はCharacterを変更しようと思います。

f:id:kazuhironagai77:20210912220217p:plain

2021-08-30のブログで述べていますが、

f:id:kazuhironagai77:20210912220231p:plain

たまたま半額セールしていたので買ってしまいました。

そしたらAnimationはついていませんでした。

後でTechnical Detailを読み直したら、

f:id:kazuhironagai77:20210912220255p:plain

と書かれていました。

Epic SkeletonにScaledはOKですがRiggedは駄目ってどういう意味なんでしょうか?

分からないのでSkeleton Assets: Anim Retargeting Different Skeletons | 03 | v4.8 Tutorial Series | Unreal Engine [9] で行われている方法でやってみます。

UE4_Mannequin_SkeletonのRetargeting Managerを開きSet up RigのSelect Rig にHumanoidを選択します。

f:id:kazuhironagai77:20210912220309p:plain

そしたらSaveしろとMessageが表示されます。

Tutorialによると以下のSaveを押せばいいそうです。

f:id:kazuhironagai77:20210912220333p:plain

押しました。

今度は、SK_Character_Fantasy_Skeletonを開いて

f:id:kazuhironagai77:20210912220348p:plain

Retargeting ManagerのSet up Rigを見ると

f:id:kazuhironagai77:20210912220407p:plain

全く同じ名称で1:1 で対応していました。

これは活けそうです。

ここでもSaveをします。

今度は

f:id:kazuhironagai77:20210912220427p:plain

を選んでRetarget Anim Assets を行います。

f:id:kazuhironagai77:20210912220442p:plain

あれ、Fantasy_Skeletonの方のMeshが表示されませんね。

SK_Character_Fantasy_Skeletonのこのイメージより

f:id:kazuhironagai77:20210912220458p:plain

Tポーズをしていると仮定して先に進みます。

UE4_Mannequin_SkeletonのポーズもTポーズに変更します。

f:id:kazuhironagai77:20210912220513p:plain

ここでSaveしろとTutorialでは言っていますが私のManage Retargeted Base PoseにはSaveボタンがありません。

f:id:kazuhironagai77:20210912220554p:plain

良く分からないですが、Select SkeletonのUE4_Mannequin_SkeletonのポーズもTポーズになったのでOKとします。

f:id:kazuhironagai77:20210912220610p:plain

何でTargetにFantasy_SkeletonのMeshが写らないんでしょうか?

一応、UE4Editorを再起動したんですが、変わりません。

これでRetargetをやってみます。

f:id:kazuhironagai77:20210912220624p:plain

出来ています。

NPC_PersonのAnimationの設定を以下の様に入れ替えると

f:id:kazuhironagai77:20210912220651p:plain

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

f:id:kazuhironagai77:20210912220709p:plain

王様、小っちゃい。

王様のサイズを1.5倍にしました。

f:id:kazuhironagai77:20210912220723p:plain

今度は王様、明後日の方を見ています。

王様の身長は変えずに横と縦だけ2倍にしてみました。

f:id:kazuhironagai77:20210912220742p:plain

今度はイイ感じです。

よく見るとやっぱりおかしいですが、まあ自分でモデルを作成する事は出来ないのである程度の所で妥協するしかありません。

6.Loading Screenの勉強の続き

6.1 先週までの流れ

新しいMapを読み込んでいる間に銀河鉄道内で会話をしている機能をRPGに追加したかったのでBackgroundでLevelをLoadする方法を調査していました。

その結果

  • UE4C++からBackgroundLoadする方法。
  • Load Stream Level ノードを使用する方法
  • Plug inであるAsync Loading Screenを使用する方法

の3つの方法がある事が分かりました。

最初のUE4C++からやる方法はAsync Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [10]で勉強しました。勉強の内容は2021-08-16のブログ2021-08-23のブログにまとめてあります。これは講演の内容を理解しただけで実際に自分で試してはいません。

次のLoad Stream Level ノードを使用する方法は、巨大なMapを複数のSub Levelに分割して作成してSeamlessに呼び込む場合でしかLoad Stream Level ノードの使用方法や機能の説明がなかったので、まずその場合におけるLoad Stream Level ノードの使用方法や機能の説明を勉強しました。

Load Stream Level ノードについて完全に理解したのでLoad Stream Level ノードを使用してLoading Screenを作成する方法をMathew Wadstein氏の HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [11] で勉強しました。

意外にこのTutorialが複雑で最後まで終わりませんでした。

今週はこのTutorialの続きからやっていきます。

6.2 HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [11]の復習

先週、勉強した内容をほとんど覚えていないので先週のブログを見ながらの復習からやります。

  • 準備編:Start ButtonのあるWidgetまでの作成
  • 本編:Start Buttonの実装
  • 本編2:Interfaceの追加によるEventの作成
  • 本編3:InterfaceからのEventを使用する事で、LevelWidget間の連絡が出来る様にする
  • 本編4:Event Load Next Streaming Levelの実装
  • 本編5:Animated Loading Loading ScreenEvent Load Loading Screenの実装

思い出してきました。Stream LevelのEventを、InterfaceをImplementする事で作成すると、そのEventはWidgetから呼び出せるようになるんでした。

f:id:kazuhironagai77:20210912220927p:plain

思い出しました。

今度、Animated Loading Map1を作成するんでした。

<Animated Loading Map1の作成>

Animated Loading Map1を作成する前に以下のActorをAnimated Loading Pers Levelに追加しました。

f:id:kazuhironagai77:20210912220950p:plain

Animated Loading Map1をStream Levelとして作成しました。

f:id:kazuhironagai77:20210912221003p:plain

Animated Loading Map1に赤いBlockを追加しました。

f:id:kazuhironagai77:20210912221017p:plain

Source CodeのAnimated Loading Map1を見ると単にPlayer が操作するキャラを生成しているだけです。

f:id:kazuhironagai77:20210912221033p:plain

Third Person Characterが生成される私のProjectは実装する必要はないです。

テストします。

UMG Splash Screen widgetが表示されます。

f:id:kazuhironagai77:20210912221053p:plain

本当のGameで言えばイントロ部分に当たるのでしょうか?

次にMain Menuが表示されます。

f:id:kazuhironagai77:20210912221116p:plain

ここでStart Gameを選択します。

するとLoading Screenが現れます。

f:id:kazuhironagai77:20210912221129p:plain

この時にBackgroundでAnimated Loading Map1がLoadされているはずです。

Animated Loading Map1のLoadが終わるとPersistent Level + Animated Loading Map1が表示されました。

f:id:kazuhironagai77:20210912221143p:plain

一応これで、Loading Screenを実行中にBackgroundでLevelをLoadする方法は分かりました。

6.3 Load Stream Level ノードを使用してLoading Screenを作成する方法のまとめ

理解するために全部やりましたが、結論はLoading Screen をWidgetで表示して

f:id:kazuhironagai77:20210912221206p:plain

その間にLoad Stream LevelノードでStream Levelを読み込むだけでした。

f:id:kazuhironagai77:20210912221221p:plain

はい。

6.4 Load Stream Level ノードを使用してLoading Screenを作成する方法の問題点と応用

この勉強をするまでStream Levelの存在自体、知らなかったです。その事とその使用方法について勉強出来た事は良かったですが、これでLoad出来るのはSub Levelだけです。全く別なLevelをLoadする時にこの方法が使用出来ない事も確認出来ました。

つまり私の「銀河鉄道に乗車中にBackgroundで次のLevelをLoadする。」事には、この方法は使えない訳です。

うーん。

しかし、Stream Levelの存在とその使用方法を学べたことはこれからのGame制作にかなり役に立ちます。

Landscape4で出現するMonsterを区域毎に分けて出現するやり方は実装するのに結構手間がかかりました。でもこれをStream Levelを使用して実装したら凄く簡単に出来たと思います。

7.  How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [12]を勉強する

7.1 How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [12] の概要を調べる

やっと最後のLoading Screenの作成方法であるPlug inを使用する方法まで来ました。以下のplug inを使用するそうです。

f:id:kazuhironagai77:20210912221315p:plain

まずは How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [12]を軽く見てみます。

Open Level ノードを使用しています。これでもAsync Loadingになるんでしょうか?

f:id:kazuhironagai77:20210912221329p:plain

Loading Screenに映像を使用するんでしょうか?Mp3 fileも手動でImportしています。

f:id:kazuhironagai77:20210912221343p:plain

Project SettingからAsync Loading Screenを選択しています。

f:id:kazuhironagai77:20210912221357p:plain

これって元からある機能なんでしょうか?それともAsync Loading Screen を使用した結果、使用出来るようになったんでしょうか?

最初に2秒くらいの映像が流れました。これが先程、手動でImportした映像のようです。

f:id:kazuhironagai77:20210912221411p:plain

Play画面が出た後、次のLevelに移動しました。

f:id:kazuhironagai77:20210912221425p:plain

Open Levelで新しいMapを読み込んでいる時に以下のイメージが表示されています。

f:id:kazuhironagai77:20210912221441p:plain

成程、AsyncしてLoading しています。

パラッと見た限りですが、Stream Levelではなく全く別のLevelをBackgroundでLoad出来るみたいですね。

7.2 How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [12] をやってみる

凄い簡単そうなので実際にやってみます。

取りあえず2つのMapを作成しました。

f:id:kazuhironagai77:20210912221500p:plain

f:id:kazuhironagai77:20210912221507p:plain

この2つはそれぞれ独立したMapです。

Tigger Boxを配置してその中に入ると反対のMapをLoadするようにします。

f:id:kazuhironagai77:20210912221522p:plain

勿論、使用しているNodeはOpen Levelです。

実際にPlayしてみるとこんな感じです。

f:id:kazuhironagai77:20210912221536p:plain

f:id:kazuhironagai77:20210912221544p:plain

ここに先程のPlug inを入れてテストしてみます。

あ、そうだ。

先程述べたProject SettingのAsync Loading Screenを調べておきます。

f:id:kazuhironagai77:20210912221559p:plain

やっぱりないですね。これはPlug inを入れたら表示されるようです。

f:id:kazuhironagai77:20210912221613p:plain

<Async Loading ScreenをImportする>

Market PlaceからAsync Loading Screenを手に入れます。

f:id:kazuhironagai77:20210912221631p:plain

うーん。

これはEngineにInstallするタイプなのか。

f:id:kazuhironagai77:20210912221701p:plain

4.26にInstallしました。

4.26のPlug inを開いてAsync Loading ScreenをEnabledにします。

f:id:kazuhironagai77:20210912221716p:plain

UE4Editorを再起動させます。

Project Setting のGame欄にAsync Loading Screenが新しく表示されました。

f:id:kazuhironagai77:20210912221730p:plain

<Async Loading Screenを使用してBackgroundでLevelをLoadする>

How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [12]の1.45分辺りを参考にしてImageをImportします。

Loading Screen用にImageを4つImportしました。

f:id:kazuhironagai77:20210912221748p:plain

Moveは無視して先に進みます。適切なMP3 fileが無いです。

多分なくても出来るでしょう。

Project SettingのAsync Loading Screenを開きます。

f:id:kazuhironagai77:20210912221802p:plain

こんな感じです。

f:id:kazuhironagai77:20210912221816p:plain

General欄から見て行きます。

f:id:kazuhironagai77:20210912221831p:plain

Startup Loading Screenはゲームが開始された時だけ流れるLoad画面だそうです。

f:id:kazuhironagai77:20210912221847p:plain

Default Loading Screenは新しいLevelがLoadされるたびに流れるLoad画面だそうです。

f:id:kazuhironagai77:20210912221900p:plain

今回はDefault Loading Screenの使用方法さえ分かれば十分です。

BackgroundのImageに先程ImportしたImageをセットしました。

f:id:kazuhironagai77:20210912221919p:plain

今度はTip WidgetのTip Textに文字を追加しました。

f:id:kazuhironagai77:20210912221932p:plain

これも表示されるのでしょうか?

興味深いです。

TutorialではLoading WidgetのLoading Icon TypeをCircular ThrobberからImage Sequenceに変更していますが私はこれでいいです。

f:id:kazuhironagai77:20210912221948p:plain

今度はLay outの設定です。

Tutorialでは下のBorder Backgroundの色を変えていますが、取りあえずはこのままで行きます。

f:id:kazuhironagai77:20210912222018p:plain

最後にMinimum Loading Screen Display Timeの値を5秒に変更します。

f:id:kazuhironagai77:20210912222032p:plain

これで設定は終りみたいです。

テストしようとしたら、TutorialでStand Alone Gameの時しか機能しないと言っています。

f:id:kazuhironagai77:20210912222054p:plain

はい。

それではテストします。

<Async Loading Screenのテスト>

Gameを開始したら以下の画面が現れました。Startup Loading Screenで何も指定していない時はDefault Loading Screenが呼ばれるようです。

f:id:kazuhironagai77:20210912222113p:plain

文字もCircular Throbberも見えません。Backgroundの色のせいでしょうか?

Game Play画面になりました。

f:id:kazuhironagai77:20210912222127p:plain

次のLevelに移動します。

Loading Screenが表示されました。

f:id:kazuhironagai77:20210912222141p:plain

これも文字もCircular Throbberも見えません。

Border Backgroundの色をオレンジに変えました。

f:id:kazuhironagai77:20210912222155p:plain

もう一回テストします。

f:id:kazuhironagai77:20210912222207p:plain

今度は文字もCircular Throbberも読めます。

出来ていますね。

うん。しかも凄い簡単ですね。

7.3 Async Loading Screenの機能を色々試す

色々弄ったんすがこれぐらいしか変化しないです。

f:id:kazuhironagai77:20210912222226p:plain

あんまり自由度がないのかなと思っていたら、こんな項目がありました。

f:id:kazuhironagai77:20210912222242p:plain

んー。

成程。色んなLayoutが選べるわけですね。

f:id:kazuhironagai77:20210912222259p:plain

Async Loading ScreenのDocument [13]を一寸だけ読む>

Documentにもっと詳しい解説が書かれているはず。

と探したらここにDocumentがあるそうです。

f:id:kazuhironagai77:20210912222319p:plain

見るとLayoutの項目が有り詳しく解説してありました。

f:id:kazuhironagai77:20210912222332p:plain

このDual Slide Layoutが格好良いです。

f:id:kazuhironagai77:20210912222348p:plain

話は飛びますが、Source Codeも全部公開してありました。

f:id:kazuhironagai77:20210912222401p:plain

Dual Slide Layoutを試した後でSource Codeも見てみます。

<Dual Slide Layoutを試す>

f:id:kazuhironagai77:20210912222504p:plain

にして色だけ変えてみました。

f:id:kazuhironagai77:20210912222517p:plain

テストします。

f:id:kazuhironagai77:20210912222532p:plain

サンプルの映像を見ると

  • Backgroundは半透明
  • Circular ThrobberLoadingは垂直に並んでいる。
  • I am loading screen2行以上に分けれるはず。

これを試してみます。

Tip TextにCtl+Shfitで行替えをして文字を追加しました。

f:id:kazuhironagai77:20210912222555p:plain

Background Imageを半透明にするのはそのまんまαの値を下げました。

f:id:kazuhironagai77:20210912222616p:plain

Circular ThrobberとLoadingを垂直に並べるのはLoading WidgetにあるLoading Widget TypeをVerticalにセットしてみます。

f:id:kazuhironagai77:20210912222632p:plain

はい。

f:id:kazuhironagai77:20210912222644p:plain

Circular ThrobberとLoadingは垂直に並びましたが、サンプルの絵と逆ですね。

以下のチェックを外してみます。

f:id:kazuhironagai77:20210912222659p:plain

お、Circular ThrobberとLoadingの位置が逆になりました。

f:id:kazuhironagai77:20210912222713p:plain

大体の操作の仕方は分かりましたね。

7.4 Async Loading ScreenのDocument [13]を読む

まずAboutが明瞭です。

  • Level間の移動中にUser Widget は破壊される。
  • LevelLoadMain Threadで行われLoad中は何も出来ない。
  • Level Streamingは別のGame ModePlayer Controllerを使用したLevel間では使用出来ない
  • Level Streamingを使用しない場合は、C++を使用する必要がある。
  • しかしC++の使用はDesignerには難しい。
  • 更にSlateフレームワークEngineModuleの理解が必要。

はい。

今まで勉強した内容がギュッと凝縮されています。

それじゃ少しだけCodeを見て行きます。

PrivateDependencyModuleNames.AddRange()にSlateとSlateCoreが使用されています。

f:id:kazuhironagai77:20210912222746p:plain

Hファイルはこんな感じになってました。

f:id:kazuhironagai77:20210912222802p:plain

Background WidgetとかDual Sidebar Layoutのようにそれぞれのクラスが何を担当しているのか位はこれ見ただけでも分かります。

SBackgroundWidget.h を見てみます。

f:id:kazuhironagai77:20210912222817p:plain

SCompoundWidgetを継承していますね。

2021-08-23のブログを見るとAction RPGRPG Loading ScreenでもSCompoundWidgetを継承しています。

f:id:kazuhironagai77:20210912222831p:plain

うーん。

Github上でコードを追っていくのは非常にムズイ。

今回の目的はUE4C++でLoading Screenを作成する事ではないので、あんまり深入りしない方がいいかもしれません。時間も無くなって来たのでこの辺で中止します。

8.Good Skyの復習

もう時間がないので今週も延期です。

9.まとめと感想

今週はそれぞれの課題で壁にぶつかった時にすぐにあきらめてしまっています。

何ででしょう?やる気がちょっと足りなかったんでしょうか?まあ何時でも絶好調ではいられないのでしょうがないのかもしれませんね。

10.参照(Reference

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

[2] CGHOW. (2021, March 19). All Forces Modules in UE4 Niagara Explained [Video]. YouTube. https://www.youtube.com/watch?v=iW867tJ93lU

[3] Epic Games. (n.d.-b). Niagara Overview. Unreal Engine Documentation. Retrieved September 12, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/Overview/

[4] gameDev Outpost. (2020, September 15). UE4 - Niagara Dynamic Inputs [Video]. YouTube. https://www.youtube.com/watch?v=utsXM2LGvPY

[5] cppreference.com. (n.d.). Expressions - cppreference.com. Retrieved September 12, 2021, from https://en.cppreference.com/w/cpp/language/expressions

[6] Epic Games. (n.d.-a). 4.2 - Inverse Square Falloff. Unreal Engine Documentation. Retrieved September 12, 2021, from https://docs.unrealengine.com/4.26/en-US/Resources/ContentExamples/Lighting/4_2/

[7] Epic Games. (n.d.-c). Particle Spawn Group. Unreal Engine Documentation. Retrieved September 12, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/ParticleSpawn/

[8] CGHOW. (2019, January 6). Unreal Engine Skull Aura Tutorial | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=V5u4iogpmQE&list=PLwMiBtF6WzsqXWJF-pjjkovVZM-04lzt_&index=2

[9] Epic Games [Unreal Engine]. (2015, September 28). Skeleton Assets: Anim Retargeting Different Skeletons | 03 | v4.8 Tutorial Series | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=xy9aLbZLdeA

[10] Epic Games [Unreal Engine]. (2019, May 20). Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=ON1_dEHoNDg

[11] Wadstein, M. [Mathew Wadstein]. (2015, October 31). HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=QJVn2mW67YQ

[12] Uisco. (2021, March 3). How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=KpXmcqSITOg

[13] Bui, T. (n.d.). GitHub - truong-bui/AsyncLoadingScreen: Async Loading Screen. GitHub. Retrieved September 12, 2021, from https://github.com/truong-bui/AsyncLoadingScreen

 

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する Map1の複製の作成など part 2

f:id:kazuhironagai77:20210906012116p:plain

<前文>

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

<沈黙は金ではない!>

先週、アメリカ人は専門家や上司の言う事を、日本人のように「自分では悪いと思っても会社の命令(専門家の意見)なので…」と言って無条件で聞く事はない。と述べましたが、じゃどうやって意思決定をしているのかと言うとこんな感じです。

ある大学発のベンチャーでゲームを制作しているとします。

ゲーム制作は順調に進み8割程度は出来て来ました。そしたら問題発生です。小さな修正をするたびにCompileするんですが、それに2時間もかかるようになってしまいました。小さな修正をするたびに2時間待たなければなりません。社長は発狂しています。

社長が発狂しながら断言します。「全部のPCのHDDをSSDに代える。」

みんな「えー」と絶叫です。

はい。ここからがとてもアメリカ的になります。

まず統計学の得意な社員がHDDでCompileした場合とSSDでCompileした場合の短縮した時間のデータを出来るだけ集めて、本当にSSDでCompileしたら速くなるのか検討します。

こんな感じでしょうか?

存在してるデータでSSDでCompileしたら平均で10分くらい速くなっている。

サンプル数が十分がどうかを検討するために逆の仮説「SSDに代えてもCompile時間は変わらない。」をDisproveします。

Student tで計算した結果、全部のSSDを変えた場合に平均で10分くらい速くならない確率は5%以下と出ました。

よって社長が言うように「全部のPCのHDDをSSDに代える。」とCompile時間の短縮に繋がる可能性は高いと。

みんな「オーッ」です。

すると今度は、会計が得意な社員が、これからCompileする回数と10分の短縮とProgrammerの時給を計算して、SSDの値段と比較してSSDを買い替えても得なのかどうかを経費の立場から意見を言います。

これもみんな「オーー」です。

はい。会社の雰囲気が変わって来ました。

即興で始まった非公式の会議ですが「Compileに2時間もかかる。」という会社存続の危機に対する解決策を検討すると言うとても重大な内容です。

ここで発言した社員は、社長からだけでなく他の社員からも出来るヤツと観られています。

こうなると「やべー。俺も何か発言しないと。」と結構焦って来ます。でも変な事を言うよりは黙っている方が良いかもしれません。

はい。皆さんがアメリカで仕事をしていてこんな状況になったらどんな発言をしますか?もしくは黙っていますか?

今回の例は、間違った回答をすると絶体絶命のピンチに陥る場面ではありませんが、日本文化的な対応をすると無能と誤解されてしまうケースです。

日本人がよくやる間違った対応をまず紹介します。

間違い1:調べて、自分なりの解答を見つけるが、取りあえず黙っておく。

例えば、今回の例でいうと、SSDとHDDにおけるCompileの時間の違いについてStack Overflowで調べたとします。

すると「SSDとHDDでCompileの時間の違いはない。」と書かれています。

ここで大抵の日本人は、SSDを買う方向で議論が進んでるという会社の空気を読んで黙ってしまいます。

いわゆる「雄弁は銀、沈黙は金」と言うやつです。日本文化だったらこれは100%正しいやり方です。

しかし、アメリカでこれをやると以下の理由で大変な無能と思われてしまいます。

  • 議論に参加出来る専門知識が欠如している。
  • リーダーシップが足りない。
  • 会話に積極的に参加する意思がない。

最初の「議論に参加出来る専門知識が欠如している。」ですが、自分の専門分野の知識を元にどんどん発言しないと詰みます。アメリカでは自分の意見を言わないのは「意見を言えるほどの勉強をしていない。」と見なされます。本当に見なされます。学生ならばまだテストの点で挽回出来るかもしれませんが、実社会ではこういう場面での発言がその人の能力の評価に直結します。Incompetentの烙印を押されないためには、自分の専門の立場からの発言は必ずしなければなりません。

日本だと専門家が専門用語を交えて説明すると、結構社会的な地位のある人でも「小学生でも分かる様に説明しろ!」と叱責する人がいますが、アメリカではそんな必要はありません。どんどん専門用語を使って良いです。多少は合いの手を入れて「ここはProgrammer以外の人には馴染みないかもしれませんが」とか言っておけば十分です。

ただし結論だけは小学生にも分かるようにしないといけません。結論だけで十分です。

次の「リーダーシップが足りない。」ですが、日本では「出る杭は打たれる。」という諺に代表されるように、トップに立つと必ず潰されます。これはヨーロッパでも同じかもしれません。

しかしアメリカではリーダーは本当に特別なんです。

開拓時代の苦しい生活においては、優れたリーダーがみんなを正しい方向に引っ張って行かないと本当に村ごと全滅してしまったんです。だからリーダーを選ぶ時は、真剣です。これは小さい子供たちのグループでも同じで、自分たちのリーダーを選ぶ時は真剣です。そして一端、リーダーを選んだら、みんなはそのリーダーを補助するための全力を尽くしますし、リーダーはみんなを正しい方向に導くために全力で頑張ります。

そしてここが重要ですが、リーダーに選ばれた人は無条件でずっとリーダーでいられるわけではありません。失敗すればすぐにリーダーの地位から降ろされますし期限で交代する時もあります。

だからアメリカ人は無意識の内に常に次のリーダー候補を探しているんです。

発言しない人がリーダーに相応しいかどうかの判断は絶対に出来ません。

だから発言しないだけでリーダーシップが足りないと判断されます。そして会社でその判断を下されたら結構、致命的です。リストラの対象になります。

最後の「会話に積極的に参加する意思がない。」ですが、もはや村の一員とすら見做してもらえない他人の烙印を押されてしまいます。村の一員でないので大切な決め事の時にも呼ばれなくなりますし、困っていても助けても貰えなくなります。

間違い2:真剣に正しい解答を考えていて議論に参加しない。

日本だとウーンと唸りながら天を仰ぎみたりすると、真剣に考えていると受け取られますが、アメリカでこれやると無視してると受け取られます。

アメリカで相手の話を真剣に聞いてるというジェスチャーは一個しかありません。

相手の目を滅茶苦茶真剣に見つめて相手の話に合わせてうんうん頷く。これだけです。これ以外のジェスチャーは人の話を聞いていないとみなされます。

大体、アメリカでは、次の発言をする人はアイコンタクトで決めているんです。相手の顔見てなかったら何時発言出来るのかも分からないです。

更に言えば、アイコンタクトしていれば、特別に発言したい時は、人差し指を一寸上げるだけで十分です。

後、思い出したんですが、日本では人が喋ってる間に割り込んで話す人がいますが、アメリカでこれやると終りですから。小学生レベルの躾が出来ていないと思われます。会社なら直ぐ首です。

間違い3:会議の後で社長だけにこっそり自分の意見を言う。

これは私も聞いた話で本当の所は分からないですが、日本だと会議をやった後に、同じ派閥の人だけが集まってそこでもう一回会議を行う所があるらしいんです。外様の社員は形だけ会議に参加させるみたいな事何でしょうか?

このせいなのかどうか知りませんが、日本人には、会議の後で社長だけにこっそり自分の意見を言う人がいるらしいです。

私の経験の範囲ですが、これはケースバイケースで、その場にいる人を直接批判する内容ですがボスには絶対報告しておいた方が良い場合はOKです。

今回の例のように、別に他の人に隠す必要がない場合は、聞いてもらえない+評価されない可能性が高いです。

これは一寸、アメリカにおける議論の前提を理解出来ればすぐに想像つきます。限られたリソースと時間の中から最適解を探すのが議論の目的なんです。後で結論が出てから自分の意見を言ったって何の役にも立ちません。

正解:兎に角、自分の意見を言っておく

Stack Overflowを調べた結果を発言しておくだけでもかなり好評価が付きます。その理由は間違い1で説明した内容の反対になるからです。

  • 議論に参加出来る専門知識は十分持っている。
  • リーダーシップがある。
  • 会話に積極的に参加する意思ある。

と評価されます。

しかし社長が、そのStack Overflowの解答を読んで、実際の結果では統計的に有意な差が出ている。つまりこの理屈は間違ってる。と断言したとします。

それでも貴方の評価が悪くなる事はアメリカでは絶対にありません。

そしてStack Overflowの解答で二番目に評価されている解答が、実際にSSDを使用すると速くなっていると言う意見だとします。社長がほら見た事かと言うかもしれませんが、それでも貴方の評価は良いままです。

因みに私がそんな状況にいたら、最初のゲームを制作する前にUE4を使用する事を進めていますね。絶対に。

そして8割完成した時にもCompileの問題は起きていないはずです。だってUE4ならHot  Reload機能がついていますから。

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

<本文>

1.今週の予定

今週は以下の事をやります。

  • Particle Systemの勉強
  • RPGの作成
    • Item Spawn Dataの複製
    • Loading Screenの勉強の続き
    • Good Skyの復習

2.Niagara : 今までの勉強の復習

今週は今まで勉強した内容を復習します。

来週から多分ですがCGHOW氏のTutorialを勉強する事にしますが、目的が曖昧なままだと着地点も曖昧になってしまいます。ので目的、何でVFXの勉強を始めたのかとか、もしっかり再確認します。

2.1 Blogの見直し

Blogを見直すと2021-04-26からParticle Systemの勉強を始めています。

それぞれのBlogから何を勉強したのかとか、何が目的で勉強していたのかなどを要約します。

2021-04-26

  • UEのParticle Systemについて全く理解していないので勉強する事にした。
  • Niagara の方がCascadeよりも資料が多そうだか、24には試験的にしか付いていない。
  • VFXとはVirtual Effect(視覚効果)という意味で、映画の撮影に使用するCGを指している。この技術で3Dゲームに使えるものが逆輸入された。
  • UEで使用されるVFXはParticle Systemのみである。

2021-05-03

  • System、Emitter、Moduleについて漠然と理解。
  • Material内で使用するParameter nodeの値をNiagara側のModuleで設定出来る事
  • Module内でHLSLが使用出来る事とMaterialの関係やCustom HLSLとModuleをnodeを使用して作成出来る事の関係が分からなくて混乱しています。
  • Houdiniについて少しだけ調べています。

2021-05-10

  • NiagaraのRenderingが、Sprite、Sprite(GPU) 、Mesh、Light、Ribbon、Steam、Sparks、そしてBeamである事について簡便ですが述べています。
  • 複数のEmitterを一つのNiagara System内で扱っています。
  • Moduleの継承について解説していますが、覚えていません。Moduleの継承ってなんでしたっけ。
  • EmitterのIconの意味について解説しています。

f:id:kazuhironagai77:20210906012428p:plain

  • Emitterの塊は、ScriptもしくはStackと呼ぶ。

2021-05-17

  • Event とEvent Handlerについて勉強しています。

2021-05-24

  • Niagaraを勉強する目的が曖昧なまま勉強しているので今回の最終目的はNiagaraで花火を作成する事と宣言しています。しかも7月までに完成させると宣言してました。
  • SpriteがParticleに面を貼り付けて作成される事を確認しました。
  • Light ParticleとSpriteで発光させた場合の違い。Light Particleは回りを光らせる働きがある事について述べています。
  • Mesh Particleの基本的な作成方法の勉強
  • Mesh ParticleとLight Particleが併用出来る事の確認
  • Mesh ParticleとSpriteの違いについて

2021-05-30

  • Audio Effects In Niagaraの基本についての勉強
  • ModuleからModule Scriptを開く方法について

2021-06-07

  • Ribbon Renderingのやり方について
  • 一応一通りRibbonについて勉強していますが、良く分かっていませんね。

2021-06-13

  • 先週、良く分からなかったRibbon Renderingに使用されているModuleなどの機能について詳しく調べています。
  • 正し、Ribbon のRenderingをどうやっているのかまではまだ理解していません。
  • Cascadeですが、以下のMaterialをどうやって作ったのか調べていますが、結局不明だったと述べています。

f:id:kazuhironagai77:20210906012558p:plain

これってどう見てもFresnel 関数ですよね。確認します。

元のMaterial名はM_ShapeMasterでした。

f:id:kazuhironagai77:20210906012621p:plain

しっかりFresnelを使用していました。

2021-06-20

  • Ribbon RenderingがどうやってRenderingしているのかを調べています。
  • 調べていますがBeam Rendering を使用して調べています。
  • Bezier Curveについて勉強しています。この時、調べたせいかBezier Curveについての動画がYouTubeのお勧めに大量に表示されるようになりました。Bezier Curveについては完璧に理解しました。お腹一杯です。

2021-06-27

  • Component Renderingについて調べていますね。
  • Ribbon Renderingにおける最初の仮説を以下のように表しています。

f:id:kazuhironagai77:20210906012706p:plain

2021-07-04

  • Ribbon Renderingの仮説に謝りがあったので修正しています。こっちが正しいRibbon Renderingです。

f:id:kazuhironagai77:20210906012739p:plain

  • 色々な絵をRibbonに貼りつけてVisual的な面白さを検討しています。

f:id:kazuhironagai77:20210906012926g:plain

このEffectなんかもう少し精度を上げたら商用で売れそうです。こういうのを深堀りすべきかもしれませんね。

2021-07-11

  • 今度はBeam Effectについて調べています。
  • Beam Renderingについて詳しく調べて結論らしきものが書かれていますが、私この辺の内容すっかり忘れてしまいました。後でもう一回勉強し直します

2021-07-18

  • 今度はSmoke Effectについて勉強しています。
  • Sub UVの使用方法が分からないので勉強すると言っています。
  • 一応、Sub UVがAnimationを担当している事と、そのAnimationの再現方法について理解しました。

f:id:kazuhironagai77:20210906013109g:plain

< 2021-07-25>

  • Smoke Effectの続きを作成しています。
  • その過程でNiagara Module Scriptの作り方も調べています。

f:id:kazuhironagai77:20210906013144p:plain

  • これ以上勉強する事がないのでContent Exampleからサンプルを見て次の勉強する内容を決めるとか抜かしています。
  • CGHOW氏のTutorialと比較してCGHOW氏のTutorialの方が実践的な気がするのでそっちをやると言ってます。
  • 池田 亘 著「HoudiniとUnreal Engine 4で学ぶリアルタイムVFX」を読んだ感想もここに書かれていました。

< 2021-08-02 >

  • CGHOW氏のTutorialの内最初の一個目をやってます。
  • 大量の蒸気を地面から発生させる方法を学びました。
  • これからは応用編として炎、煙、雷、水、氷、魔法陣、雪、砂、風、光、闇、爆発、回復、状態異常や呪いなどの作成方法を勉強すると言ってます。

成程、この辺から目的がブレてるんですね。Niagaraそのものの勉強、Moduleの仕組みやNiagaraにしかない機能の勉強をしたいと言う気持ちと、ゲーム制作のために必要なEffectの作成方法を勉強したいという二つの目的が生まれてどっちつかずになってしまうわけですね。

< 2021-08-09 >

  • CGHOW氏のTutorialの続きをやっています。
  • CGHOW氏のTutorial ではLight Emitterを使用して雲を光らせていますが、それが出来ません。

はい。雲を光らせるのがこのTutorialの肝なのにそれが出来ないんです。しかも4.26で作成したサンプルがほしけりゃ10ドルで買え。と

これは、Niagaraの勉強の速度が非常に遅くなってしまいます。はい。

< 2021-08-16 >

  • CGHOW氏のTutorialで全く別なNebulaの作成に挑戦してますね。もう炎、煙、雷などのゲームのEffectとか関係なしになっています。
  • 今回のは、そこそこは作成出来たみたいで、分かり易いと書いています。
  • ample Static Mesh ModuleやScratch Moduleの使用方法について学べたのでそれなりには役に立ったみたいです。

この辺は難しい所ですね。

炎、煙、雷などのEffectの作成方法について知りたいわけですが、そこは直接は教えてもらえない訳です。しかし自分の知らないModuleの使用方法は教えてもらえます。

< 2021-08-23>

  • 前の週に始めて使用したModuleについて調べています

< 2021-08-30>

  • CGHOW氏のTutorialを整理してどれを試してみるか調べています。
  • Curl NoiseのTutorialを試していますが、Curl Noiseについての説明はほとんどなくがっくりしています。

以上です。

2.2 Niagaraの勉強における問題点

はい。

Niagaraの勉強が一寸詰まっている理由が完璧に分かりました。CGHOW氏のTutorialのせいです。CGHOW氏のTutorialをやると目的の達成度は60%とかになってしまいます。これでは出来たのかどうか分かりません。

そしてですね。私の勉強の経験から言うと60%しか理解出来ないものは危ういんです。簡単なものでも100%理解した方が上に詰めるんです。単純に言って60%の出来のものに60%の出来のものを積むと30%の出来になってしまいます。

フランス語のTutorialですが

Rimaye [ Assets and Tutorials - NIAGARA ]氏のTutorial [1]の方がまだ良いかもしれません。

f:id:kazuhironagai77:20210906013302p:plain

試しに見てみましたが、フランス語全く分かりません。

凄い不安です。英語が分からない日本人の友達の気持ちがなんか分かりました。

あるいはContent ExampleのNiagaraを勉強すべきでしょうか?

f:id:kazuhironagai77:20210906013526p:plain

f:id:kazuhironagai77:20210906013536p:plain

Spriteの面は常にカメラに向いているのではなく自由に方向を変えられると言うTutorialですがパッと見ではどこでSpriteの面の方向を弄っているのか分かりません。

こういうのをキッチリ追及した方が勉強になる気がしますが、今の自分にそれが出来るでしょうか?

やっぱりCGHOW氏のTutorialも捨てがたいですね。60%しか出来なくても結構重要なModuleの使用方法なんかも教えてくれます。

ただしCGHOW氏のTutorialで勉強する時は、

  • 目的は?
  • 出来なかった事は?
  • 学んだ事は?
  • 目的は達成出来たのか?
  • Tutorial通りに作れたのか?
  • このTutorialの改善点について

を常にまとめる必要があります。

わかった。

CGHOW氏のTutorialが他の英語圏のTutorialと徹底的に違う点が。

生徒の意見を聞いて推敲しないんです。

まるで日本の先生のようです。

インド人と日本人は似ている。中国人とアメリカ人は似ている。と言う説がありますが、こんなとこでインド人と日本人が似ていたとは驚きです。

2.3 別なTutorialで勉強してみる

今週、Niagaraの勉強そのものをやらないのもあれなので、公式のYouTubeチャンネルであるUnreal EngineBuilding advanced effects in Niagara | Unreal Engine [2]で勉強してみます。

このTutorialを勉強する目的は、ずばりCGHOW氏のTutorialとの違いを見極める事です。

このTutorialはNiagaraの機能では上級者向けである以下に示したEffectの作成を行いますが、

f:id:kazuhironagai77:20210906013612p:plain

Niagaraの学習初心者が必ず躓くFXのどれを選択すれば良いのかから説明しています。

f:id:kazuhironagai77:20210906013637p:plain

そしてそういうNiagara学習初心者は、兎に角、最後のNiagara Systemを選択しておけ。と言っています。

これってこのTutorialの学習者にとって大変重要な線引きをしていますよね。このFXからどれを選択すべきなのか分からない程度の知識しかない学習者に対してもこのTutorialは対応していますと。

ちなみに私がこの中からNiagara SystemかNiagara Emitterを選択出来るようになったのは、

の3つのTutorialから学んだ成果です。

今だとこの選択肢をどれくらい理解していでしょうか?

最初のNiagara Dynamic Input Scriptは多分、Scratch PadにあるDynamic InputsのAsset版だと思います。

f:id:kazuhironagai77:20210906013713p:plain

次のNiagara Effect Typeは何なんでしょう?

試しに一個作成してみましたが

f:id:kazuhironagai77:20210906013744p:plain

ちょっと意味が分かりません。

f:id:kazuhironagai77:20210906013803p:plain

Niagara Emitterは勿論、Emitterを作成するためのものです。

Niagara Function ScriptはNiagara Systemで使用する関数を作成するものでしょうか?

Moduleとどう違うんでしょうか?

中身はこんな感じでした。

f:id:kazuhironagai77:20210906013822p:plain

これもよく分かりません。

Niagara Module ScriptはModuleを作成するためのものでしょう。

Scratch Pat Moduleをasset化したものと同じだと思います。

Niagara Parameter CollectionとNiagara Parameter Collection Instanceはこれも多分ですが、MaterialにParameterを送るやつのNiagara版でしょう。

まあ、使い方は分かりませんね。

最後のNiagara Systemは、Niagaraの機能を一括で管理します。NiagaraVFXを作成する時に必ず使用します。

こんな感じです。

しょっぱなから脇道に逸れました。

元に戻ります。

はい。Niagara SystemからNS_Spinning Particlesを作成しました。

f:id:kazuhironagai77:20210906013839p:plain

以下の箇所のTrackを押す事で新しいEmitterをNiagara Systemに足せる事を簡単ですが説明しています。

f:id:kazuhironagai77:20210906013855p:plain

その後で、Emitter内のそれぞれのCategoryがModuleを実行する事を説明しています。

f:id:kazuhironagai77:20210906013912p:plain

出来ればここで、それぞれのCategoryは何をしているかの説明もしてくれると、その後でModuleを追加する時に何故そのCategoryに追加しないといけないのかも分かって良かったんですが、それは無かったです。

簡単に自分が知る限りで説明しておきます。(公式のDocumentであるNiagara System and Emitter Module Reference [7] を参考にしています。)

Emitter Settingsです。

f:id:kazuhironagai77:20210906013930p:plain

ここはClassで言う所のConstructerです。Emitterが持つ変数に値をAssignします。

基本的にModuleを追加する事は出来ません。

Emitter Spawnです。

f:id:kazuhironagai77:20210906013946p:plain

ここはEmitterが作成された時、一回だけ実行されます。

BPで言う所のEvent BeginPlayです。

ここにModuleをセットする事は出来ますが、このEmitterが作成された時に一回だけしか実行されないので、実際はModuleをこのSectionに追加する事はあまりありません。

次がEmitter Updateです。

f:id:kazuhironagai77:20210906014007p:plain

ここはEmitterがUpdateするたびに実行されます。BPでいう所のTickです。

当然ですがここで、1秒間に何個のParticleを生成するとか、一回で何個のParticleを生成するとかを指定します。

その次がParticle Spawnです。

f:id:kazuhironagai77:20210906014030p:plain

これはそれぞれのParticleで毎回Updateしたい特徴を指定する時に使用します。例えばParticleの色が時間によって変化させたい時はここで指定します。

さらにEffectでSprite以外の表現をする時(Ribbon、Beam、SubUVによるAnimation、MeshによるParticleなど)でParticleに対して特別な指定を毎回する必要がある場合はこのSectionで行います。

ここで分からないのはここでもForceの指定が出来る事です。

最後のSectionはRendererです。

f:id:kazuhironagai77:20210906014046p:plain

このSectionはその言葉通りでどんなRenderingを行うのかを指定します。

Sprite、Mesh、Ribbonなどです。NiagaraではBeam RenderingはRibbon Rendererを使用して行います。

Light Rendererのように他のRendererと併用して行えるものも有りますが、通常は一個のRenderingしか選択出来ません。

こんな説明を追加して欲しかったです。

先に進みます。

Emitter Update CategoryにSpawn Rate Moduleを追加しました。

f:id:kazuhironagai77:20210906014102p:plain

この部分の解説にSpawn Rateが1秒間に何回、Particleを生成するのかを指定している事を説明して欲しかったです。

f:id:kazuhironagai77:20210906014116p:plain

なんと一秒間に400回もParticleを生成します。

f:id:kazuhironagai77:20210906014131p:plain

今度はParticleを生成する場所を変更する事で実際は沢山のParticleが生成されている事を示します。

Particle Spawn SectionにSphere Location Moduleを追加します。

f:id:kazuhironagai77:20210906014146p:plain

この結果、ViewportのImageが以下の様になり沢山のParticleが生成されている事が分かります。

f:id:kazuhironagai77:20210906014227p:plain

所が、私が4.26のNiagaraで同じ事をやると以下のようになります。

f:id:kazuhironagai77:20210906014243p:plain

こっこれは。私がCGHOW氏のTutorialを試した時もこれと同じ事が起きました。と言う事が私が思っている程CGHOW氏のTutorialも悪くないのかもしれませんね。

Particle Spawn Sectionに作成されているInitialize Particle Moduleの値を以下に示した様に変更してParticle のサイズを小さくしました。

f:id:kazuhironagai77:20210906014409p:plain

大体、Tutorialの結果と同じになりました。

f:id:kazuhironagai77:20210906014428p:plain

今度はこれらのParticleにForceを追加していきます。

最初はParticle Update SectionにVortex Force Moduleを追加しました。

f:id:kazuhironagai77:20210906014444p:plain

Errorが表示されます。

これを修正するにはSolve Forces and Velocity Moduleの上にVortex Force Moduleを移動する必要があります。

これはそれぞれのModuleの役割を考えれば当たり前の話で、Solve Forces and Velocity Moduleで速度や力を計算するのに計算した後で速度や力の値を変更しても意味ないですよね。

Vortex Force Moduleについてですが要するに渦を作成するための力をそれぞれのParticleに追加してくれるModuleです。

上から眺めると一応渦を描いています。

f:id:kazuhironagai77:20210906014502p:plain

はい。どうせなのでこのModuleを使用してForceをParticle Spawn Sectionにセットした場合と、Particle Update Sectionにセットした場合の違いを見てみます。

Particle Update SectionにVortex Force Moduleをセットした場合です。

f:id:kazuhironagai77:20210906014647g:plain

Particle Spawn SectionにVortex Force Moduleをセットした場合です。

f:id:kazuhironagai77:20210906014545g:plain

Particle Spawn SectionにVortex Force Moduleをセットした場合の方が、Particleが遠くまで広がっています。両方とも渦を描いていますが、Particle Update SectionにVortex Force Moduleをセットした場合の方が回転が強力です。

この結果から推測するとParticle Spawn SectionにVortex Force Moduleをセットした場合は、そんなものがあるのか分かりませんが、初加速度的な力の加え方をしていて、Particle Update SectionにVortex Force Moduleをセットした場合は継続的に加速度がかかっているいて所謂、等加速度運動の動きをしているようです。

私、力学はあんまり得意じゃないんでこの解釈で正しいのか分かりません。

この辺の解釈は力学の復習も兼ねてぼちぼち勉強していきます。

今度はParticle Update SectionにGravity Force Moduleを追加する事で、重力を追加します。

f:id:kazuhironagai77:20210906014725p:plain

重力を計算するためのModuleをParticle Update Sectionにセットしていると言う事は、Particleに等加速度運動を強いる時はForce ModuleはParticle Update Sectionにセットすべきと言う事ですね。

それは兎も角としてParticleが真下に落ちるだけになってしまいました。

f:id:kazuhironagai77:20210906014741p:plain

Gravity Forceのzの値を‐30に変更します。

f:id:kazuhironagai77:20210906014755p:plain

Particleの動きはこんなになりました。

f:id:kazuhironagai77:20210906014809p:plain

最後にParticle Update SectionにPoint Attraction Force Moduleを追加します。

f:id:kazuhironagai77:20210906014826p:plain

このModuleは中心に集まるようなForceをそれぞれのParticleに追加するModuleだそうです。

f:id:kazuhironagai77:20210906014841p:plain

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

今度はColor ModuleをParticle Update Sectionに追加します。

f:id:kazuhironagai77:20210906014855p:plain

こんな感じです。

f:id:kazuhironagai77:20210906014911p:plain

今度は色の変化をParticleの寿命からParticleの中心からの距離に変更します。

f:id:kazuhironagai77:20210906014925p:plain

を以下の様に変更しました。

f:id:kazuhironagai77:20210906014938p:plain

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

f:id:kazuhironagai77:20210906015009p:plain

Particles Positionは何となく意味が分かりますが、Simulation Positionは何を指しているのでしょうか?

f:id:kazuhironagai77:20210906015023p:plain

Emitter Properties ModuleのLocal Spaceにチェックは付いていないので、Engine.Owner.Positionの値を返すみたいですね。そのEngine.Owner.Positionの値がなんなのか不明ですが?

あ、分かりました。このModule、中心の位置を返すんですよ。それで意味が通じます。Start Positionで現在のParticleの位置、End Positionで渦の中心の位置を指定して、その差の最大が400になるようにセットしているだけでしょう。

最後にRenderer SectionにLight Rendererを追加します。

f:id:kazuhironagai77:20210906015046p:plain

それはいいんですが、Tutorialではなんの説明もなくLight RendererのUse Inverse Squared Falloffのチェックを外してしまいます。

f:id:kazuhironagai77:20210906015100p:plain

調べます。

f:id:kazuhironagai77:20210906015114p:plain

どうやらLightの減衰の計算を物理的に正しく計算するかどうかみたいですね。

どっちでもいいです。

f:id:kazuhironagai77:20210906015128p:plain

地面が光ってますね。

因みにLight RendererのUse Inverse Squared Falloffのチェックを入れたらどうなるのかも確認してみました。

f:id:kazuhironagai77:20210906015145p:plain

全く地面に光が写らなくなりました。

今度は今まで作成したNSは一端置いておいて、Robotが溶けるEffectを作成するそうです。

新しいNiagara Systemを作成しNS_DissolveEffectと名付けます。

f:id:kazuhironagai77:20210906015201p:plain

Spawn Rate ModuleをEmitter Update Sectionに追加します。値は80000にします。

f:id:kazuhironagai77:20210906015215p:plain

f:id:kazuhironagai77:20210906015239p:plain

8万はCPUによっては負担になるかもしれないのでGPUでSpriteを管理するようにします。

Emitter Setting SectionのEmitter Properties ModuleにあるSim Targetの値をGPU Compute Simに変更してFixed Boundsにチェックを入れます。

f:id:kazuhironagai77:20210906015305p:plain

f:id:kazuhironagai77:20210906015310p:plain

何でGPUによるSpriteの時はEmitterの境界を指定しないといけないのかを説明しています。

その説明によるとGPU内でSpriteを計算するとEmitterのサイズをEngineは知る事が出来ないそうです。なので大体のサイズをEngine側に手動で教える必要があるそうです。

はい。

納得しました。

次にParticle Spawn SectionにInitialize Mesh Reproduction Sprite Moduleを追加します。

f:id:kazuhironagai77:20210906015329p:plain

初めて使用するModuleです。

以下の解説がありました。

f:id:kazuhironagai77:20210906015345p:plain

何を言っているのか良く分かりません。

公式のDocumentであるParticle Spawn Group [7] のInitialize Mesh Reproduction Spriteの説明も見ましたが、書いてある内容は全く同じでした。

唯一の違いは以下の警告が書かれていた点です。

f:id:kazuhironagai77:20210906015401p:plain

うーん。読むしかないですね。

まず最初の文ですが、理想的なParticle の大きさやUVのサイズ、SpriteのAlignment(意味不明)などを決定するのにSkeletal Meshから適当に選んだ三角を使用します。とあります。

うーん。専門的過ぎます。私が知りたいのはこのModuleが何をするかなんで、Particle の大きさなどの決定方法はその後で余裕が出来た時に勉強するんで十分です。

例えば、Sphere Location Moduleだったら以下に示した様に、球の形にParticleを発生させるModuleです。とこのModuleの機能を一言で説明しています。

f:id:kazuhironagai77:20210906015418p:plain

Initialize Mesh Reproduction Spriteの説明も何をするModuleなのかバッチと一言で説明してほしいです。

私が欲しい説明はModuleの機能についての説明で、そのModuleの細かい仕組みじゃないんです。

多分ですが、Initialize Mesh Reproduction Sprite Moduleの機能とは指定したMeshの形にParticleを発生させる事だと思います。ただしそうすると、Mesh Modulesである以下に示した他のModuleとの相違点とかが良く分からないです。

f:id:kazuhironagai77:20210906015434p:plain

うん。取りあえずTutorial通りにやってみます。もしInitialize Mesh Reproduction Sprite Moduleに関する新たな情報が見つかったら、その時にまた勉強する事にします。

TutorialではPreview MeshにCrunchをセットしていますが、

f:id:kazuhironagai77:20210906015450p:plain

このModelを持っていないのでSK_Mannequinを代わりに使用します。

f:id:kazuhironagai77:20210906015507p:plain

こういう所をいい加減にやるから完成品の精度が落ちるんですね。

反省してやっぱりCrunchを探して見ます。

f:id:kazuhironagai77:20210906015542p:plain

ありました。これをDownloadして使用する事にします。

Downloadして開いたらこんな感じです。

f:id:kazuhironagai77:20210906015601p:plain

Skeletal MeshですがCrunchとなっていました。

f:id:kazuhironagai77:20210906015618p:plain

Tutorialだと

f:id:kazuhironagai77:20210906015633p:plain

となっていますので、少しだけ違いますね。

f:id:kazuhironagai77:20210906015649p:plain

ViewportのImageが以下の様になりました。

f:id:kazuhironagai77:20210906015705p:plain

Tutorialのは以下の様になっています。

f:id:kazuhironagai77:20210906015721p:plain

数値を弄って少しだけTutorialの形状に近づけました。

f:id:kazuhironagai77:20210906015737p:plain

このキャラクターに今作成したNSを追加します。

f:id:kazuhironagai77:20210906015753p:plain

やり方を以下に示します。

f:id:kazuhironagai77:20210906015811p:plain

Add Componentを押してNiagara Particle Systemを選択します。

するとNiagara System Assetが現れるのでそこにNS_DissolveEffectをセットします。

f:id:kazuhironagai77:20210906015852p:plain

こんな感じです。

f:id:kazuhironagai77:20210906015909p:plain

まあ、いいんじゃないでしょうか?

所がTutorialによるとこのやり方だと問題があるそうです。

以下に示したように、キャラの動きに合わせてParticleが動いてくれません。

f:id:kazuhironagai77:20210906015931p:plain

これはこれで凄いじゃん。と単純に思ってしまいますが、Tutorialの目的には沿っていないんでしょうね。

自分のヤツで試してみましたが、同じでした。

f:id:kazuhironagai77:20210906015948p:plain

何が起きているかと言うとそれぞれのParticleのVelocityがCharacterの動きに対して更新されないんです。

それを直すにはUpdate Mesh Reproduction Sprite ModuleをParticle Update Sectionに追加する必要があります。

f:id:kazuhironagai77:20210906020011p:plain

そしてReview MeshにCrunchをセットします。

f:id:kazuhironagai77:20210906020042p:plain

はい。

やりました。

f:id:kazuhironagai77:20210906020059p:plain

Viewportに表示されるparticleが小さくなりました。

何でなんでしょう?

Level上に実際に配置したCrunchのImageです。

f:id:kazuhironagai77:20210906020118p:plain

もっとParticleが合ってもいい感じですね。

これでParticleがキャラの動きについて行くのか確認します。f:id:kazuhironagai77:20210906020141g:plain

出来てますね。

はい。次の工程に入ります。

次はCrunchに実際に使用されているTextureをParticle Systemに使用する事で、Crunchの美しさを失わないでParticleを貼り付ける様にするそうです。

まず、Materialを複製します。

f:id:kazuhironagai77:20210906020216p:plain

むむむ。私のVersionだと5種類のMaterialをCrunchは使用しています。

f:id:kazuhironagai77:20210906020306p:plain

どれかを選んでDuplicate すれば良いんでしょうか?それとも全部Duplicateする必要があるんでしょうか?

分からないのでTutorialを一寸見てから考えます。

結論から言えばTutorialではCrunchのMaterialを元に以下のMaterialを作成しました。

f:id:kazuhironagai77:20210906020332p:plain

そして元のMaterialが以下の物です。

f:id:kazuhironagai77:20210906020348p:plain

所が私のVersionのCrunchのMaterialであるM_ Crunch _ Parentは以下の様になっています。

f:id:kazuhironagai77:20210906020404p:plain

しかもこれがCrunchの一部に使用されているMaterialで他の場所には別なMaterialが使用されています。

なにをやっているのかさっぱり分かりません。

しかしですね。

Tutorialがやった事は、Niagara Mesh Reproduction Sprite UVs ノードのParticle Mesh UVsを全てのTexture SampleのUVsに繋いだこととNiagara Mesh Reproduction Sprite UVs ノードのModule Mesh NormalをNormal のTextureのRGBに掛けただけです。

M_ Crunch _ Parentを見ると

f:id:kazuhironagai77:20210906020431p:plain

f:id:kazuhironagai77:20210906020437p:plain

f:id:kazuhironagai77:20210906020444p:plain

f:id:kazuhironagai77:20210906020501p:plain

f:id:kazuhironagai77:20210906020509p:plain

Decal Texture以外はNiagara Mesh Reproduction Sprite UVs ノードを繋げる訳です。

試してみる価値はあります。

M_ Crunch _ ParentをDuplicateしてやっています。

Normal のUVsにNiagara Mesh Reproduction Sprite UVs ノードのParticle Mesh UVsを繋げます。

更にNiagara Mesh Reproduction Sprite UVs ノードのModulate Mesh NormalsとNormalのRPGを掛けた値をNormalとして返します。

f:id:kazuhironagai77:20210906020527p:plain

更に、以下のTexture SampleにもNiagara Mesh Reproduction Sprite UVs ノードと繋げます。

f:id:kazuhironagai77:20210906020547p:plain

f:id:kazuhironagai77:20210906020559p:plain

f:id:kazuhironagai77:20210906020606p:plain

f:id:kazuhironagai77:20210906020619p:plain

Decal TextureはTexCoord[1]を使用しているのでそのままにしておきました。

f:id:kazuhironagai77:20210906020642p:plain

それをNS_DissolveEffectのRender SectionにあるSprite RendererのMaterialにセットします。

f:id:kazuhironagai77:20210906020659p:plain

こんな感じです。

f:id:kazuhironagai77:20210906020714p:plain

実際のLevel上ではこんな感じです。

f:id:kazuhironagai77:20210906020737p:plain

Tutorialではこんな感じです。

f:id:kazuhironagai77:20210906020809p:plain

Tutorialでは顔は灰色、体は緑色のようにきちんと色分けされて表示されていますが、私のは、全部の色が混じっています。

出来てないですね。

しかしこれ以上の解決策もないのでこれで続けてみます。

更にTutorialでは二つの問題点、

  • Spriteが四角な事
  • Spriteが常にカメラを向いている事

を述べています。

拡大してみると私のも四角になっていて常にカメラ側を向いています。

f:id:kazuhironagai77:20210906020846p:plain

この常にカメラ側を向いているのは簡単に直せるそうです。

Sprite Renderer ModuleのAlignmentとFacing Modeの値を以下の様に変更するだけだそうです。

f:id:kazuhironagai77:20210906020902p:plain

すると

f:id:kazuhironagai77:20210906020926p:plain

Meshに沿ってSpriteの面が貼られています。

これで出来るのはParticle Update SectionでUpdate Mesh Reproduction Sprite Moduleがあるからだそうです。

f:id:kazuhironagai77:20210906020944p:plain

うーん。成程。

今度は、Spriteを丸くします。

Tutorialを見ると以下のコードをOpacity Maskに繋いでParticle ColorのRPGをEmissive Colorに繋いでいます。

f:id:kazuhironagai77:20210906021014p:plain

それのやり方が分からないので以下の様にしてみました。

f:id:kazuhironagai77:20210906021038p:plain

Tutorialの結果を見るとこんな感じです。

f:id:kazuhironagai77:20210906021054p:plain

私のはこんな感じでした。

f:id:kazuhironagai77:20210906021111p:plain

出来ている?

今度は色を表示させます。

Particle Spawn Sectionの

f:id:kazuhironagai77:20210906021125p:plain

Initialize Particle ModuleのColor を黒にします。

f:id:kazuhironagai77:20210906021140p:plain

色が表示されました。

f:id:kazuhironagai77:20210906021154p:plain

此処の理屈は全く分かりません。

近づいて見ると確かにSpriteが丸くなっています。

f:id:kazuhironagai77:20210906021208p:plain

流石にもうNiagaraをやっている時間ではなくなってしまいました。残りは来週やります。

2.4 別なTutorialをやった感想など

公式のTutorialを途中までやったわけですが、やっぱりしっかりと生徒の事を考えた作りになっています。4.26になってCrunchのMaterialが変更された点を除けば、ほとんどTutorialの言っている事は分かりました。分からない部分でもTutorialの指導通りに付いて行く事は出来ました。

CGHOW氏のTutorialでもありましたがVersionの変化によってやり方が変わってしまうのは、仕方ない事なのかもしれません。

結論は来週、このTutorialを終えてから考えます。

3.Cascade: 今週の続き

今週はNiagara に時間を使い過ぎたのでCascadeの勉強はお休みします。

4.Item Spawn Dataの複製

Item Spawn Dataは先週、検討した結果、元に使用しているStructに新しい要素を追加する事で、色々なMapに生成するItemを一括で管理する事にします。

その後で、RPGGameInstanceにあるItem Spawn DataにMap1とMap1_Test、更にLandscape4用に分けたSpawn するItemのDataを追加します。

次にそれぞれのLevel BPに配置されているSpawn Items 関数を改良してそのMapに必要なMonsterだけSpawnするようにします。

f:id:kazuhironagai77:20210906021257p:plain

Pick up Item WidgetのRemove Picked Item()関数も改良が必要です。

この関数はItemをPlayerが操作するキャラが拾った時にItemを消します。

f:id:kazuhironagai77:20210906021315p:plain

先週、この関数の検討する事を忘れていました。

あと改良が必要な場所は、

Priest_Welcome WidgetでSaveをする時

f:id:kazuhironagai77:20210906021331p:plain

Start Menu WidgetからLoad する時

f:id:kazuhironagai77:20210906021346p:plain

の2か所です。

4.1 StructであるItem Spawn Dataの書き変え

それではStructであるItem Spawn Dataを書き換えます。

f:id:kazuhironagai77:20210906021409p:plain

先週の検討では、Structに要素を追加すると一回Editorがクラッシュしますが、再起動すればそのStructを使用しているArrayはデータを失わずに新しい要素も追加されていました。

試します。

LevelNameを追加しました。

f:id:kazuhironagai77:20210906021434p:plain

Editorを再起動してStructのItem Spawn Dataを開きます。

f:id:kazuhironagai77:20210906021454p:plain

前に追加した要素であるLevelNameは存在しています。

今度はRPGGameInstanceを開きます。

f:id:kazuhironagai77:20210906021554p:plain

なにこれ?

LevelNameの下にIsWeapon、ItemName、そしてMemberVer_20 があります。

更にItemNameにMap1が指定されています。

もう一度StructのItem Spawn Dataの要素を確認します。

f:id:kazuhironagai77:20210906021615p:plain

うわ、追加したLevelNameの下にもっと沢山の要素がありました。

しかも個々のデータがDefault値に変更されています。

せめて前のDataのScreen Shotをとっておくべきでした。

痛恨のミスです。

大体の値を入れて見ました。

f:id:kazuhironagai77:20210906021655p:plain

Map1_TestのLevel BP内で使用している関数、Spawn Itemsの実装を直します。

f:id:kazuhironagai77:20210906021711p:plain

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

Start Menu WidgetがCompile出来ないとErrorが出ました。

f:id:kazuhironagai77:20210906021726p:plain

直しました。

指定した位置に武器とItemが生成されています。

f:id:kazuhironagai77:20210906021744p:plain

f:id:kazuhironagai77:20210906021753p:plain

これでは見にくいのでStructのItem Spawn Dataを直します。

後、最後のMemberVer_20が何をしているのか不明なのでそれも調べます。

f:id:kazuhironagai77:20210906021810p:plain

調べた結果MemberVer_20は何もしていませんでした。消します。

Structの並びは以下の様にしました。

f:id:kazuhironagai77:20210906021825p:plain

またRPGGameInstanceのItem Spawn DataのDataが消えています。

f:id:kazuhironagai77:20210906021842p:plain

そらそうだ。

でも焦っても仕方ないです。ゆっくり直していきます。

直しました。

f:id:kazuhironagai77:20210906021918p:plain

f:id:kazuhironagai77:20210906021933p:plain

BPの見た目もそれなりですが綺麗にしました。

f:id:kazuhironagai77:20210906021951p:plain

4.2 それぞれの関数の直し

<Pick up Item WidgetのRemove Picked Item()関数の変更>

f:id:kazuhironagai77:20210906022013p:plain

最初から直っていました。

<Priest_Welcome WidgetでSaveをする時>

f:id:kazuhironagai77:20210906022034p:plain

これは直す必要無かったです。

<Start Menu WidgetからLoad する時>

これも勝手に直っていました。

f:id:kazuhironagai77:20210906022054p:plain

これで全部直したはずです。

テストします。

f:id:kazuhironagai77:20210906022120p:plain

Itemを拾おうとしたら拾えません。更にItemのイメージなどの詳細も表示されていません。

Errorがこんなに。

f:id:kazuhironagai77:20210906022138p:plain

直します。

Errorの理由が分かりました。Dropped Item Base BPで変数NameとItem Nameが同じDataを保持してるだけだったのでItem Nameに統一してNameは消去しました。

しかしPickup Item WidgetでDropped Item Base BPからNameの値にアクセスしていました。それがErrorを起こしました。

Dropped Item Base BPで変数Nameを消す前にこの変数を使用している箇所を検索でチェックはしましたが、Widgetはその検索から外れていたようです。

Errorが表示されている箇所が全部直しました。

今度はItemの説明が絵入りで説明されています。

f:id:kazuhironagai77:20210906022156p:plain

今度は装備するために装備画面を開いたら武器の名前が表示されていません。

f:id:kazuhironagai77:20210906022219p:plain

されるときもあります。

f:id:kazuhironagai77:20210906022249p:plain

なんで?

あっ。

Itemの発生位置を確認するために静的に配置したDropped Item Base BPを消すのを忘れていました。

全く同じ位置に二つの別々なdataを持つDropped Item Base BPが配置されていました。

JoJoを読んでいた時に、全く同じボートを二つ重ねて戦う敵がいてそれの何が強いのかと不満に思った事が昔ありました。しかし全く同じBPが2個重なっていた今回のErrorは直すのが本当に大変でした。

本当に強敵でした。

SaveやLoadの時も確認します。

回復薬だけ拾った状態でセーブしました。その後、ゲームを終了して新しいゲームを開始しLoadしました。

f:id:kazuhironagai77:20210906022320p:plain

回復薬だけ無くなっています。

出来ています。

4.3 それぞれのLevelでSpawn するItemが変更出来る様にする

Map1_TestのLevel BPのSpawn Items関数に以下のコードを追加しました。

Map1_TestのみにItemがSpawnするようにしてテストします。

f:id:kazuhironagai77:20210906022549p:plain

結果です。

f:id:kazuhironagai77:20210906022608p:plain

出来ていますね。

あ。

大きなバグを一個見つけてしまいました。ItemのSpawnを武器の種類の名前で管理していましたが、それぞれの武器に固有の名前をつけないとその種類の武器が全部消えてしまいます。

こんな風に短剣(小)が3つ配置されていたとします。

f:id:kazuhironagai77:20210906022637p:plain

一個だけ短剣を拾います。

f:id:kazuhironagai77:20210906022654p:plain

これをすると別なmapに移動して戻って来た時に全部のItemが消えるはずです。

テストします。

f:id:kazuhironagai77:20210906022750p:plain

やっぱり全部消えていました。

5.バグ直し

このバグを直すためには、Dropped Item Base BPの全てのInstanceに固有の名前が必要になります。

またStructのItem Spawn Dataを直す必要があります。

f:id:kazuhironagai77:20210906022808p:plain

それぞれのInstanceの固有の名前は、Own Nameにします。

と言う事はまたDataが消えてしまうわけです。

今度はここにDataを記録しておきます。

f:id:kazuhironagai77:20210906022834p:plain

Item Spawn Dataを使用している全てのBPとWidgetをチェックしていきます。

5.1 Item Spawn Dataを使用している全てのBPWidgetのチェック

<Pickup Item WidgetのRemove Picked Item関数>

消去するItemのDataをItem Spawn Dataから探している所です。

f:id:kazuhironagai77:20210906022910p:plain

現状ではItem Nameを比較していますが、Own Nameを比較する必要があります。

<Priest Welcome WidgetのSet Item Spawn Data関数です。>

Item Spawn Dataの中からSaveしなければならないDataをCopyしています。

f:id:kazuhironagai77:20210906022956p:plain

これは変更する必要はありません。

<Start Menu WidgetのChange Item Spawn Data in Game Instance関数>

これはSaveしたDataをGame InstanceのLoadする時に使用する関数でItem Spawn Dataの管理をしています。

f:id:kazuhironagai77:20210906023054p:plain

これも変更する必要はありませんね。

<Map1 Level BP の Spawn Items 関数>

これはMap1を開いたときにItemを生成する関数です。

f:id:kazuhironagai77:20210906023120p:plain

これも特に変更する必要はありませんね。

<Map1_test Level BP の Spawn Items 関数>

これはMap1と全く同様の関数なので変更する箇所はないです。

f:id:kazuhironagai77:20210906023140p:plain

はい。これで全部調べ終わったと思ったら違いました。

Dropped Item Base BPにもOwn Nameを保持する変数が必要になります。

そうする事でPickup Item WidgetのRemove Picked Item関数がDropped Item Base BPに新しく追加する変数、Own Nameにアクセス出来るはずです。

確認します。

Pickup Item WidgetのRemove Picked Item関数で使用しているDropped Item Base BPのObjectであるMy Dropped Itemを追っていきます。

f:id:kazuhironagai77:20210906023206p:plain

この変数はPickup Item Widgetを作成した時に値をAssignされています。

f:id:kazuhironagai77:20210906023225p:plain

なのでThird Person Character BPでこのWidgetを作成する所を調べます。

f:id:kazuhironagai77:20210906023242p:plain

なんとGame Mode BPの値をパスされています。

このGame Mode BPの値がいつAssignされるのかを調べたら、Third Person Character BPのTrigger Box内にPlayerが操作するキャラが侵入した時でした。

となるとPickup Item WidgetのRemove Picked Item関数は、Dropped Item Base BPに新しく追加する変数、Own Nameにアクセス出来ますね。

本来なら来週直しますが、今週はあんまり進まなかったのでこれもやる事にします。

5.2 直し

StructのItem Spawn Dataに新しい要素であるOwnNameを追加します。

f:id:kazuhironagai77:20210906023326p:plain

今度は、ここでUE4Editorを閉じずにRPG Game Instance BPを開きCompileしてSaveします。

するとRPG Game Instance BPのItem Spawn Dataの値が以下の様に変化しました。

f:id:kazuhironagai77:20210906023350p:plain

あれ。

Dataを失う事なく新しい要素の追加に成功してます。

うーん。何で今回は成功したんでしょうか?

それぞれのItemに名前を付けていきます。

f:id:kazuhironagai77:20210906023415p:plain

出来ました。

不安なので一回、UE4Editorを再起動します。

RPG Game Instance BPのItem Spawn Dataの値は変更した状態のままです。出来ています。

Dropped Item Base BPにOwn Name変数を追加します。

f:id:kazuhironagai77:20210906023436p:plain

Map1_Test Level BPのSpawn ItemでDropped Item Base BPのInstanceを動的に作成する時に

f:id:kazuhironagai77:20210906023458p:plain

Own ItemのDataをパスします。

<Pickup Item WidgetのRemove Picked Item関数>

Dropped Item Base BPのInstanceにassignされたMy Dropped Item 変数からOwn Nameのデータを取り出してRPG Game Instance BPにあるDataと比較するようにします。

f:id:kazuhironagai77:20210906023536p:plain

<Start Menu WidgetのChange Item Spawn Data in Game Instance関数>

これは変更する必要はありませんが念のため確認しておきます。

f:id:kazuhironagai77:20210906023600p:plain

線が外れていたので直しました。

<Map1 Level BP の Spawn Items 関数>

これは先程直しました。

<Map1_test Level BP の Spawn Items 関数

こっちも直していました。

テストします。

Map1に短剣(小)が3本配置されています。

f:id:kazuhironagai77:20210906023642p:plain

一本だけ拾いました。

f:id:kazuhironagai77:20210906023714p:plain

銀河鉄道に乗ってLandscape4に行って帰って来ました。

f:id:kazuhironagai77:20210906023738p:plain

同じ種類の武器が全部消える事はなく拾ったItemだけ消えています。

出来ました。

5.3 Storyの作成

これでMap1とMap1_Testが分割出来ました。これからテストする時はMap1_Testで行い、RPGの方がMap1で制作していきます。

6.Loading Screenの勉強の続き

6.1 先週の勉強の確認

Load Stream Levelノードの使用方法については完全に理解しました。Sub LevelつまりStream Levelの使用方法も大体理解出来ました。

Level Streaming Volumeを使用する場合は良く分かりません。これは今週勉強します。

Load Stream Levelノードを使用したLoading Screenの勉強も今週勉強します。HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [8]を勉強します。

6.2 Level Streaming Volumeを使用する場合

公式のDocumentであるStream Sublevels with Level Streaming Volumes [9] を勉強します。

後、Unreal Engine JPのTutorialで「猫でも分かる UE4を使ったゲーム開発 超初級編 #8 タイトルからゲームメインへのレベル遷移を作ってみよう!」[10] の1:25頃から実際にLevel Streaming Volumeを使用したStream LevelのLoad方法の実演がありました。

私はあんまり日本語のUEのTutorialは見ないんですが、内容がそのものズバリだったのと、YouTubeのお勧めにしつこく登場したので見たらかなり良かったです。

先週、以下に示した様に「View Port(View Pointと書いていますがView Portの事です。)内にLevel Streaming Volume が一寸でも入ったらStream Levelが生成される。」と書きましたが、

f:id:kazuhironagai77:20210906023828p:plain

この動画をみるとカメラ自身がLevel Streaming Volume内に侵入した時に初めてStream Levelが生成されるようです。ここは良く確認します。

6.3 Stream Sublevels with Level Streaming Volumes [9] を勉強します。

< Level Streaming Scenario >

Sun Temple projectを使用して説明するとあります。私はLevel Streaming Volumeの設定の仕方さえ理解出来れば良いので、敢えて同じProjectでやる必要は感じないですが、一応このProjectを探して見ます。

ありました。

f:id:kazuhironagai77:20210906023850p:plain

無料なのでもらっておきます。

試しに開いて見たらTutorialと全く同じです。

f:id:kazuhironagai77:20210906023912p:plain

これを使用して勉強する事にします。

公式のDocumentに載っている写真と同じ位置を見つけました。

f:id:kazuhironagai77:20210906023941p:plain

ここまではこの先のpatio(中庭?)が見えないのでpatioをStream Levelに入れておいて

f:id:kazuhironagai77:20210906023957p:plain

Playerがこの辺に来たらLevel Streaming Volumeを起動させてpatioが生成されるようにするそうです。

f:id:kazuhironagai77:20210906024012p:plain

と書かれていますが、Persistent Levelしかないです。

f:id:kazuhironagai77:20210906024029p:plain

<Streaming In Levels with Volumes

うーん。やっぱり先週作成したヤツでやります。

f:id:kazuhironagai77:20210906024052p:plain

これのStream_2(床が配置されている)をLevel Streaming Volumeで起動させるようにします。

f:id:kazuhironagai77:20210906024108p:plain

Tutorialでは

f:id:kazuhironagai77:20210906024132p:plain

と書かれているので、Level Streaming VolumeをPersistent Levelに配置します。

f:id:kazuhironagai77:20210906024155p:plain

Tutorialに以下の様に書かれていました。

f:id:kazuhironagai77:20210906024211p:plain

と言う事はやっぱりcameraのViewにLevel Streaming Volumeが入った時じゃなくてCameraそのものが入った時に発動するみたいですね。

以下の図のLevelsの右側にあるオレンジ色になっている箇所をクリックするそうです。

f:id:kazuhironagai77:20210906024236p:plain

こんな画面が表示されました。

f:id:kazuhironagai77:20210906024251p:plain

あれ、TutorialのImageと全然違います。TutorialのImageは以下に示した様になっています。

f:id:kazuhironagai77:20210906024311p:plain

あ、分かりました。Stream Levelの方を選択しています。

Stream_2を選択しました。Tutorialと同じ画面が出て来ました。

f:id:kazuhironagai77:20210906024328p:plain

Streaming VolumesにElementを追加します。そこに先程作成したLevel Streaming Volumeをセットします。

f:id:kazuhironagai77:20210906024408p:plain

Level のセットはこれで終わりだそうです。

最後に、先程セットしたLevel Streaming VolumeをLevel画面から選択してDetail画面にあるStreaming UsageをSVB Visibility Blocking on Loadに変更します。

f:id:kazuhironagai77:20210906024428p:plain

これで出来ているそうです。

試してみます。

f:id:kazuhironagai77:20210906024445p:plain

現れませんね。

色々試したんですが理由が分かりません。

猫でも分かる UE4を使ったゲーム開発 超初級編 #8 タイトルからゲームメインへのレベル遷移を作ってみよう!」[10] でCameraがLevel Streaming Volumeに入っていなくてStream Levelが中々読み込まれなかったので、同じ理由かと思って以下に示したようにLevel Streaming Volumeをかなり大きくしたんですが駄目でした。

f:id:kazuhironagai77:20210906024514p:plain

ほとんど諦めかけてた時に、たまたま空を眺めたらStream_2 に配置してあるFloorが写りました。

f:id:kazuhironagai77:20210906024533p:plain

どうやらLevel Streaming Volumeの高さが足りなくてCameraがBoxに入っていなかったみたいです。

Level Streaming Volumeを高くしてみました。

f:id:kazuhironagai77:20210906024552p:plain

今度は普通にStream_2がLoadされました。

f:id:kazuhironagai77:20210906024813p:plain

6.4 Level Streaming VolumeとCameraについて

Particle SystemのGPUのBoundsはカメラの視界にBoundsが入ったらEffectを生成します。

これと同じ様にLevel Streaming Volumeも、カメラの視界にLevel Streaming Volumeが入ったら指定されたStream LevelをLoadするなら意味分かります。

が、なんでCameraがLevel Streaming Volumeに入った時にStream LevelをLoadする理由があるでしょうか?それならPlayerが操作するキャラがLevel Streaming Volumeに入った時で良いでしょう。

Level Streaming Volumeを作成する時に、最初は「カメラの視界にLevel Streaming Volumeが入ったらStream LevelをLoadする。」となってたのを誰かが間違えて「カメラがLevel Streaming Volumeが入ったらStream LevelをLoadする。」に変わっちゃったんじゃないでしょうか?

これってバグだと思います。

6.5 HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [8]を勉強します。

もうLevel Streamingの方法は十分理解したので今度はLoad Stream Level ノードを使用したLoading Screenの作成方法について勉強します。

軽くどんな感じなのか見たら、結構複雑です。

これは動画みただけじゃ再現するの無理じゃないか?と思ったらSource Codeが公開されていました。

f:id:kazuhironagai77:20210906024842p:plain

ただしSource CodeのVersionが4.9になっています。取りあえずこのSource CodeをDownloadして開けるか試してみます。

4.9をInstallしてSource Codeを開いて見ます。

f:id:kazuhironagai77:20210906024900p:plain

f:id:kazuhironagai77:20210906024907p:plain

開けました。このコードを参考にしながらやってみます。

まず、以下のLevelを使用しています。

f:id:kazuhironagai77:20210906024925p:plain

Persistent Levelには以下のStream Levelが追加されています。

f:id:kazuhironagai77:20210906024942p:plain

Persistent LevelのBPは以下のようになっています。

f:id:kazuhironagai77:20210906025019p:plain

この辺から作ってみます。

<準備編:Start ButtonのあるWidgetまでの作成>

Persistent LevelですがSource Codeを見るとAnimated Loading Persとなっていました。

更にSource Code ではAtmospheric Fog、BP Sky Sphere、Directional Lightが追加されていたのでそれも追加します。

f:id:kazuhironagai77:20210906025047p:plain

Source Code では空は青いですが、私のは真っ赤です。

調べるとSource Code ではBP Sky SphereのDirectional Light ActorにDirectional Lightがセットされていました。

f:id:kazuhironagai77:20210906025107p:plain

BP Sky SphereのDirectional Light ActorにDirectional Lightをセットしました。すると

f:id:kazuhironagai77:20210906025133p:plain

空が青くなりました。

この辺の設定は全然理解していません。後で勉強する必要がありますね。

次にPersistent LevelのBPを作成します。

f:id:kazuhironagai77:20210906025151p:plain

はい。いきなり来ました。Load Stream Levelノードです。先週、Streaming Levelをしっかり勉強したお陰でこのノードが何をやっているのかしっかり理解出来ます。TutorialではこのノードからAnimated Loading Splash Screen を呼び出しますが、まだAnimated Loading Splash Screenを作成していないので、作成してから呼び出せるようにします。

次のノードであるRemote Eventはどんな機能を持っているんでしょうか?初めて見るノードです。

f:id:kazuhironagai77:20210906025237p:plain

こんな説明されてました。

これだけだと良く分からないですね。TutorialでEvent Nameに記載されている名前はLoad Splash Screenとなっています。これってEventじゃなくてLevel名でしょう?

Source CodeのAnimated Loading Splash ScreenのLevel BPを開いたらなんとEvent Load Splash Screenがありました。

f:id:kazuhironagai77:20210906025304p:plain

うーん。成程。やっとPersistent Levelで何をやっているのかが分かりました。

Load Stream Levelノードでstream LevelであるAnimated Loading Splash Screenを作成して、それが終了した途端にAnimated Loading Splash Screen BPにあるEvent Load Splash Screenを実行するわけです。

でもこれだったらAnimated Loading Splash ScreenをOpen Levelノードで開いて、Animated Loading Splash ScreenのEvent Begin PlayでEvent Load Splash Screenを実行してもそんなに差がない気がします。

私が言いたい事は、ここではLoad Stream Levelノードの機能であるBackgroundでLevelをLoadする事が生かされていません。

多分、次のLevelでLoad Stream Levelノードを使用してBackgroundでLevelをLoadするんでしょう。取りあえずTutorialと同じのを作成していきます。

Animated Loading Splash ScreenをAnimated Loading PersのStream Levelとして作成しました。

f:id:kazuhironagai77:20210906025328p:plain

Source Codeで確認するとAnimated Loading Splash ScreenはAssetを全く持っていないLevelでした。あるのはEvent Load Splash Screenだけです。

Load Splash Screenの実装部はかなり色々な事をやっていますが、順番に実装していきます。

まず最初にUMG‐Splash Screen Widgetを開いています。

f:id:kazuhironagai77:20210906025347p:plain

UMG‐Splash Screen Widgetを見ると以下のImageをTextとImageで作成しただけのwidgetでした。

f:id:kazuhironagai77:20210906025407p:plain

これと同じ物を作成します。

f:id:kazuhironagai77:20210906025424p:plain

全く同じ物を作成しても面白くないので少しだけ変更しました。

f:id:kazuhironagai77:20210906025448p:plain

はい。ここまで出来ました。

次です。

f:id:kazuhironagai77:20210906025505p:plain

Animated Loading Main MenuをLoadしています。

このAnimated Loading Main MenuもAssetを何も持たないLevelでした。BPを開くと二つのEventだけが実装されていました。

f:id:kazuhironagai77:20210906025522p:plain

Animated Loading Main MenuのBP内の2つのEventは一端置いておいて、ここまでTutorialと同じ物を作成してみます。

Stream Level、Animated Loading Main Menuを作成します。

f:id:kazuhironagai77:20210906025543p:plain

f:id:kazuhironagai77:20210906025550p:plain

このStream LevelをAnimated Loading Splash ScreenのBPからLoad Stream Levelノードを使用して呼び出します。

f:id:kazuhironagai77:20210906025609p:plain

Animated Loading Splash ScreenのEvent Load Splash Screenの続きを追っていきます。

f:id:kazuhironagai77:20210906025635p:plain

先ほど表示したWidgetを外しています。これも実装します。

f:id:kazuhironagai77:20210906025653p:plain

次はRemote EventでLoad Main Menuを呼び出しています。

f:id:kazuhironagai77:20210906025711p:plain

これも実装してしまいましょう。

f:id:kazuhironagai77:20210906025729p:plain

しました。

では、一端、Animated Loading Splash ScreenのEventであるLoad Splash Screen Eventの作成は停止して、Animated Loading Main MenuのEvent Load Main Menuの作成をします。

f:id:kazuhironagai77:20210906025747p:plain

またWidgetを作成しています。正直こんなに複雑にする必要はない気がしています。どうなんでしょうか?完成したら見直してみます。

この部分だけ作成したらWidget、UMG Main Menuを作成します。

f:id:kazuhironagai77:20210906025805p:plain

まだUMG Main Menu WidgetがないのでErrorが表示されています。

UMG Main Menu Widgetを作成します。

こんな感じのDesignです。

f:id:kazuhironagai77:20210906025847p:plain

それぞれのButtonに実装されている機能はこんな感じです。

f:id:kazuhironagai77:20210906025906p:plain

f:id:kazuhironagai77:20210906025914p:plain

え。Game Instanceに新しい変数も作成しているの?

しかもやっとここからLoading する訳ですか。

ううん。

UMG Main Menu WidgetのDesign部分だけ作成しました。

f:id:kazuhironagai77:20210906025934p:plain

Animated Loading Main Menu のCreated Widgetに今作成したUMG Main Menu Widgetをセットします。UWidgetのタイプもUMG Main Menu Widgetに変更しました。

f:id:kazuhironagai77:20210906025958p:plain

Source code のAnimated Loading Main Menu の続きを見ると以下の実装をして終わっています。

f:id:kazuhironagai77:20210906030015p:plain

これは単純にCursorによるUIの操作のための実装ですね。

これも実装します。

f:id:kazuhironagai77:20210906030040p:plain

これでAnimated Loading Main Menu の実装が終わりました。

なので、Animated Loading Splash ScreenのEventであるLoad Splash Screen Eventの作成に戻ります。

f:id:kazuhironagai77:20210906030058p:plain

最後にUnload Stream Levelノードを追加するだけでLoad Splash Screen Eventの実装は終わりました。

どうなっているのか全体像が分からなくなってしまったので最初から見直します。

Animated Loading Persistent Levelの実装部です。

Load Stream LevelノードのLevel NameにLoadするLevelが指定されていませんでした。Animated Loading Splash Screenをセットします。

Remote Event NodeのEvent NodeにもLoading Splash Screenをセットします。

f:id:kazuhironagai77:20210906030119p:plain

次はAnimated Loading Splash Screen BPのLoading Splash Screen Eventをチェックします。

この部分はSource Codeと全く同じに作成されていました。

f:id:kazuhironagai77:20210906030136p:plain

このEvent はLoad Stream LevelでAnimated Loading Main MenuをloadしてEvent Load Main Menuを実行します。

この部分も完全にSource Codeと同じになっています。

ここまででテストしています。

f:id:kazuhironagai77:20210906030153p:plain

あれ、何も表示されません。

Load Stream LevelのMake Visible After Loadにチェックを入れるのを忘れていました。

f:id:kazuhironagai77:20210906030217p:plain

もう一度テストします。

Animated Loading Splash Screen LevelのLoad Splash Screen Load Eventが実行され以下のWidgetが表示されました。

f:id:kazuhironagai77:20210906030235p:plain

今度はLoad Splash Screen Load Event からAnimated Loading Main MenuがLoadされLoad Main Menu Eventが実行されました。

Load Main Menu EventでWidget UMG Main Menuが開かれ以下のUIが表示されました。

f:id:kazuhironagai77:20210906030414p:plain

はい。

ここまでは出来ていました。問題なのは肝腎のBackgroundによるLoading Screenの作成がこれからな所です。

HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [8]も見直しました。5分過ぎまでの説明部分が今までやった所と見事にシンクロしていました。

<本編:Start Buttonの実装>

Widget UMG Main MenuのStart ButtonがクリックされるとまずGame InstanceをAnimated Loading Game InstanceにCastしています。

f:id:kazuhironagai77:20210906030442p:plain

となると最初にAnimated Loading Game Instanceを作成する必要があります。

Source CodeのAnimated Loading Game Instanceを見るとName タイプのLevel To Load変数が追加されただけのようです。

f:id:kazuhironagai77:20210906030501p:plain

これを作成します。

Project SettingのMap and ModeのGame Instance ClassにAnimated Loading Game Instanceをセットします。

f:id:kazuhironagai77:20210906030525p:plain

Animated Loading Game Instanceが出来たので、Widget UMG Main MenuのStart Button のOn Click Event にCast 部分を追加します。

f:id:kazuhironagai77:20210906030549p:plain

更にLevel To Load変数の値を以下の様にセットします。

f:id:kazuhironagai77:20210906030605p:plain

これはセットしただけでは何とも言えませんね。

<本編2:Interfaceの追加によるEventの作成>

以下に示したようにAnimated Loading Map1もAnimated Loading PersistentのStreaming Levelではあります。

f:id:kazuhironagai77:20210906030648p:plain

次のノードが以下の様になっています。

f:id:kazuhironagai77:20210906030710p:plain

しかしLoad Next Streaming Levelを呼び出せません。

これが理由かどうか分かりませんが、Source CodeのLoad Next Streaming Levelには以下の印がついています。

f:id:kazuhironagai77:20210906030746p:plain

よく見たらUMG to Level BPというInterfaceをImplementしていてそのInterface内にLoad Next Streaming Level Eventがあるみたいです。

f:id:kazuhironagai77:20210906030803p:plain

f:id:kazuhironagai77:20210906030810p:plain

公式DocumentのBlueprint Interface [11] を参考にしてInterface、UMG to Level BPを作成します。

f:id:kazuhironagai77:20210906030836p:plain

中を開いてFunction名をLoad Next Streaming Levelに変更します。

f:id:kazuhironagai77:20210906030930p:plain

以上です。

更に公式DocumentのImplementing Blueprint Interfaces [12]を参考にして作成したInterface、UMG to Level BPをAnimated Loading Main MenuにImplementします。

f:id:kazuhironagai77:20210906030952p:plain

むむむ、

そしたらInterfaceの項にこの関数が表示されるようになりました。

f:id:kazuhironagai77:20210906031015p:plain

ここでLoad Next Streaming Levelを選択したままMouseを右クリックすると

f:id:kazuhironagai77:20210906031031p:plain

Implement Eventが表示されます。

それを選択すると、とうとうEvent Load Next Streaming Levelが表示されました。Source CodeのLoad Next Streaming Level Eventと同じ様に右上に謎のIconが付いています。

f:id:kazuhironagai77:20210906031102p:plain

更にEvent GraphにもEvent Load Next Streaming Levelが表示されました。

f:id:kazuhironagai77:20210906031118p:plain

今度はWidget UMG Main MenuのStart Button でLoad Next Streaming LevelをCall出来るようになりました。

f:id:kazuhironagai77:20210906031136p:plain

以下のコードを追加して本当にWidget UMG Main MenuのStart ButtonからAnimated Loading Main MenuのEvent、Load Next Streaming Levelが呼び出せるのか試してみます。

Start Buttonを押したら以下の文が表示されました。

f:id:kazuhironagai77:20210906031215p:plain

出来ています。

<本編3:InterfaceからのEventを使用する事で、LevelWidget間の連絡が出来る様にする>

何でInterfaceからEventをわざわざ作成するのかと思ったらWidgetから直接Level内のEventを呼び出す事が出来ないからなんですね。

分かりました。

今回のケースはStream Levelが変わるんですが、そうなるとGame Modeはどうなるんでしょうか?

Stream Levelが変わる度にGame Modeも新しく読み込まれたりするんでしょうか、それともPersistent LevelにセットされたGame Modeのみが実行されてStream Levelの切り替えの時はGame Modeには何の影響もないんでしょうか?

そう言えばHTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [8]のコメント欄に

f:id:kazuhironagai77:20210906031301p:plain

と書かれていました。

もしGame Modeがそのままならば、Game ModeにEvent Dispatcherを作成してWidgetからGame ModeのDispatcherを読んで、そのDispatcherの実装部をLevel BP内で行う方法でもWidgetからLevel BPのEventを呼び出せた気がします。

時間があったらこの方法で同じ事が出来ないか試してみます。

もしこの方法でも出来るのならどっちが効率良いのかについても検討したいです。勿論、時間があったらですが。

<本編4:Event Load Next Streaming Levelの実装>

Source CodeのEvent Load Next Streaming Levelの実装の最初の部分です。

f:id:kazuhironagai77:20210906031345p:plain

Animated Loading Loading ScreenをLoad しています。Animated Loading Loading Screenはまだ作成していません。

Source CodeのAnimated Loading Loading Screenを見ると、Assetを全く持たないStream Levelで以下のEvent のみが実装されています。

f:id:kazuhironagai77:20210906031425p:plain

それではAnimated Loading Loading Screenを作成します。

f:id:kazuhironagai77:20210906031507p:plain

Animated Loading Loading ScreenのBPにEvent Load Loading Screenも作成しました。(実装はしていません。)

そしてEvent Load Next Streaming Levelの実装の最初の部分を追加します。

f:id:kazuhironagai77:20210906031538p:plain

Animated Loading Loading ScreenのEvent Load Loading Screenの実装は後でするとして、Animated Loading Main MenuのEvent、 Load Next Streaming Levelの実装を先にやってしまいます。

実装の残りを以下に示します。特に新しい事はやっていないのでそのままCopyしてしまいます。

f:id:kazuhironagai77:20210906031600p:plain

Animated Loading Main Menu LevelからAnimated Loading Loading Screen LevelのEventのAccessは、Stream Levelから別なStream LevelのEventへのAccessなのでRemote Event ノードで可能です。

これだけ似たような名前があるとSpell Missが心配です。後でErrorが出たらSpell Missを最初にチェックする事にします。

<本編5:Animated Loading Loading ScreenのEvent Load Loading Screenの実装>

Streamの名前はLoading Loading Screenですが、Eventの名前はLoad Loading Screenなんですね。ややこしいです。

それは兎も角、Animated Loading Loading ScreenのEvent Load Loading Screenの実装をします。

Source Codeの最初の部分です。

f:id:kazuhironagai77:20210906031711p:plain

UMG Loading Screen Widgetを作成します。

Source Codeをみるとこんな感じです。

f:id:kazuhironagai77:20210906031837p:plain

BPには何も実装されていません。

こんな感じに作成しました。

f:id:kazuhironagai77:20210906031922p:plain

Circular Throbberは初めて使用するWidgetです。

Throbberって初めて聞く単語だったので意味を調べたら、Loading Iconって出て来ました。そのものずばりですね。

Circular Throbberのサイズや色の調整方法が分からなかったのでSource Codeの値を参考にしました。

f:id:kazuhironagai77:20210906032106p:plain

Source Codeの値を参考にしましたが、弄っている内に大体の意味は分かりました。

Widgetが完成したのでAnimated Loading Loading ScreenのEvent Load Loading Screenの実装の続きをやっていきます。

f:id:kazuhironagai77:20210906032123p:plain

出来ました。

次の部分の実装をみます。

f:id:kazuhironagai77:20210906032139p:plain

ここでGame Instanceに保存したLevel名を使用するんですね。このままCopyします。

f:id:kazuhironagai77:20210906032156p:plain

残りの部分を実装します。

f:id:kazuhironagai77:20210906032216p:plain

Remote Event 関数でAnimatedLoadingMap1のEventであるLoad Levelを呼んでいますが、もしGame Instance のLevel to LoadがAnimatedLoadingMap1じゃない時はどうするんでしょうか?

因みに、AnimatedLoadingMap1のLoad Levelでは以下のコードが実装されています。

f:id:kazuhironagai77:20210906032241p:plain

AnimatedLoadingMap2を見たら、実装内容は全く違いましたが同じ名前のEventがありました。

f:id:kazuhironagai77:20210906032446p:plain

このTutorialではAnimatedLoadingMap1かAnimatedLoadingMap2しか呼ばないのでこのやり方で良いのかもしれませんね。

後、一番最後のノードでAnimated Loading Screenと指定されていますがそんなLevelはないですし、このEventが実装されているLevel BPを閉じるのが目的なはずですからAnimated Loading Loading Screenが正しいと思います。

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

f:id:kazuhironagai77:20210906032507p:plain

Tutorialの解説を見ると、実際のゲームではLoad するStream Levelの数が10や20になる場合もあってそれにも対応出来るように実装されている事が分かりました。

<Remote Eventについての考察>

Remote Event ノードは今回初めて知ったんですが、これかなり面白い機能ですよね。

Polymorphismの機能に似ていますが、同名のEventなら全く別なLevelからでも呼び出せる所が違います。

Polymorphismにはコードを簡易にする機能がある代わりに実際のDataが継承したどのクラスのメンバー関数を使用しているのか分かりにくくする欠点もあります。しかし現実問題としてPolymorphismを使用しないでコードを書く事は不可能な訳です。このRemote Event ノードの機能は、そんなPolymorphismの欠点を補える可能性を感じました。

<AnimatedLoadingMap1の作成>

流石に時間が無くなってしまったので残りは来週やる事にします。このTutorialは今週中に終わらしたかったんですがどうやってももう無理です。

Tutorialの10:36の所までやりました。

7.Good Skyの復習

当然、来週以降やる事になります。

8.まとめと感想

時間がもうないのでまとめもなしです。

9.参照(Reference

[1] Rimaye. (n.d.). ð¨ UE4 - Niagara VFx Tutorials [ Stylized ] ð FR voice - English Explanations ð¨. YouTube. Retrieved September 5, 2021, from https://www.youtube.com/playlist?list=PLvYJUGYt8abH6GK8d6zGjaMLiFgqvmV-s

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

[3] Epic Games. (n.d.-e). Niagara Visual Effects. Unreal Engine Documentation. Retrieved September 5, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Niagara/

[4] Epic Games. (n.d.-d). Niagara Quick Start. Unreal Engine Documentation. Retrieved September 5, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Niagara/QuickStart/

[5] Epic Games. (n.d.-b). Create a Sprite Particle Effect in Niagara. Unreal Engine Documentation. Retrieved September 5, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Niagara/HowTo/SpriteEffect/

[6] gameDev Outpos. (2020, July 30). UE4 - Introduction To Niagara [Video]. YouTube. https://www.youtube.com/watch?v=VEG-Xp92cBk&list=PLomQNLPOWtzYXU_pRIUVVEV9uY7bjENZ5&index=1

[7] Epic Games. (n.d.-f). Particle Spawn Group. Unreal Engine Documentation. Retrieved August 31, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/ParticleSpawn/

[8] Wadstein, M. [Mathew Wadstein]. (2015, October 31). HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=QJVn2mW67YQ

[9] Epic Games. (n.d.-g). Stream Sublevels with Level Streaming Volumes. Unreal Engine Documentation. Retrieved September 5, 2021, from https://docs.unrealengine.com/4.26/en-US/BuildingWorlds/LevelStreaming/HowTo/StreamWithVolumes/

[10] Epic Games [Unreal Engine JP]. (2020, August 28). 猫でも分かる UE4を使ったゲーム開発 超初級編 #8 タイトルからゲームメインへのレベル遷移を作ってみよう! [Video]. YouTube. https://www.youtube.com/watch?v=7ianEtjiWVI&list=PLr_Cbd4sUDTzbVjg1Bsm5s_21uPQ4xHLx&index=8

[11] Epic Games. (n.d.-a). Blueprint Interface. Unreal Engine Documentation. Retrieved September 3, 2021, from https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/Blueprints/UserGuide/Types/Interface/

[12] Epic Games. (n.d.-c). Implementing Blueprint Interfaces. Unreal Engine Documentation. Retrieved September 3, 2021, from https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/Blueprints/UserGuide/Types/Interface/UsingInterfaces/

 

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する Map1の複製の作成など

f:id:kazuhironagai77:20210830001334p:plain

<前文>

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

<専門家や上司に対する考え方の違い>

これはキリスト教でもプロテスタントが主流のアメリカ特有の話なのかもしれませんが、アメリカ人は専門家の話を信用しません。自分がどう思うかが重要でその判断を下すのに専門家の意見は参考、あくまで参考にしますが、頭ごなしに信用する事は絶対にありません。

大多数の常識のある日本人が専門家の意見を自分の考えより優先させるのと対照的です。

先週話した通り、アメリカを含めたキリスト教文化圏の教育システムは、質問、考える(調べる)、回答、で組み立てられてます。

この考えた結果の回答が、質問した司祭が用意していた回答と違っていた事から喧嘩になって、戦争になって最終的には、国を追い出されてアメリカと言う壮大な国が建国される羽目になったわけです。

それがみんなが良く言う「元々、プロテスタントの人達は、カソリックの司祭の言う事に対して、盲目的に聞く事を良しとせず、納得いく答えを貰うまで抗議したが、最終的には国を追い出されて住む場所がなくなって仕方なくアメリカ大陸に移民したのが始まりです。」な訳です。

だからアメリカ人は、少なくとも私が会った全てのアメリカ人がそうだったですが、絶対に自説を曲げません。そして自分の思った正しい事を実行します。子供でも老人でも例外はありません。

「自分では悪いと思っても会社の命令なので…」なんて考えるアメリカ人は(少なくとも私が会った全てのアメリカ人に関しては)絶対にありません。

日本人にはにわかには信じがたい話ですが、そうなんです。

そしてここからが大切な話になります。

大多数の日本人が、私が今した話が信じられないように、アメリカ人もまた「自分では悪いと思っても会社の命令なので…」と考える人がいるなんて信じられないんです。

最近のコロナに関しても日本のコロナの専門家で世界の大多数の専門家の意見と180°反対の意見を言っている人達がいましたが、アメリカ人はそんな専門家がいる事自体はまあ信じられるんですが「専門家が言ったから、自分では間違っていると思ったけど聞くしかなかった。」と考える人がいる事は絶対に信じられません。

喫煙なんか特にそうです。

ここまで書いて、専門家の意見と会社や上司の意見がゴッチャになってしまっている事に気が付きましたが、言わんとする事は一緒で、自分の意思より優先する他人の意見が存在するか否かです。

アメリカで、絶体絶命な事態になった時に「上司に言われたからそうした。」とか「専門家がしろと言った。」という言い訳はあまり通じません。と言うか日本人がそこから感じる深刻さは全くアメリカ人には理解出来ません。

此処まで説明した通り、アメリカ人には「自分では悪いと思っても会社の命令なので…」と言う発想がないからです。

じゃどうすれは、アメリカ人に「自分は悪くないのに上司や専門家によって強制されてやらされているだ。」っと暗にほのめかす事が出来るのかと言う事ですが、

まず「法律で決まってる。」と主張する事です。

法律で定められていたら「この人は悪くないけど強制されているんだ。」感がアメリカ人にもぐっと伝わります。

でもそんなに都合のよい法律なんでないですよね。

で次の策ですが「(不本意ながら)契約があるのでやらざる得なかった。」です。

これはどんな場面でも言えて「この人は悪くないけど強制されているんだ。」感はぐっと広がります。

はい。

「何でそんな事をしたんですか?」とアメリカ人から尋問される窮地に陥った場合「上司に言われたからそうした。」とか「専門家がしろと言った。」と心に浮かんだらそれをそのまま言うのはちょっと待って下さい。

そして私がここに書いている内容を思い出して「法律で決まってる。」もしくは「契約があるのでやらざる得なかった。」と言い換える事にしましょう。

そうする事で貴方を尋問しているアメリカ人たちも貴方の置かれた立場は複雑で本当のBad guyは別にいる事が何となく理解出来るはずです。

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

<本文>

1. 今週の予定

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

  • Particle Systemの勉強
  • RPGの作成
    • Map1の修正の続き
    • Loading Screenの勉強の続き
    • Good Skyの復習

2.Niagara の勉強

今週は何を勉強するのか、まだ決めていません。

2.1 CGHOW氏のTutorial [1]をみる

CGHOW氏のTutorial [1]をみたら沢山のシリーズがありました。

f:id:kazuhironagai77:20210830001534p:plain

先週、勉強したのは以下のTutorialシリーズに含まれるもので、他のTutorialシリーズとどう違うのかが良く分かりません。

f:id:kazuhironagai77:20210830001602p:plain

それぞれのTutorialシリーズがどんな内容なのかを軽く調べる事にします。

For Patreon

これはCGHOW氏をPatreonで支援している人達のために作成されたTutorialのシリーズのようです。

f:id:kazuhironagai77:20210830001622p:plain

Patreonってずっとパトロンの英語名だと思っていたんですが、パトロンの英語はPatronでした。

Patreonのメンバーになるための会費はいくらなのかも一応調べておきます。

f:id:kazuhironagai77:20210830001649p:plain

一番安いのはひと月5$で一番高いのでも20$ですね。

UEのVFXの専門家になる人は絶対勉強すべきですが、私はどうしましょう。

取りあえずはFreeの教材だけで勉強します。

UE4 HLSL

f:id:kazuhironagai77:20210830001718p:plain

一番最初のTutorialをみると、HLSLの基本をUE5 のNiagaraを使用して作成する方法を教えるTutorialだそうです。ここではUE4と書かれていますが、UE5と言っていますね。

大変興味深いです。

最初にShadertoy [2]と言う名前のサイトの紹介がありました。

f:id:kazuhironagai77:20210830001741p:plain

何これ。初めて知りました。

ここに自分で作成したShaderを載せる事が出来るんでしょうか?

これは後で読んで置く事にします。

同じような別のサイトも紹介されていました。こちらはvertexshaderart.com [3]と言う名前のサイトです。

f:id:kazuhironagai77:20210830001756p:plain

こんなサイトが有ったんですね。

ひょっとして日本語でも同様のサイトがあるんでしょうか?

探したらありそうですね。

WebGLが生まれてもう10年経ったんでしたっけ。こんな所で花を咲かせていたんですね。感動です。

一番最初のTutorialをもう少しだけみると以下に示したCustom Hlslノードの使用方法についての解説をしています。

f:id:kazuhironagai77:20210830001812p:plain

多分ですがこのTutorialシリーズはこのCustom HLSLの書き方についてのTutorialだと思います。

面白そうですが、この辺はNiagaraの基本を理解した後で、勉強すれば良いと思います。

<Introduction to Niagara

f:id:kazuhironagai77:20210830001830p:plain

これは私が先週、勉強したシリーズとどう違うのでしょうか?

f:id:kazuhironagai77:20210830001911p:plain

中身を見たら一目瞭然でした。Sprite、GPU Spriteと基本から教えています。

成程と思ったらCurl Noiseがありました。Curl Noiseって基本だったんですね。

f:id:kazuhironagai77:20210830001934p:plain

一番最初のTutorialが作成されたのが2020年でEmitterの形を見ると今のNiagaraとあんまし変わっていません。

f:id:kazuhironagai77:20210830002002p:plain

こっちのTutorialで勉強した方が楽かもしれません。

これか、公式のDocumentであるNiagara Visual Effects [4] 、

f:id:kazuhironagai77:20210830002017p:plain

もしくはgameDevOutpost氏のUE4-VFX [5] 、

f:id:kazuhironagai77:20210830002033p:plain

のどれかで勉強すればNiagaraの基本の勉強は十分でしょう。

RPG Game Effect in Unreal Engine Niagara

f:id:kazuhironagai77:20210830002055p:plain

マジですか?

一番私が勉強したいEffectじゃないですか?

後でじっくり見る事にしましょう。

Unreal Engine VFX (UE4 Niagara VFX)

f:id:kazuhironagai77:20210830002131p:plain

中を見ると同じTutorialが4個も5個も入っていてどんな基準でこのシリーズに分類されているのか良く分かりません。

TutorialだけじゃなくVFXを紹介しただけの短い動画も入っています。

Unreal Engine Effects in Marketplace

f:id:kazuhironagai77:20210830002206p:plain

これが私が先週、勉強したTutorialが載っていたシリーズですが、ここには今までCGHOW氏が作成したNiagaraのTutorialが全部入っているみたいですね。

364個のTutorialがあります。

Unreal Engine VFX Tutorial

f:id:kazuhironagai77:20210830002244p:plain

こっちはCascadeのTutorialも含まれていました。

Cascadeの勉強する教材が見つからないと思っていたらここに沢山ありました。

これは大発見です。

2.2 Intro to Niagara | Curl Noise | Point Attractor | Sine | Unreal Engine Niagara Tutorial [6] の勉強

本当はRPG Game Effect in Unreal Engine Niagaraシリーズのどれかを勉強したかったんですが、一個良さそうなのを開いて見たら、かなり複雑な事をサラッと済ましていたので止めました。

Introduction to Niagaraシリーズから勉強する事にします。

となるとやっぱり先週勉強したCurl NoiseについてのTutorialをやってみたいですね。

Intro to Niagara | Curl Noise | Point Attractor | Sine | Unreal Engine Niagara Tutorial [6]を勉強します。

Curl Noiseについては12分11秒当たりから解説が始まっています。

取りあえずそこだけ勉強します。

新しいNiagara systemを作成しCurl Noiseと名付けます。

TutorialのNiagara systemの作成方法はちょっと今のVersionとは違うみたいですね。

結果、以下に示したようなNiagara systemのStackのみが表示されているものが作成されていたので

f:id:kazuhironagai77:20210830002308p:plain

Empty Systemを選択して作成してみます。

f:id:kazuhironagai77:20210830002349p:plain

全く同じものが出来ました。

f:id:kazuhironagai77:20210830002402p:plain

次にDefault Emitterを追加しました。

何時もTutorialに使用しているヤツだそうですが、勿論、私には初耳です。

Tutorialに表示されたヤツをみるとRenderに何もセットされていませんが、全くModuleがないわけでもありません。

f:id:kazuhironagai77:20210830002420p:plain

どうせEmpty Emitterと同じだろうと思ってEmpty Emitterを作成したら全く違いますね。

f:id:kazuhironagai77:20210830002435p:plain

しかも今のVersionには無いModuleも結構使用しています。

仕方ないのでEmptyを代わりに使用して続行します。

RenderにSpriteを追加してMaterialにM_Radialを追加しています。

M_RadialがないのでEmptyにDefaultでセットされている

f:id:kazuhironagai77:20210830002502p:plain

をそのまま使用します。

Tutorialでは今度はSpawn Rate ModuleをEmitter Update Categoryに追加してSpawn Rateの値を200にセットします。

f:id:kazuhironagai77:20210830002523p:plain

こんな感じのイメージがReviewに表示されています。

f:id:kazuhironagai77:20210830002539p:plain

同様にSpawn Rateを追加してSpawn Rateの値を200にセットしてみます。

f:id:kazuhironagai77:20210830002554p:plain

うーん。まあいいですわ。次に行きます。

Add Velocity ModuleをParticle Spawn Categoryに追加します。

f:id:kazuhironagai77:20210830002609p:plain

f:id:kazuhironagai77:20210830002615p:plain

こんな感じです。

f:id:kazuhironagai77:20210830002631p:plain

大体、Tutorialのイメージと同じです。のでこれで行きます。

そしたら、Velocityは要らない。Random Momentumが欲しいとなってVelocityを消してしまいました。

TutorialによるとCascadeにはOrbit ModuleというRandom MomentumをParticleに追加出来るModuleがあるそうです。

f:id:kazuhironagai77:20210830002647p:plain

もしくはGPUに変えてVector FieldのLocal Vector Fieldを使用する方法もあります。

f:id:kazuhironagai77:20210830002704p:plain

Niagara Systemの場合は、それらの代わりにCurl Noise Force Moduleを使用します。

成程。

ここでCurl Noiseの登場ですか。

TutorialではPan Noise Fieldにチェックを入れて以下の設定にセットしています。

f:id:kazuhironagai77:20210830002718p:plain

こんな風に下の方のParticleがばらけています。

f:id:kazuhironagai77:20210830002734p:plain

同じ値で試してみます。

f:id:kazuhironagai77:20210830002757p:plain

下の方は僅かにばらけていますが、全体の形は微妙に違います。

Spawn Rateを20にまで落としたら以下の様に最後の部分がばらけるようになりました。

f:id:kazuhironagai77:20210830002811p:plain

でも何か違います。

Tutorialのは最後のばらけ方がランダムなんですが、私のは一直線です。

まあ、いいです。今回はTutorialと同じEffectを作成するために勉強しているのではなく、Curl Noise Force Moduleの使用方法を勉強するのが目的ですから。

うーん。

ちょっと結論から書いてしまうんですが、この後も色々な調整はするんですが、Curl Noise Force Moduleについての解説はこれだけでした。

これだけでは視聴者はCurl Noise Force Moduleの使用方法について全く理解出来ないですよね。

うーん。

CGHOW氏のTutorialは実際のNiagaraの実装について学ぶには良いのかもしれませんが、個々のModuleのロジックについては余りと言うか全然解説してくれてないですね。

例えば今回、私が知りたかったのは、先週意味が分からなかったFrequencyの機能ですが、全く何の解説もしてくれていません。

CGHOW氏のTutorialは勉強方法を考えないとそこから何も学べない事態になりかねないですね。

少しやり方を考えます。

2.3 Niagaraの勉強方法についての検討

まず、NiagaraというかUE4のParticle Systemを使用したVFXの勉強方法として私は、

  • 基本編と応用編に分けて勉強すべき
  • 基本編では、SpriteRibbonなどのそれぞれのRendering方法についての理解や個々のModuleの機能について理解する
  • 応用編では、どんなEffectが炎や氷のVFXを作成するために必要なのかを勉強し、具体的な作成方法を学ぶ。

と言う考え方で進めて来て、かなりNiagaraについても根本から理解出来て来ています。

例えばgameDev Outpost氏のUE4 – VFX [5] は私の言う基本編で勉強すべき内容と完全に一致しています。gameDev Outpost氏も明言はしていませんが、Niagaraの学習方法に対して私と同様の考え方を持っていると考えらます。

一方で、CGHOW氏は全く基本については説明しません。でもいつでも説明しない訳ではなく、例えば2021-08-16のブログで説明したように

f:id:kazuhironagai77:20210830002843p:plain

滅茶苦茶分かり易く説明する時もあります。

これ多分なんですが、CGHOW氏にとってはParticle Systemの基本なんでとっくの昔にマスターしちゃったんで、他の人がその部分が分からないって事に気が付いてないんだと思います。

もしくはアメリカの大学教授のように教え方が上手ければ年収何千万円もらえるならともかく、YouTubeで無料で教えるわけですから、そこそこ教えて後は自分で何とかしろみたいな感じなのかもしれません。

後、考えられるのは、インドでNiagaraの基礎だけ教えるTutorialを作ってもGame会社から評価されないってのもあるかと思われます。Game会社にとってはそれこそCurl Noiseの計算方法なんてどうでもよくて、最終Productだけ見せろって要求ばっかりしてくるので結果的にそうなってしまったのかもしれません。

まあ、どちらにしてもYouTubeで現状あるNiagaraのtutorialで最も優れたものの一つである事は間違いないですから、何とかしてこのTutorialを完全に理解出来るようにしたいです。

もう一つの問題としてNiagaraはまだ発展途上であってVersionが変わるとModuleもどんどん変化してしまう事が挙げられます。

これは理論的には、本当にModuleの機能を理解していれば多少の形が変化しても理解出来るはずですが、実際は無理でした。

それで特にですがCGHOW氏のTutorialをやる場合はVersionが同じNiagaraでやる方が良い気がします。

もう一つ、CGHOW氏のTutorialを勉強する時は、私の言う応用編を勉強する気持ちでやるべきかもしれません。基礎は凄く説明してくれている時もありますが無い時もあります。基礎を学ぶつもりで動画を見てて今回みたくほとんど説明がない事態に遭遇すると絶望感が半端ないです。

後、今まで勉強した内容を振り返る時なのかもしれません。

今 、見直したらParticle Systemの勉強を始めたのが2021-04-26のブログからです。丁度4カ月前です。一端、勉強した事を全部まとめて総括して、自分の足場を確認すべき時だと思います。

3.Cascadeの勉強

CGHOW氏のCascadeのTutorialが沢山ある事が分かったのでその内のどれかをやる事にします。

Unreal Engine Skull Aura Tutorial | Download Project Files [7] は約50分の動画と大変長いですが、他の動画と比べてよく説明しているみたいです。コメント欄に、此処までは出来たけどその先に進めません。とかもう少し詳しい解説をお願いします。みたいなのがあまりないからです。

出来る所までやっていきます。

f:id:kazuhironagai77:20210830002918p:plain

これを作成します。

3.1 最初のEmitterを作成する

まずMayaを使用して以下のSkullを作成しています。

f:id:kazuhironagai77:20210830002937p:plain

これは自分では作成出来ないので、球か立方体のStatic Meshで代用しましょう。

f:id:kazuhironagai77:20210830002951p:plain

Cubeで代用する事にします。

次にParticle Systemを作成してp_Skull_Auraと名付けています。

f:id:kazuhironagai77:20210830003005p:plain

全く同じ物を作成しました。

f:id:kazuhironagai77:20210830003158p:plain

名前をSkullsに変更した後、Data TypeをMesh Dataに変更します。

f:id:kazuhironagai77:20210830003213p:plain

しました。

ここまでは簡単ですね。

この調子で最後まで行ってくれるとうれしいです。

Mesh Data ModuleのMeshにSkullをセットしています。

f:id:kazuhironagai77:20210830003228p:plain

SkullのMeshはないので、Mesh Data ModuleのMeshに立方体のStatic Meshをセットします。

f:id:kazuhironagai77:20210830003244p:plain

あれ。Previewに何も表示されなくなりました。

以下に示した様に色を変えて見ましたが何も表示されません。

f:id:kazuhironagai77:20210830003259p:plain

此処でつまずくの?

色々調べた結果、元にしたCubeが大きすぎて写らないみたい事が分かりました。

うーん。しょうがない。

Infinity_Blade_AssetsにあったSkeleton Headを使用する事にします。

f:id:kazuhironagai77:20210830003313p:plain

f:id:kazuhironagai77:20210830003319p:plain

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

f:id:kazuhironagai77:20210830003335p:plain

これでいきます。

実際に配置してみたらこんなに大きいです。

f:id:kazuhironagai77:20210830003350p:plain

Initial Size Moduleなどで変更出来るんでしょうか?

25から5に下げて見ました。

f:id:kazuhironagai77:20210830003405p:plain

小っちゃくなっていますね。

f:id:kazuhironagai77:20210830003420p:plain

更に3まで下げて見ました。

f:id:kazuhironagai77:20210830003450p:plain

これでやってみます。

Initial Velocity ModuleのVelocityを以下の値にセットします。

f:id:kazuhironagai77:20210830003517p:plain

しました。

今度はSkullがCharacterの周りで回転するようにするそうです。

速度を以下のように変化させます。

f:id:kazuhironagai77:20210830003541p:plain

しましたが、何故したのかはまだ分かりません。

後、Locked AxesのXYZの意味が分かりません。

Spawn Rate ModuleのSpawnを以下のように変更しました。

f:id:kazuhironagai77:20210830003604p:plain

f:id:kazuhironagai77:20210830003609p:plain

Skullが一個だけ生成されるようになりました。

f:id:kazuhironagai77:20210830003630p:plain

Initial Velocity ModuleでLocked Axesの値をXYZにした理由が説明されていました。

f:id:kazuhironagai77:20210830003646p:plain

は、Locked AxesがNoneでx=2000、y=2000、z=2000の場合と同じだそうです。

そしてVelocity /Life Moduleを追加します。

f:id:kazuhironagai77:20210830003727p:plain

更にInitial Location Moduleを追加して

f:id:kazuhironagai77:20210830003750p:plain

Yに400を指定します。

f:id:kazuhironagai77:20210830003806p:plain

Velocity /Life ModuleのVelocity Over Lifeを以下の様にセットします。

f:id:kazuhironagai77:20210830003821p:plain

何でこれで骸骨が中心に対して公転するようになるのか今一分かりませんが、結果は

f:id:kazuhironagai77:20210830003857g:plain

回転してます。

ちょっとだけ2次元で考えてみます。

最初の状態は、x=2000、y=2000と同じであるとすると以下のようなベクトルになっています。

f:id:kazuhironagai77:20210830004038p:plain

これはt=0の場合、x=-1、y=0が乗算されます。つまりx=-2000、y=0になります。

f:id:kazuhironagai77:20210830004104p:plain

T=0.25の場合、x=0、y=1が乗算されます。つまりx=0、y=2000になります。

f:id:kazuhironagai77:20210830004119p:plain

T=0.5 の場合、x=1、y=0が乗算されます。つまりx=2000、y=0になります。

f:id:kazuhironagai77:20210830004141p:plain

T=0.75 の場合、x=0、y=-1が乗算されます。つまりx=0、y=-2000になります。

f:id:kazuhironagai77:20210830004156p:plain

最後にt=1 の場合、x=-1、y=0が乗算されます。つまりx=-2000、y=0になります。

f:id:kazuhironagai77:20210830004213p:plain

つまり最初に戻ります。

この考えで合っているかどうかは不明です。Tutorialの説明を見る限りはこの説明で正しい気はしています。

今度は骸骨の向きを変更します。

以下の動画を見ると分かりますが骸骨は常に正面を向いています。骸骨が外側を見るようにします。

f:id:kazuhironagai77:20210830004240g:plain

Required ModuleのScreen Alignmentの値をPSA Squareから

f:id:kazuhironagai77:20210830004306p:plain

PSA Velocityに変更します。

f:id:kazuhironagai77:20210830004321p:plain

すると骸骨が外側を見るようになりました。

f:id:kazuhironagai77:20210830004341g:plain

この辺の理屈は分かりません。

PSA Velocityと言うくらいだから、Meshが速度のVectorの向きに沿うようになると言う事なんでしょうか?

Cursorを重ねたら解説が表示されました。

f:id:kazuhironagai77:20210830004405p:plain

うーん。カメラに向かってと解説されていますがどのカメラに対して何でしょうか?

次にLife Time ModuleのLife Timeを以下の設定に変更して

f:id:kazuhironagai77:20210830004421p:plain

Required ModuleのDurationのEmitter Durationの値を以下の様に変更します。

f:id:kazuhironagai77:20210830004435p:plain

骸骨の回転がゆっくりになりました。

Tutorialと骸骨の向きが違いますね。

Tutorialでは骸骨は進行方向を向いていますが、私のは外側を向いています。

Tutorialの骸骨。進行方向をむいています。

f:id:kazuhironagai77:20210830004453p:plain

私の骸骨。外側を向いています。

f:id:kazuhironagai77:20210830004506p:plain

後で直し方は考えます。

次は骸骨の数を4つに増やします。

Required ModuleのDurationのEmitter Durationを1に戻します。

f:id:kazuhironagai77:20210830004519p:plain

これで骸骨が2つになります。

更にSpawn ModuleのRateの値を2にします。

f:id:kazuhironagai77:20210830004532p:plain

Spawn ModuleのBurstからは生成しないので0に戻します。

f:id:kazuhironagai77:20210830004545p:plain

結果です。

f:id:kazuhironagai77:20210830004559p:plain

4つの頭蓋骨が生成されています。

f:id:kazuhironagai77:20210830004639p:plain

この後はこの骸骨のためのMaterialを作成するそうなので微調整を行います。

まず、骸骨の回転が速すぎます。

Initial Velocity ModuleのStart Velocityの値を1000に変更します。

f:id:kazuhironagai77:20210830004654p:plain

骸骨が回転する円の半径が半分になってしまったので、Lifetime ModuleのLife Timeを倍の4.0にします。

f:id:kazuhironagai77:20210830004707p:plain

すると骸骨が8個になってしまったので、Spawn Rate ModuleのSpawnを1に戻します。

f:id:kazuhironagai77:20210830004721p:plain

こんな感じです。

f:id:kazuhironagai77:20210830004741g:plain

骸骨が一瞬だけ横を向くんですが、何なんでしょうこれ。後で直します。

骸骨の回転の中心がParticle Systemの中心と全然違う箇所にあります。

f:id:kazuhironagai77:20210830004819p:plain

この原因はInitial Location ModuleのLocationの値が400だからだと思います。

f:id:kazuhironagai77:20210830004835p:plain

これを‐400に直します。

f:id:kazuhironagai77:20210830004849p:plain

直りました。

実際のMap上で見ると骸骨、大きすぎます。

f:id:kazuhironagai77:20210830004903p:plain

サイズを半分にします。

f:id:kazuhironagai77:20210830004918p:plain

なんとサイズを半分にしたら回転の半径が二倍に増えてしまいました。

手前に写っている骸骨はサイズが半分に成っているにもかかわらず、カメラに前の2倍も近づいているため元の大きさと変わらないように見えます。

Initial Velocity ModuleのStart Velocityの値を500にします。

f:id:kazuhironagai77:20210830004934p:plain

やっぱり骸骨が一瞬だけ横を向くのは気になります。

骸骨の向きは、Required ModuleのScreen Alignmentによって指定されているはずです。

f:id:kazuhironagai77:20210830005009p:plain

そして現在、PSA Velocityに指定されているのでParticleのVelocityによってParticleの向きは決定されるはずです。

そのParticleのvelocityはInitial Velocity ModuleとVelocity/Life Moduleによって以下の様に指定されています。

f:id:kazuhironagai77:20210830005024p:plain

f:id:kazuhironagai77:20210830005030p:plain

ここでVelocity/Life Moduleの0の時の値と1の時の値を見ると、同じです。つまりParticleは重なるはずです。この時に何故か骸骨が一瞬だけ横を向くんバグが発生するんでしょうか?

分かりせんね。

今の知識ではまだ直せませんね。この問題は。

次に行きます。

3.2 Skull用のMaterialを作成する

Materialを作成します。名前はM_skullとします。

f:id:kazuhironagai77:20210830005052p:plain

Viewportの表示をskeleton Headに変更します。

f:id:kazuhironagai77:20210830005107p:plain

やり方は簡単で、skeleton Headを選択した状態で、

f:id:kazuhironagai77:20210830005121p:plain

ViewportのTeapotを選択します。

f:id:kazuhironagai77:20210830005137p:plain

以下に示した様にskeleton HeadのMeshが表示されます。

f:id:kazuhironagai77:20210830005150p:plain

この機能始めて知りました。これからはガンガン使用していきます。

後、ずっとPreviewと呼んでいましたがViewportが正しい名前でした。

f:id:kazuhironagai77:20210830005204p:plain

いきなりFresnelノードとLinear Interpolationノードを追加しました。

f:id:kazuhironagai77:20210830005219p:plain

更にMaterialの設定をTranslucent、Unlit、そしてTwo Sideに変更しました。

f:id:kazuhironagai77:20210830005240p:plain

Shading Modelの設定にUnlitがあるのは知りませんでした。

こっちがUnlitです。

f:id:kazuhironagai77:20210830005254p:plain

こっちはDefault Litです。

f:id:kazuhironagai77:20210830005308p:plain

結構違いますね。Default LitにはBase ColorとAmbient Occlusionがあります。

話は変わりますが、RPGGameに配置してるAssetで陰影が表示されないものがあります。

f:id:kazuhironagai77:20210830005322p:plain

前に調べた時、これらのAssetに使用されている全てのMaterialはNormalが指定されていない。

f:id:kazuhironagai77:20210830005336p:plain

からNormalがない事が原因ではないのか?

と推測しました。

でもShading ModelでUnlitが指定出来るならそれが原因かもしれません。それでそこを確認してみます。

f:id:kazuhironagai77:20210830005505p:plain

Default Litでした。Assetで陰影が表示されないものとこのShading ModelをUnlitにする事は関係なさそうです。

OpacityにConstant Nodeを繋げます。Constant Nodeの値は1にします。

f:id:kazuhironagai77:20210830005521p:plain

Emissive Colorには以下の実装を行いました。

f:id:kazuhironagai77:20210830005535p:plain

Materialはまだ本格的な勉強はしていないので、この形の実装も始めて見るものです。

Fresnelを使用していると言う事は端だけ表示される感じになるんでしょうか?

Viewportは以下の様になっています。

f:id:kazuhironagai77:20210830005601p:plain

うーん。想像とは全然違いました。

Fresnel Nodeについてちょっとだけ勉強します。

<Fresnel Node

Mathew Wadstein 氏のWTF Is? Material - Fresnel in Unreal Engine 4 [8] で勉強します。

まずFresnelの発音から解説しています。Sは発音しませんと言っています。あえてここで説明すると言う事はFresnelと言う名前はアメリカでは珍しいんでしょうか?

気になるので発音をもう少しだけ調べて見ます。IPAによる発音記号はfrəˈnɛlと記されていました。

Googleの発音では

f:id:kazuhironagai77:20210830005646p:plain

と表示されました。日本語で敢えて言えば、フレネェウって感じでしょうか?

日本語ではフレネルとなっていますね。かなり英語の発音には近いですね。フランス人ですので英語の発音に近かったとしてもだからどうしたと言う感じですが。

それでは肝腎の内容ですが、カメラに対してMeshのNormal Vectorが垂直に近づく程、値が大きく(1に近づく)ようになります。

以下の例で言えば、球の端の部分です。

f:id:kazuhironagai77:20210830005725p:plain

球の正面のNormal Vectorはカメラに対して水平だから値は0じゃないのか?なのに黒くないじゃないか?となりますが、その辺はFresnelにある二つのParameterの値によって変わってきます。

f:id:kazuhironagai77:20210830005742p:plain

DefaultではExponentInは5にセットされていますが、これを0にすると

f:id:kazuhironagai77:20210830005755p:plain

全部赤くなります。

ExponentIn=1

f:id:kazuhironagai77:20210830005835p:plain

1の時は球の正面は黒いですね。

ExponentIn=2

f:id:kazuhironagai77:20210830005848p:plain

2の時はgradationが出来ていますね。

ExponentIn=3

f:id:kazuhironagai77:20210830005901p:plain

数字が大きくなると内円の部分が大きくなるのと内円の色が薄くなる傾向が見られます。

ExponentIn=5

f:id:kazuhironagai77:20210830005915p:plain

Defaultの状態です。

ExponentIn=8

f:id:kazuhironagai77:20210830005930p:plain

かなり内円が大きくなってほとんど外円と重なってしまいました。

ExponentIn=10

f:id:kazuhironagai77:20210830005943p:plain

8の時とあまり変わらいですね。

次のParameterであるBase Reflect Fractionですが、Mathew Wadstein 氏の説明によると光が物質内で反射される割合を示しているそうです。

反射されない物質なら0だそうです。

Base Reflect Fraction=0、ExponentIn=5

f:id:kazuhironagai77:20210830005956p:plain

こっちの方が分かり易いですね。

Base Reflect Fraction=0、ExponentIn=1

f:id:kazuhironagai77:20210830010009p:plain

の場合です。

Base Reflect Fractionの変化をExponentInを10に固定して見て行きます。

Base Reflect Fraction=0、

f:id:kazuhironagai77:20210830010023p:plain

内円は真っ暗です。

Base Reflect Fraction=0.01、

f:id:kazuhironagai77:20210830010111p:plain

内円がかなり明るくなりました。外円も明るくなっているのかは分からないですね。

Base Reflect Fraction=0.02、

f:id:kazuhironagai77:20210830010125p:plain

内円はもっと明るくなりました。

Base Reflect Fraction=0.04、

f:id:kazuhironagai77:20210830010138p:plain

内円はもっと明るくなりました。

これでBase Reflect Fractionの傾向も判明しました。値が大きくなると内円が明るくなります。

それでここまでやって思い出したんですが、私、このFresnel Refection を量子化学のSpectroscopyのクラスで勉強してました。

すっかり忘れていました。

今理解しているかと言われると「もう忘れちゃった。」としか答えられません。が、一回は理解した記憶があります。後でMaterialの勉強する時はしっかり式から理解出来るようにします。

最後のParameterのNormalですが、これはMeshが本来持っているNormal Vectorとは違うNormal Vectorを使用する時に使うそうです。ので今回はパスします。

<Materialの作成の続き>

試しなのか、CGHOW氏、Emissive Colorの実装を以下の様に変更して

f:id:kazuhironagai77:20210830010157p:plain

黄金のSkullを作成しました。

f:id:kazuhironagai77:20210830010212p:plain

凄い、絶句ものの美しさです。

私もそっくりまねて実装してみました。

f:id:kazuhironagai77:20210830010225p:plain

何か全然違いますね。まあ元々使用しているMeshが違うのでしょうがないですね。

色々値を弄ってみましたがこれが限界でした。

f:id:kazuhironagai77:20210830010250p:plain

結局、CGHOW氏は以下の実装に戻してしまいました。

f:id:kazuhironagai77:20210830010305p:plain

後で、Cascadeの方から値を変化させるんでしょうね。

3.3 最初のEmitterを作成するの続き

Required ModuleのMaterialをM_skullに変更しました。

f:id:kazuhironagai77:20210830010323p:plain

Tutorialのは完全に真っ黒ですが、

f:id:kazuhironagai77:20210830010337p:plain

私の方は元のMaterialが使用されたままになっています。

f:id:kazuhironagai77:20210830010350p:plain

Skeleton HeadをDuplicateしてMaterialをM_skullに変更したStatic Meshを作成して

f:id:kazuhironagai77:20210830010403p:plain

それをP_Skull_AuraのSkull EmitterのMeshにセットしました。

f:id:kazuhironagai77:20210830010427p:plain

そしてColor Over Life Moduleの設定を先程のGoldの値にセットします。

f:id:kazuhironagai77:20210830010454p:plain

こんな感じです。

f:id:kazuhironagai77:20210830010510p:plain

あれ、また後ろの髑髏が前に写っています。Ribbonの時と同じ現象が起きています。

f:id:kazuhironagai77:20210830010525p:plain

真ん中にSK_Mannequinを配置してみます。

f:id:kazuhironagai77:20210830010539p:plain

それなりには雰囲気が出て来ました。

これで最初のEmitterの作成は終わりのようです。

今週のCascadeの勉強はここまでとします。

3.4 今週のCascadeの勉強のまとめと感想

CGHOW氏のUnreal Engine Skull Aura Tutorial | Download Project Files [7] の最初のEmitterの作成までやりました。このTutorialは大変分かり易かったです。

大体、CGHOW氏のTutorialの仕組みが分かって来ました。Tutorialによっては初心者向けに非常に詳しく解説したり、上級者向けに簡単に解説したりしているんです。だから自分のLevelにあったTutorialを選択する必要があるんです。

そして基礎を学ぶよりも実際にゲームで使用するVFXの作成方法、つまり応用を学ぶ所と考えるべきですね。

後、UE4のVersionは揃えた方がいいですね。ちょっとしたNiagaraの違いで訳わからなくなる可能性があります。

<Effectの違いはMeshの違い>

全く同じMaterialを使用していてもCGHOW氏のSkullは以下ので

f:id:kazuhironagai77:20210830010604p:plain

私のはこうなりました。

f:id:kazuhironagai77:20210830010617p:plain

やっぱり優れたMeshを使用する事は綺麗なEffectの作成に絶対必要です。

<Fresnel Nodeについて>

Fresnel Nodeの使用方法については良く理解出来ました。

やっぱり一個一個試してみるのが理解するコツですね。

実際の計算方法についてもMaterialを勉強する時は、復習したいです。

<骸骨が一瞬だけ横を向くバグ>

これ非常に見苦しいんですが直し方が分かりません。

<骸骨を公転させる方法について>

これももっと楽なやり方があると思います。全体を理解したら別な方法で実装します。

以上です。

4.Map1の修正の続き

Map1とMap1_Testで共有している全てのDataを別々にします。

先週、作成しなかったDataは

f:id:kazuhironagai77:20210830010728p:plain

と村のNPCとの会話です。

f:id:kazuhironagai77:20210830010741p:plain

それぞれどこで使用してるかを確認します。

4.1 Item Spawn Dataの使用状況

まずはItem Spawn Dataです。

f:id:kazuhironagai77:20210830010802p:plain

Map1とMap1_Testしか使用してませんね。使用方法は全く同じはずなので、Map1_Testを見てみます。

Event BeginPlay関数内で、Itemを動的に生成するための実装部でItem Spawn Dataが使用されています。

f:id:kazuhironagai77:20210830010815p:plain

それだけです。

いやいや、Itemを拾ったらそのItemは2度と生成されないのだから、Itemを拾った時にもItem Spawn DataにAccessする必要があるはずです。

なんで検索には引っかからないのか不明ですが、それを探します。

ありました。

Pick up Item WidgetのRemove Picked Item()関数内で使用しています。

f:id:kazuhironagai77:20210830010829p:plain

このWidgetからItem Spawn Dataを検索してみると、以下に示してたように沢山引っかかって来ました。

f:id:kazuhironagai77:20210830010843p:plain

どうやらUE4 Editorでは検索を開始するBPによって検索結果は変わるみたいですね。多分ですがWidgetからある変数を使用している時はWidgetから検索しないと、だめみたいです。

ある変数の使用箇所を調べるのに、検索で出て来た所だけを確認して全部調べた気になっていると危ない事が分かりました。

以下の二つのWidgetでItem Spawn Dataを使用してました。

一体何に使用しているのかを調べたら、Game をSaveする時とLoadする時でした。

f:id:kazuhironagai77:20210830010902p:plain

f:id:kazuhironagai77:20210830010910p:plain

はぁー。すっかりSaveする時とLoadする時の事を忘れていました。

Priest_Welcome Widgetを開いて見るとやっぱりSaveする時に使用していました。

f:id:kazuhironagai77:20210830010924p:plain

セーブボタンを押した時に実行されるコードです。

f:id:kazuhironagai77:20210830010939p:plain

この中のFrom Game Instance to Save Game関数を開くとItem Spawn Dataを使用しています。

f:id:kazuhironagai77:20210830010956p:plain

もしItemのSpawn するDataを他のMapに作成するとこの部分を増やす必要がありますね。

すっかり忘れていました。

最後はStart Menu WidgetのLoadに使用してます。

f:id:kazuhironagai77:20210830011013p:plain

ここです。

f:id:kazuhironagai77:20210830011027p:plain

Load Gameを開くと

f:id:kazuhironagai77:20210830011041p:plain

Item Spawn Dataがある訳ではなくChange Item Spawn Data in Game Instance関数があり

f:id:kazuhironagai77:20210830011054p:plain

その関数内でItem Spawn Dataが使用されています。

4.2 Item Spawn Dataの改造について

それぞれのMapにItem Spawn Dataを作成する予定です。

ただItem Spawn DataにそのItemがSpawnされるMapのデータを含ませる事で、一個のArrayで全部のItemを管理出来ないのか検討してみます。

Item Spawn Data はArrayでBaseになっているStructureはItem Spawn Dateです。以下にその要素を示します。

f:id:kazuhironagai77:20210830011112p:plain

ここにLevel名を追加すれば出来そうです。

ただしArrayの元になっているStructureの構成を変化させた場合、前のStructureで作成されたArrayのDataは全部消えてしまった気がします。

後、Data Tableに書かれたデータを外部に保存して新たにImportすると凄い楽だった気がします。これも調べて見ます。

<Data Tableの元になっているStructureの構成を変化させる>

Testと言う名前のStructureを作成しました。

f:id:kazuhironagai77:20210830011134p:plain

中身は以下の様にしました。

f:id:kazuhironagai77:20210830011147p:plain

これを元にArrayをGame Instanceに作成します。

f:id:kazuhironagai77:20210830011200p:plain

作りました。

更に中身も追加します。

f:id:kazuhironagai77:20210830011232p:plain

この状態で変数Test Structの元になっているStructureであるTestに新しい要素を追加します。

f:id:kazuhironagai77:20210830011247p:plain

Game InstanceからCompileをクリックしたらUE4 Editorがクラッシュしてしまいました。

UE4 Editorを開いてGame Instanceに作成したarray 、Test Structを確認したら

f:id:kazuhironagai77:20210830011301p:plain

先程、作成した要素が普通に追加されていました。

Structureに新しい要素を追加する時は、追加した後、一端UE4Editorを閉じて、もう一度開けば大丈夫みたいです。

<Data Tableに書かれたデータを外部に保存して新たにImportする方法>

これは2020-05-24のBlogにやり方がまとめられていました。

f:id:kazuhironagai77:20210830011322p:plain

よくこんな細かい事を覚えていたと思います。

ただ、この方法はArrayには使用出来ません。Data Tableに対してのみです。

4.3 NPCとの会話

NPCとの会話はNPC_Person BPのVillage Name とOccupationによって決定します。

f:id:kazuhironagai77:20210830011344p:plain

f:id:kazuhironagai77:20210830011350p:plain

これはMap1で新しくNPCを配置する時にこの二つを変更すれば良いだけです。

これは時に何もする必要はないですね。

4.5 Item Spawn Dataの調査のまとめ

Item Spawn Dataは二つの解決策があります。それぞれに長所と短所があり、どちらを選択してもかなりのコードを変更する必要が出て来ます。それぞれの長所と短所、直す必要があるコードについてまとめます。

<Map1用とMap1_Test様に別々のArrayをGame Instanceに作成する方法>

長所です。

  • この方法は現在、Game Instanceに存在しているItem Spawn Dataをそのまま使用出来ます。

短所です。

  • Map2個の内はまだいいかMapが増えるたびに新しいArrayGame Instanceに作成する必要がある。
  • 勿論、それに伴ってItem Spawn Dataに関係している全てのコードを書き変える必要が出て来る。

この方法を採用した時、直さなくてはならないコードを書き出します。

  • Map1_TestにおけるEvent BeginPlay関数内で、Itemを動的に生成するための実装部を書きなおす必要があります。

f:id:kazuhironagai77:20210830011438p:plain

  • Priest_Welcome WidgetからSaveをする時

f:id:kazuhironagai77:20210830011508p:plain

この2つは新たなMapを追加するたびに書きなおす必要があります。

<StructであるItem Spawn Dateにあらたな要素、Level名を追加する>

長所です。

  • 一回作成出来れば、後から何個mapが追加されても何も変更する必要がない。

短所です。

  • Structを書き変えた時に発生するErrorが未知
  • 書き変えるコードが比較的多い

この方法を採用した時、直さなくてはならないコードを書き出します。

  • Map1Map1_TestにおけるEvent BeginPlay関数内で、Itemを動的に生成するための実装部を書き直す必要があります。

f:id:kazuhironagai77:20210830011555p:plain

  • Priest_Welcome WidgetSaveをする時(以下の実装を見ると変更しないでも大丈夫かもしれません。)

f:id:kazuhironagai77:20210830011622p:plain

  • Start Menu WidgetからLoad する時

f:id:kazuhironagai77:20210830011648p:plain

<結論>

二つのやり方を厳正に比較した所、「StructであるItem Spawn Dateに新たな要素、Level名を追加する」方法の方が優秀であると考えられます。このやり方でやる事にします。ただし一週間だけ寝かします。もっと良い考えが浮かぶかもしれませんし、何かの大きな問題に気が付くかもしれませんので。

なので今週のRPGの製作はこれだけです。

4.6 NPCのキャラクターについて

現在、NPCのキャラについてはSK_Mannequinで代用しています。

f:id:kazuhironagai77:20210830011741p:plain

いつかはこれらをしっかりしたMeshに代える必要があります。

NPCだけで14種類必要です。

f:id:kazuhironagai77:20210830011755p:plain

Third Person Character BPに書かれている職業を見ると現時点で23種類必要です。

f:id:kazuhironagai77:20210830011807p:plain

候補を探して見ました。

f:id:kazuhironagai77:20210830011823p:plain

f:id:kazuhironagai77:20210830011830p:plain

このPolygonシリーズが親和性が高そうです。

ただし、この会社、コメント欄に

f:id:kazuhironagai77:20210830011858p:plain

と書かれていてあまり評判は良くないみたいです。

現状、これぐらいしか見つかりません。これで妥協するのも必要かもしれません。

5.Loading Screenの勉強の続き

5.1 先週の復習

現在、制作中のこのRPGでは、別なMapに移動する時は銀河鉄道に乗車している事にしました。

なのでLoad中は電車内の会話を表示するようにしたいんです。出来ればAnimationで。Load時間が短い時は「○○駅を発車しました。○○駅に到着しました。」と出ます。Load時間が長い時は「異音を検知したため低速運行を行っています。」みたいな連絡が表示される訳です。

それで先週はBackgroundでLoadする方法について勉強しました。

まずUE4C++からBackgroundでLoadする方法を勉強しました。

主に使用したTutorialはAsync Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [9]です。

次にBPでBackgroundでLoadする勉強をしました。

その一環としてUnreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [10]を勉強しましたが、そこでLoad Stream Levelノードを使用すればBackgroundでLoad出来る事が分かりました。

f:id:kazuhironagai77:20210830011940p:plain

所がこのノードの使い方を直接、説明したサイトやDocumentが見つからなかったんです。

更にSub Levelについても良く分からなかったんです。いやSub Levelの設定の仕方とかは分かったんですが、Sub Levelって何?普通のLevelとどう違うの?と言う根本的な所が分かりませんでした。

よくよく調べて見ると、このノードやSub Levelは、元々、巨大なMapを分割して作成してSeamlessに繋ぐために開発されたものでした。

最後にPlug-inを使用してLoadする方法を一寸だけ勉強しました。

最後に、Mathew Wadstein氏のTutorialでLoad Stream Levelノードを使用したLoadの作成方法を解説した動画、HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [14] が見つかったのでこれも勉強したいと述べています。

5.2 SeamlessなMapについて

Load Stream Levelノードを勉強するためには、先にSeamlessなMapの接続方法を勉強すれば良いとなりましたので、その作成方法を教えてるTutorialを探すと、

などがありました。

最初のTutorialであるUE4 - Tutorial - Level Streaming! [11]は、Dean Ashford氏が作成したものです。Dean Ashford氏のTutorialにはCascadeの勉強でも散々お世話になっています。

YouTubeの評価を見ると

f:id:kazuhironagai77:20210830012025p:plain

となっています。かなり良いTutorialと思われます。

次のTutorialであるHTF do I? Level Streaming using Blueprint Nodes in Unreal Engine 4 [12]はMathew Wadstein氏が作成したものです。BPのノードの機能や使用方法が分からない時は、いつもMathew Wadstein氏のTutorialにお世話になっています。

今回は特にLoad Stream Levelノードを理解するのが目的です。

このTutorialで勉強するのはかなり重要でしょう。

最後のTutorialであるLevel Streaming with Blueprints Unreal 4 [13]ですが、Shaun Foster氏が作成したものですが、多分ですが、今まででこの人のTutorialを見た事はないです。でも何かよさげ*なので試しに見てみます。

*全然関係ないですが、よさげを若者言葉として排斥する勢力があるみたいですが、私は絶対反対です。よさげはきちんとした日本語で、若者言葉じゃないです。昔からありました。またよさげのげは、気って意味です。良い気が出ていると言う意味です。これについてはかなり言いたい内容なのでいつか前文でまとめます。

5.3 Level Streaming with Blueprints Unreal 4 [13] を勉強する

Shaun Foster氏のLevel Streaming with Blueprints Unreal 4 [13]から勉強します。

最初からここに公式のDocumentがありますと説明していました。

f:id:kazuhironagai77:20210830012117p:plain

あれ。何で先週は見つからなかったんでしょうか?

もう一回探してみます。

公式のDocumentにLevel Streaming [15]がありました。

f:id:kazuhironagai77:20210830012132p:plain

更に、Collaborate with Sublevels [16]もありました。

f:id:kazuhironagai77:20210830012145p:plain

それでこの人のTutorialはこの辺のDocumentを読んだ前提で話しているみたいで付いていけません。

先にこのdocumentを読む事にします。

後、Comment欄で

f:id:kazuhironagai77:20210830012159p:plain

と回答しています。やっぱりUE5ではLoadの方法は根本から変更されているみたいですね。

5.4 Level Streaming Overview  [17]を勉強する

作戦変更です。公式のDocumentであるLevel Streaming Overview  [17]を勉強する事にします。

Level Streaming OverviewのRemarkには以下の様に書かれています。

f:id:kazuhironagai77:20210830012224p:plain

Streaming Levelとは先週、よく意味が分からないと言っていたSub Levelの事だと思います。

だとすると、このRemarkは「Sub LevelはLevel Streaming Volumeを使用するかBPかC++でprogrammingする事でLoad出来ます。」と読めます。

この解釈が正しければ、BPでSub LevelをLoadする場合にLoad Stream Levelノードが使用されているはずです。

f:id:kazuhironagai77:20210830012238p:plain

<The Persistent Level

Persistent Levelについての解説です。要するにPersistent LevelはSub Levelに対しての親Levelのようです。

Landscapeはどこで管理するんでしょうね。大きなLandscapeを作成してこのPersistent Levelで管理するんでしょうか。それとも沢山のLandscapeをそれぞれのSub Levelで管理するんでしょうか?

<Streaming Levels

Streaming Levelと言う言い方がまずしっくりきません。Sub Levelの方が実態を表しています。しかし公式がStreaming Levelと呼んでいる以上、これからはStreaming Levelと呼ぶ事にします。

Streaming Levelの管理はLevels Windowによって行われるそうです。

Levels Windowって何?と調べて見たら、以下のヤツでした。

f:id:kazuhironagai77:20210830012301p:plain

Menu画面にあるWindowからLevelsを選択すると開けます。

f:id:kazuhironagai77:20210830012330p:plain

Streaming Level はpersistent Levelと重ねて作成する事も可能ですし、別々に作成する事も可能だそうです。

これが知りたかった。

Level Streaming with Blueprints Unreal 4 [13] では、Streaming LevelをPersistent Levelに重ねて作成していたんです。このやり方を始めて見た私は「えっ。これがseamless なLevelの作成なの?」と困惑しました。Streaming LevelはPersistent Levelに重ねても良いし、重ねなくても良いんですね。

それぞれのStreaming LevelはAlways Loaded かBlueprintのどちらかをLevels Windowから選択出来るそうです。

どうやって。と思ったらこちらも公式のDocumentであるManaging Multiple Levels [18] で説明されていました。

f:id:kazuhironagai77:20210830012347p:plain

Always Loadedにセットされていると、Persistent Levelと同一のLevelと見なされるみたいですね。

このDocumentによる解説では、Always Loadedにセットされている限りLevel Streaming Volumeを使用してもBPかC++でprogrammingしても無視されるとあります。

ふーん。です。

ふーん。ですが「それならPersistent Levelのままでよくない。」と思いました。そしたらそれについてもこのDocumentにしっかり説明がありました。

その説明によると、今のGameはmapが大変広大で、複数のLevel Designerが同時に同じmapを制作するのが普通だそうです。そうしないと期限までにGame が完成しないらしいです。ただしUE4では複数で同じLevelにaccessして同時にそのLevel内の何かを変更する事は出来ないので、Streaming Levelで分割する事で、それぞれのLevelを同時に制作出来るようにしたそうです。

うーん。納得です。

となると、Level Streaming Volume、Programmingのどちらを使用するにしてもStreaming LevelのSeamlessなLoadをするためにはChange Streaming MethodはBlueprintにセットしないといけないと言う事ですね。

段々理解してきました。

<Dynamic Streaming Methods

私は、ActorをLevel上に配置した場合は、その「Actorを静的に生成した。」と言っています。そしてBPやUE4C++からActorを生成した場合は動的と呼んでいます。これはProgrammingの概念としても正しいはずです。

でも動的なStreamingって?何なんでしょう。

「じゃあ静的なStreamingもあるんですか?」って思ったんですが、要するにLevel Streaming Volumeを使用するかC++やBPのProgrammingを使用するかしてPlay中に新しいLevelを作成する事を動的と呼んでいるんでした。

それなら納得です。

<Level Streaming Volumes

いつ、Stream Levelを生成するかですが、Level Streaming Volumeは簡単です。View PointにLevel Streaming Volumeが侵入したらそのStream Levelを生成します。

はい。

これでいいですね。というかこれ以上の方法ってあるんでしょうか?

正しこのDocumentにはどうやったらLevel Streaming Volumeでセット出来るのかの説明はありませんでした。リンク先のLevel Streaming Volumes [19] で実際に使用する方法が解説されているみたいです。

Seamlessな広大なMapを生成するだけならここで、Level Streaming VolumesによるStream Levelの生成方法の勉強に突入しますが、今回の目的はあくまでLoad Stream Levelノードについての勉強です。

恐らくLoad Stream Levelノードを使用するであろう、Programmingを使用してのLevel Streaming を解説する次の節を続けて読んでいきます。

< Scripted Level Streaming >

いきなり下記の説明がありました。

f:id:kazuhironagai77:20210830012423p:plain

説明を読んだ限りでは、Level Streaming Volumeよりも複雑なstream LevelのLoadやUnloadをしたい時は、Load Stream Level やUnload Stream Level, 更にはGet Streaming Level function やCreate Instanceを使って自分で作成して下さい。とありました。

5.5 UE4 - Tutorial - Level Streaming! [11] を勉強する

大体理解しちゃったので、先程の「5.2 SeamlessなMapについて」で調べたTutorialを見ても理解出来るはずです。

UE4 - Tutorial - Level Streaming! [11]を見直します。

早速知らない事一つです。

Persistent Levelの下にStream Levelを新たに作成したい時はLevels WindowのLevelsの三角の部分をクリックしてCreate Newを選択すれば良いです。

f:id:kazuhironagai77:20210830012442p:plain

二つStream Levelを追加しました。

f:id:kazuhironagai77:20210830012455p:plain

Stream2が水色ですが、これはStream2が選択されている事を示してます。

Stream1を選択した状態で、

f:id:kazuhironagai77:20210830012508p:plain

Cubeを配置します。

f:id:kazuhironagai77:20210830012554p:plain

するとこのCubeはStream1に配置されます。

試しにStream1を見えないようにすると

f:id:kazuhironagai77:20210830012607p:plain

先程配置したCubeも消えています。

f:id:kazuhironagai77:20210830012620p:plain

Levels Windowにある以下の表示の部分をクリックするとそれぞれのLevel BPが開くそうです。

f:id:kazuhironagai77:20210830012634p:plain

試してみます。

f:id:kazuhironagai77:20210830012648p:plain

開きました。

これはLockだそうです。これがLockされた状態だとそのLevel内に配置されたものを編集する事は出来ないそうです。

f:id:kazuhironagai77:20210830012703p:plain

そのLevelが最後にSaveされた時から何らかの変更があった時は鉛筆のマーク、最後にセーブされた時から何の変更もない時はフロッピーディスクのマークになるそうです。

f:id:kazuhironagai77:20210830012719p:plain

ちなみにこのIconをDouble ClickするとSaveされます。

f:id:kazuhironagai77:20210830012732p:plain

このMessageがうざいので消そうとBuild Light Onlyを実行したら

f:id:kazuhironagai77:20210830012752p:plain

Errorになってしまいました。

World Outlinerを見たらそれぞれのLevelで同じActorを持っていました。

f:id:kazuhironagai77:20210830012806p:plain

f:id:kazuhironagai77:20210830012812p:plain

Tutorialではこうなってなかったんですが何ででしょう?

作り直しました。

今度はEmpty Levelを選択しました。

f:id:kazuhironagai77:20210830012826p:plain

今度は上手くいきました。

f:id:kazuhironagai77:20210830012839p:plain

Build Light Onlyも出来ました。

Tutorialとは少し違いますが、cubeとFloorもそれぞれStream1とStream2に配置しました。

f:id:kazuhironagai77:20210830012900p:plain

ここでLevel Streaming Volumesの使用方法についての説明をしてくれるのかと思ったらいきなりBPを開いてコードを書き始めました。どうやらこのTutorialではLevel Streaming Volumesの使用方法についての解説はなさそうです。

Persistent Levelを選択したまま、Trigger Boxを追加します。

そしてPersistent LevelのLevel Blueprintを開き以下のコードを追加します。

f:id:kazuhironagai77:20210830012915p:plain

やっとLoad Stream Levelノードが来ました。

もうこのノードの使用方法は大体ですが判明していますね。

やっぱりLoad Stream Levelノードの使い方を理解するためにはSeamlessなLoadについて勉強する必要があったんですね。

テストします。

Stream1に配置されているcubeは消えています。

f:id:kazuhironagai77:20210830012938p:plain

目の前にあるTrigger Boxに触れるとStream1が生成され、

f:id:kazuhironagai77:20210830012956p:plain

Cubeが現れました。

f:id:kazuhironagai77:20210830013009p:plain

今度はUnload Stream Levelの場合です。Trigger Boxから出たらStream1が消えるようにしました。

テストします。

Trigger Boxに入りました。

Cubeが発生しました。

f:id:kazuhironagai77:20210830013027p:plain

Trigger Boxから出ました。

Cubeは消えました。

f:id:kazuhironagai77:20210830013041p:plain

はい。

残りは同じ事をStream2で繰り返してるだけですのでスキップします。

5.6 HTF do I? Level Streaming using Blueprint Nodes in Unreal Engine 4 [12]を勉強する

もうLoad Stream Levelノードの使用方法は理解してしまったので、特にこのTutorialを見る必要はないんですが一応、理解に漏れがないか確認する意味で見ておきます。

What is Level StreamingというTutorialがあるのでLevel Streaming自体が分からない人はそっちを見て下さいと言っています。

調べたらありました。WTF Is? Level Streaming in Unreal Engine 4 [20] と言う名前でした。

これ見たら全て解決してたんでしょうか?

Always Loadedを使用した場合はBPではなくVolumeによって決定されると言っています。

f:id:kazuhironagai77:20210830013105p:plain

うーん。

少なくとも私が理解した限りではLevel Streaming Volumeを使用する時もBPにセットしないといけないはずです。これは要確認です。

以下の方法で既にLoadしたLevelかどうか確認しています。

f:id:kazuhironagai77:20210830013120p:plain

このやり方はいずれ使用する事になるでしょう。記録しておきます。

Actorを別なMapに間違って配置してしまった時の直し方についての説明がありました。

  1. そのActorを選択して切り取ります。
  2. 望みのMapを選択します。
  3. そこでPasteします。

これでActorは正しいMapに配置されるそうです。

以上です。

5.7 「Loading Screenの勉強の続き」のまとめ

Load Stream Levelノードの使用方法については完全に理解しました。Sub Levelについても同じです。Sub Levelとは言わずにStream Levelと言うみたいです。

Level Streaming Volumeを使用する場合は、確認が必要です。来週テストしてみます。

残念ながら、Load Stream Levelノードを使用したLoading Screenの勉強までは出来ませんでした。これは来週やります。

HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [14]も来週勉強します。

後、勿論、

f:id:kazuhironagai77:20210830013154p:plain

の使用方法についても来週勉強します。

6.Good Skyの復習

時間が無くなってしまいました。

7.まとめと感想

Niagaraの勉強以外は結構上手く出来ました。この調子で来週もがんばります。

来週は以下の勉強を予定しています。

  • Particle Systemの勉強
  • RPGの作成
    • Item Spawn Dataの複製
    • Loading Screenの勉強の続き
    • Good Skyの復習

以上です。

8.参考文献(Reference

[1] CGHOW. (n.d.). CGHOW. YouTube. Retrieved August 29, 2021, from https://www.youtube.com/c/cghow/playlists

[2] Beautypi. (n.d.). Shadertoy BETA. Shadertoy. Retrieved August 29, 2021, from https://www.shadertoy.com/

[3] vertexshaderart.com. (n.d.). vertexshaderart.com. Retrieved August 29, 2021, from https://www.vertexshaderart.com/

[4] Epic Games. (n.d.-d.). Niagara Visual Effects. Unreal Engine Documentation. Retrieved August 29, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/

[5] gameDevOutpost. (n.d.). UE4 - VFX. YouTube. Retrieved August 29, 2021, from https://www.youtube.com/playlist?list=PLomQNLPOWtzYXU_pRIUVVEV9uY7bjENZ5

[6] CGHOW. (2020, March 14). Intro to Niagara | Curl Noise | Point Attractor | Sine | Unreal Engine Niagara Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=I3G_rOQArQU&list=PLwMiBtF6WzsoNsDquipGfD-uLUb-fyRSV&index=7

[7] CGHOW. (2019, January 6). Unreal Engine Skull Aura Tutorial | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=V5u4iogpmQE&list=PLwMiBtF6WzsqXWJF-pjjkovVZM-04lzt_&index=1

[8] Wadstein, M. [Wadstein]. (2016, February 8). WTF Is? Material - Fresnel in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=PLwEwIYX454

[9] Epic Games [Unreal Engine]. (2019, May 20). Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=ON1_dEHoNDg

[10] Reids Channel. (2019, December 15). Unreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [Video]. YouTube. https://www.youtube.com/watch?v=lzGcVDUDU5g

[11] Ashford, D. [Dean Ashford]. (2017, November 9). UE4 - Tutorial - Level Streaming! [Video]. YouTube. https://www.youtube.com/watch?v=XE2x4TZHxHg

[12] Wadstein, M. [Wadstein]. (2015, October 30). HTF do I? Level Streaming using Blueprint Nodes in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=7JCBKCZbKh0

[13] Foster, S. [ Shaun Foster]. (2019, January 1). Level Streaming with Blueprints Unreal 4 [Video]. YouTube. https://www.youtube.com/watch?v=gPHcWOsCL0c

[14] Wadstein, M. [Mathew Wadstein]. (2015b, October 31). HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=QJVn2mW67YQ

[15] Epic Games. (n.d.-b). Level Streaming. Unreal Engine Documentation. Retrieved August 29, 2021, from https://docs.unrealengine.com/4.26/en-US/BuildingWorlds/LevelStreaming/

[16] Epic Games. (n.d.-a). Collaborate with Sublevels. Unreal Engine Documentation. Retrieved August 29, 2021, from https://docs.unrealengine.com/4.26/en-US/Basics/Levels/CollaborateWithSublevels/

[17] Epic Games. (n.d.-c). Level Streaming Overview. Unreal Engine Documentation. Retrieved August 29, 2021, from https://docs.unrealengine.com/4.26/en-US/BuildingWorlds/LevelStreaming/Overview/

[18] Epic Games. (n.d.-e). Managing Multiple Levels. Unreal Engine Documentation. Retrieved August 29, 2021, from https://docs.unrealengine.com/4.26/en-US/Basics/Levels/LevelsWindow/

[19] Epic Games. (n.d.-d). Level Streaming Volumes. Unreal Engine Documentation. Retrieved August 29, 2021, from https://docs.unrealengine.com/4.26/en-US/BuildingWorlds/LevelStreaming/StreamingVolumes/

[20] Wadstein, M. [Mathew Wadstein]. (2015a, October 30). WTF Is? Level Streaming in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=ix1PDCr86lI

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する Ticket Systemなどの作成  Part 3

f:id:kazuhironagai77:20210822233421p:plain

<前文>

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

守破離は日本固有の文化>

皆さんは、守破離って聞いた事ありますか?

武道などの習い事で、よく言われる言葉ですが、簡単に言えば上達のためのノウハウみたいなのものです。

初心者の段階は、師匠の言う事が理不尽だったり、良く理解出来なくても言われた通りにやる事が最も上達が速いです。

中級者になって師匠の言っている意味が完全に理解出来たら、自分の場合に当てはめて、敢えて師匠から教わった内容を破る事が必要になります。中級者になっても師匠の言っている事をずっと守っているだけではそれ以上の上達は見込めません。

最後の段階では、自分の自由にやります。教わった内容からは全く離れます。

これは別に日本の伝統技能に限らず、何にでも応用出来ます。

例えばProgrammingの勉強だったら、

最初はSample codeに何が書いてあるのか理解は出来なくても丸写ししてしまいます。そして何回も読んだり、分からない部分を調べたりします。この段階では、このサンプルコードは絶対正しいと仮定して勉強します。つまり守の段階です。

Sample codeに何が書いてあるのか大体理解したら、次の段階です。少しだけコードを変更してみます。自分の理解が正しいかそれで確認します。そうです。少しだけSample codeを破壊します。ので破の段階です。

最後の段階は、自分の目的に最適化するように全部書き直します。つまり離の段階です。

皆さんはこれって当たり前の事だと思うかもしれませんが、この考え方って日本独自の考え方なんですよ。

アメリカではというかキリスト教文化圏では、守破離と言う考え方自体がありません。ではどうやって師匠が弟子に教育するのかと言うと、質問、考える(調べる)、回答です。

まず師匠が弟子に質問するんです。最初は弟子は質問の意味も分かりません。

弟子はひたすら考えたり調べたりします。

そして弟子が師匠の質問の意味を正しく理解して、これが質問の答えだと自信を持って言える様になると師匠と面会します。

弟子は自分が正しいと思う答えを師匠に回答します。すると師匠は弟子の回答を検討したり、導き方を厳しくチェックしたりします。そして弟子が正しく理解しているのを確認すると次の質問をします。

そして最初に戻ります。

こうやって質問、考える(調べる)、回答を繰り返す事で弟子を教育していきます。

私がアメリカの大学の研究室に入った時もこんな感じでした。最初に教授が課題を出すんです。

それで終。

来週までにやってこいと。

因みに課題に書かれている内容なんか全く理解出来ません。でも担当の教授は一切質問は受け付けません。仕方ないので自分で一週間ひたすら調べます。すると何となく課題の言っている事が分かって来て、こんな事を教授は言っているに違いないとコードを書いて持っていきます。

すると教授は私が書いたコードを逐一チェックして、ここはどうしてこうしたとか、厳しく聞いてきます。

私がそれはこんな理由でそう書きました。とか調べたらこんな資料が見つかって、そこにはこう説明されていた。から参考にしました。と言うと、凄い真剣に聞いていて、フンフンとうなずいたりします。

そして教授が言うんです。「よし、ここは正しく理解出来ている。」って。

そうすると直ぐに次の質問です。

それで最初に戻ります。

これを延々と繰り返します。

これがアメリカというかキリスト教圏の伝統的な教育方法なんです。

此処から深い話に入ります。

日本人がアメリカ人に教える立場になった時、それは漫画の描き方でも、寿司の握り方でも何でいいですが、守破離が世界基準だと思って、最初は何でも黙って師匠の言う事聞いてろ。ってやるとアメリカ人から詐欺師だと思われますよ。

Karate Kidと言う映画で、主人公がひたすら床掃除をさせられていて、頭に来て空手の師匠に文句を言ったら、その掃除のフォームがそのまま空手の防御だったという、シーンがあります。

それを見ていたアメリカ人は椅子から落っこちる位びっくりしますが、それはあくまで映画の話です。

現実では生徒が怒って、詐欺師と認定されて、とんでもないしっぺ返しを食らう事になります。

アメリカでは騙されたら生きていけないんです。そしてアメリカ人は自分を騙したヤツは絶対許しません。とことん追いつめられますよ。

ではどうやってそれを回避するかと言うと、

まずこれは下策ですが、最初から日本における指導方法は守破離に基づいて行うので、最初は理不尽と思っても黙って師匠の言う事聞く事と説明するのが一つです。これは時間限定で3日しても何も学べないと生徒が感じたら終わりです。

次はアメリカ方式と言うかキリスト教方式で教えるやり方です。

質問を作成して、弟子がそれの回答を必死に考える訳です。

これはアメリカ方式に沿っているからいけるだろうと思われますが、実際、敢えて日本文化にある意味逃げ込んでくるアメリカ人達というのは現行の教育システムからの落ちこぼれで、この方法で学ぶのが凄い苦手な人達なんです。

だから、詐欺師には思われないかもしれませんが、一向に生徒が育たない事態になる可能性が大です。

中策と呼びましょう。

最後ですが、これはかなり上手いと思ったやり方を紹介します。

海外の人にラーメンの作り方を教える動画で見たんですが、まず日本の昆布のダシの取り方を教えます。この部分は日本の守破離の守のやり方そのもので、兎に角、こうやれと教えます。生徒に疑問を挟む隙は与えません。

日本の守破離方式の凄い所は、最初の守を強制する事で、あんまり才能の無い生徒でも一応、やり方はマスター出来るところです。

そしてアメリカでは水質が違うから同じやり方でやると苦くなる。と言ってどうすれば良いのかを自分達で考えさせます。ここはアメリカ方式になっています。生徒はそれぞれ日本の水と近い水質の水を遠くまで汲みに行ったり、昆布を煮る時間を長くしたりして工夫します。

そうやって工夫している内に最初に教わった昆布のダシの取り方が、どういう理屈でダシを取っているのかをアメリカ人の生徒が理解していくんです。

もし最初からアメリカ方式で全部自分で考えろとやったら多分ほとんどの生徒は意味が分からなくて挫折しているはずです。しかしそこは日本方式の守破離の守で基本を無理やり押し付けてしまう事で回避しているんです。

しかし、日本方式の守破離だけだったら、アメリカ人は一体何を学んでいるのか理解出来ず、騙されているんじゃないかとなって怒って止めてしまったでしょう。そこにアメリカでは水質が違うから苦くなる。自分でその問題を解決しろ。とやる事で自分達のやるべき事が理解出来き、その先に進めるわけです。

実に上手いやり方です。これこそ上策でしょう。

ちなみに上記の動画は全部英語ですので、苦いはBitterと言っています。日本語の苦いは英語では絶対言ってはいけないあの言葉に聞こえますのでアメリカで料理を教える人は超注意して下さい。

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

<本文>

1. 今週の予定

先週はちょっとUE4の勉強が多すぎてRPGの製作に掛けた時間が少な過ぎました。勉強するのは好きですし、得意でもあるのでどうしてもそっちに重心が移ってしまいます。

しかしみんなが使いたいアプリは糞コードで書かれていても、完全無欠のプログラミングで書かれた誰も使わないアプリより遥かに価値があります。

ゲームだってそうです。面白いゲームを作るのが最も大切で、技術的に完全無欠にする必要は全くありません。

そして今、私が作成してるRPGは完成させるのが第一の目的でそれ以外はほどほどにやっておくべきです。

そこで今週からUE4の勉強に関しては量を大幅に減らしてRPGの製作にもっと力を注ぐ事にします。

1.1 先週までの勉強の総括

先週の勉強は何をしたのかを確認します。

必要な勉強とあまり必要でない勉強に分けて、あまり必要でない勉強は中止する事にします。

Niagara Particle System

RPGの製作と言う面から言えばもっとも必要のない勉強です。現在使用している4.24ではNiagaraは使用出来ませんから。しかしやっとCGHOW氏のTutorialが理解出来るようになったのと将来性の高さから勉強は継続すべきと考えています。

Cascade Particle System

今、作成しているRPGに使用するVFXを作成するとなるとこっちの勉強が重要になりますが、先週の砂のEffectのように参考になるTutorialが見つからない場合が多い気がします。参考になるTutorialが見つからないなら削るのも有りかと思います。

今考えると先週の砂のRenderingの勉強は無駄だったと思います。Cascade Particle Systemとは全く関係ないですから。

<別なマップに移動してる間に別なアニメーションを表示する方法についての調査>

これも絶対必要かと言えばそうでもないです。しかし先週勉強したAsync Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [1] は、大変優れたTutorialであるので勉強しておきたいです。

以下にこのTutorialが何故、重要なのかについてまとめておきます。

  • UE4BPからUEC++、そして自作したModuleの呼び出し方を学べる。
  • ActionRPGに書かれた実際のコードをどのように参考にすべきかを学べる。
  • Multi-threadのようなProgrammerが対応しないととんでもないバグを引き起こす箇所はBlack box化して、BPを触るDesignerにはMulti-threadは触らせないDesign設計も学べる。

つまりこのTutorialはLoading Screenの作成方法以上に大切なものが学べるって訳です。

思い出して来ました。

このTutorialを勉強するのは、RPGの作成に必要な事です。しかしここから派生してMulti-threadについての理解が不十分だから勉強しよう。となるとそれって絶対今しないといけない事なのとなります。

そうです。

Multi-threadの勉強は、勉強のための勉強で今すべき事じゃありません。絶対に始めるべきじゃないです。

<総括>

こうやってまとめたら思ったより勉強してなかったです。

うーん。

思い出しました。先週、Air conditionerから水が噴き出してきて、修理の人が来るまで地獄の暑さの中でやってたんでした。直った途端に大雨が降って来てエアコンが要らなくなると言うおまけ付きでした。

それで滅茶苦茶大変な思いして勉強してたんで非常に沢山やった気になってたんでした。実際滅茶苦茶疲れましたし。

どうしようかな。

Cascadeの勉強は切るつもりでしたが、こうやってまとめてみるとCascadeの勉強が一番、今のRPGの製作に関係してますね。

分かりました。

勉強のための勉強は切るべきです。

例えば先週のCascadeの勉強で、砂のEffectの作成方法を勉強するのが目的でしたが、実際に学んだのは砂のRenderingの方法でCascadeとは何の関係もない分野の勉強でした。これはやるべきではなかったです。

同様にC++のMulti-Threadの勉強もやるべきではないです。

1.2 今週の予定

前節の結論を踏まえて今週の予定を決めました。

  • Particle Systemの勉強
    • Niagara System
      • 先週の続き
    • Cascade System
      • 水のEffectの作成
    • RPGの作成の続き
      • 駅の作成の続き
        • 切符を道具として使用した場合の実装
        • バグ出し
      • 実際のゲームに使用するmap1とテスト用のMap1を分ける
      • 別なマップに移動してる間に別なアニメーションを表示する方法についての調査の続き
      • Good Skyの勉強

結局やる内容はあんまり変わってないですね。

2Niagara Systemの勉強

先週の続きをやっていきます。CGHOW氏のNebula Effect | UE4 Niagara Nebula | Download Project Files [2] です。

  • Moduleの勉強
    • Static Mesh Location Moduleについて
    • Curl Noise Force Moduleについて
    • Drag Moduleについて
    • Vortex Force Moduleについて
    • Scratch Moduleについて
  • Scratch Moduleの中身の実装について
    • 最初のサラの状態で存在するノードの機能や役割を調べる。
    • 左脇に表示されているToolについて調べる。
    • 作成したModuleの機能について解説する。
  • 前回、作成しなかった残りのEffectも作成する。

をやっていきます。

2.1 Moduleの勉強

Nebula Effect | UE4 Niagara Nebula | Download Project Files [2]で始めて使用したModuleについて調べます。

先週初めて使用したModuleはStatic Mesh Location Module、Curl Noise Force Module、Drag Module、Vortex Force ModuleそしてScratch Moduleの5つです。

<Static Mesh Location Module

先週のブログでは以下の様に解説されています。

f:id:kazuhironagai77:20210822233750p:plain

思い出しました。指定したStatic Meshの形にParticle を発生させるModuleです。

後、Static Meshを指定するためにSample Static Mesh Moduleが必要になります。Sample Static Mesh Moduleの事は忘れていました。このModuleについても調べます。

公式のDocumentであるParticle Spawn Group [3] には、

f:id:kazuhironagai77:20210822233816p:plain

とだけ説明されていました。

気になるのはその二つ上にSkeletal Mesh Location Moduleと言うのがあります。

f:id:kazuhironagai77:20210822234130p:plain

これ使用したらPlayerが操作するキャラとかMonsterの形からParticle に移行出来るんでしょうか?

それが出来たら凄いですね。忍者が逃走する時に消えるEffectとか、One Pieceのロギア系が攻撃された時のEffectみたいなの作れそうですね。

それは兎も角、もっとStatic Mesh Location Moduleについての資料はないのかと探したらありました。

gameDev Outpost のUE4 - Niagara Static Mesh and Surface [4] です。 

滅茶苦茶、分かり易く説明されていました。

<Sample Static Mesh Module

これは、gameDev Outpost のUE4 - Niagara Static Mesh and Surface [4]にあった説明で十分理解出来ました。

Curl Noise Force Moduleについて>

先週のBlogを見てみると以下の様に使用しています。

f:id:kazuhironagai77:20210822234159p:plain

それぞれのParticle にCurl Noiseに沿って速度を追加しているみたいですね。

Curl Noiseって何?

色んなサイトで少しずつ説明されていていました。一個だけ代表を選ぶとすると、このサイト(Intro to Curl Noise [5] )にあるPDFのスライドですかね。

このスライドや他のサイトそしてYouTubeにある説明を総合してまとめます。

まずCurl Noiseは以下の式の事です。(この式の具体的な計算方法についてはIntro to Curl Noise [5]にあるPDFファイルを見て下さい)

f:id:kazuhironagai77:20210822234231p:plain

滅茶苦茶簡単に言えば、この式は在る点にいる粒子の速度を計算しています。

この式を使用して流体の移動などを表すと凄い綺麗な動きになります。

ただしこの計算をするためには元になるVector場が必要になります。大抵はPerlin Noiseが使用されます。

以上になります。

ここからは想像ですがCurl Noise Force Moduleにある以下の二つのParameterは

f:id:kazuhironagai77:20210822234249p:plain

Noise Strengthがベクトル場の大きさを表して、Noise Frequencyがベクトル場の複雑さを表してるじゃないでしょうか。

Intro to Curl Noise [5]にあるPDFファイルでPerlin NoiseのFrequencyの大きさについて述べています。

f:id:kazuhironagai77:20210822234313p:plain

Noise Frequencyはこれを計算しているんじゃないんでしょうか?

試しにCurl Noise Force ModuleのScriptを開いて見てみました。

f:id:kazuhironagai77:20210822234328p:plain

うーん。分からん。

分からんなりに見てみますと、Noise StrengthはSampled Noiseに掛けていますね。

f:id:kazuhironagai77:20210822234351p:plain

となるとやっぱりNoise Strengthはベクトル場の強さに関係してそうですね。Noise Strengthがベクトル場の最大の高さを表すのではなくて、Sample Noise、恐らくPerlin Noiseの値を何倍にもするScaleの働きをしているんでしょうね。

Noise Frequencyの方も見てみます。

f:id:kazuhironagai77:20210822234406p:plain

あれ、Age AdvancementってParticleが一定時間でどれだけ移動したかって事なんでしょうか?

良く考えたらもうPerlin Noiseの計算方法覚えていません。

Noise Frequencyに関しては、良く分からないですね。

公式のDocumentであるParticle Update Group [6] には以下の説明がされていました。

f:id:kazuhironagai77:20210822234428p:plain

これ読むとPerlin Noiseはオプションみたいですね。

以下の部分で、元になるVector場をどっかから一気に持って来てる感じですね。

f:id:kazuhironagai77:20210822234443p:plain

まあ、これ位分かれば今回は十分です。次のModuleを調べます。

<Drag Moduleについて>

このModuleに関しては単にParticleにDrag Forceを追加してるだけでしょう。

f:id:kazuhironagai77:20210822234504p:plain

上記の例で言えば、Dragする方向に1を追加していると考えられます。

一応、Scriptも開いてみます。

f:id:kazuhironagai77:20210822234518p:plain

あれ!

これは簡単です。これなら今の自分でも読んで理解出来そうです。

読んでみましょう。

最初の塊です。Liner Dragと書かれています。

f:id:kazuhironagai77:20210822234531p:plain

最初のMap Getノードですが、何をしているのか分かりました。

このノードはこのEmitter内に存在してる全てのParameterにGet 関数としてAccess出来るんです。

因みにEmitter内に存在してる全てのParameterはNSのParametersに載っているparameterの事です。(この部分は間違っていました。Physics DragはTransientですが以下に示したNSのParametersには載っていません。)

f:id:kazuhironagai77:20210822234544p:plain

今回Get関数としてAccessしたのはこのDrag ModuleにParameterとして有るDragと元から存在してるParameterであるPhysicsDragです。

このPhysicsDragこそがそれぞれのParticleのDrag 力を指定する変数なはずです。だからその変数にDrag ModuleのDragで指定した値を追加しているんです。

NiagaraFloatがTrueかFalseかは以下に示したDragにチェックが入っているかどうかによると思われます。

f:id:kazuhironagai77:20210822234557p:plain

もしチェックが入っていればPhysicsDragの値は、PhysicsDragの値 + Drag ModuleのDragで指定した値になり、チェックが入っていなければPhysicsDragの値はそのままです。

Rotational Dragの塊の方も全く同じ事をやっています。

f:id:kazuhironagai77:20210822234610p:plain

回転のDrag Forceを管理するのはPhysics Rotational Drag変数です。

公式のDocumentであるParticle Update Group [6] には以下の説明がされていました。

f:id:kazuhironagai77:20210822234623p:plain

はい。Scriptで予測した通りです。

少しはScriptも読めるようになって来ました。

<Vortex Force Moduleについて>

このModuleは何をしているのか全く覚えていません。

外してみました。

f:id:kazuhironagai77:20210822234645p:plain

もう一度追加します。

f:id:kazuhironagai77:20210822234700p:plain

公転してます。

全てのParticleが在る点を中心として公転する力を追加しているようです。

Scriptの方はまあまあ複雑です。

f:id:kazuhironagai77:20210822234715p:plain

Scriptの方はまあまあ複雑なので、今回はScriptの分析はパスします。

公式のDocumentであるParticle Update Group [6] には以下の説明がされていました。

f:id:kazuhironagai77:20210822234729p:plain

ここで言われているVortex Axisが全てのParticleが公転する為の中心軸で、そのために必要な力はPhysics. Forceに追加されるようです。

<Scratch Moduleについて>

まっさらのModuleでScriptを自分の自由に書けるModuleです。

UE4 Answer HubのWhat is Scratch Pad Module? [6] にはScratch Pad Moduleについての解説がありますが、Scratch Pad ModuleはどうやらScratch Moduleの事みたいです。

このサイトに紹介されているYouTubeに飛ぶと更に詳しい説明がされています。一つだけ私が大切だと思った事を書いておくとScratch ModuleはTransientなのでその場だけしか存在しない事です。

もっと細かい内容については次の節で勉強します。

2.2 Scratch Moduleの中身の実装について

今度はScratch Moduleの内容について検証します。

<最初のサラの状態で存在するノードの機能や役割を調べる>

Scratch ModuleをクリックするとScratch Padが開きます。

Scratch Padには以下のBPが配置されています。

f:id:kazuhironagai77:20210822234801p:plain

これはもう理解出来ます。Map Getは現存するParameterにaccessする為のもので、Map Setはそのparameterの値を変更するためのものです。Getter setterのBP版です。

<左脇に表示されているToolについて調べる>

以下のヤツです。

Scratch Padというやつです。

f:id:kazuhironagai77:20210822234823p:plain

で色々探したんですがこれそのものを説明しているサイトは見つかりませんでした。

ので私が色んなサイトから集めた情報で解説します。

間違っている部分もあるかもしれませんが現時点で理解している範囲でベストをつくします。

<<Modules>>

f:id:kazuhironagai77:20210822234842p:plain

+ボタンを押すと新しいScratch Moduleを作成します。

ほとんどのTutorialで解説してたのが、作成したScratch Moduleを普通のModuleとして永遠に保存する方法です。

以下の様にModuleをクリックしてEditorを表示させ、そこからCreate Assetを選択します。

f:id:kazuhironagai77:20210822234857p:plain

すると以下の様な画面が表示されるので適切な名前を打ち込みSaveボタンをクリックする事で出来ます。

f:id:kazuhironagai77:20210822234911p:plain

<<Dynamics Inputs>>

これは何なのか分かりません。

f:id:kazuhironagai77:20210822234929p:plain

分からないなりに予測するとNiagara Emitterの方でParameterの値を指定する方法の一つにDynamic Inputというのがあります。

f:id:kazuhironagai77:20210822234944p:plain

これを自作しているのだと思われます。

試しにLife timeにAdd Floatをセットします。

f:id:kazuhironagai77:20210822235001p:plain

そしてそれを開いて見ます。

すると以下の様な形になっています。

f:id:kazuhironagai77:20210822235038p:plain

今度は以下の様にDynamic Inputsに新しいInputを作成してそれを開いてみます。

f:id:kazuhironagai77:20210822235057p:plain

はい。Add floatとほとんど同じ形をしていますね。

f:id:kazuhironagai77:20210822235111p:plain

間違いないですね。

<<Scratch Script Parameters>>

ここはModule内で使用しているAttributeを表示しているようです。

試しにNormalized Ageを追加してみます。

f:id:kazuhironagai77:20210822235131p:plain

Normalized Ageが表示されています。

f:id:kazuhironagai77:20210822235144p:plain

所でParticlesタイプじゃなくてTransientタイプの追加方法を知りたいです。

<<Scratch Pad Selection>>

これは作成しているModuleのDetailを表しているんでしょうね。

f:id:kazuhironagai77:20210822235202p:plain

個々の機能についてはまだ分からないですね。

一応、Cursorを添えると説明文が表示されるので必要に応じて勉強します。

f:id:kazuhironagai77:20210822235224p:plain

以上です。

<作成したModuleの機能について解説する>

以下に先週作成したScratch Moduleを示します。

f:id:kazuhironagai77:20210822235244p:plain

まずMap GetでNew Static MeshをInputに追加します。

そのStatic Mesh内からRandomな場所を選択します。

ここからは2つの作業をしています。

最初の作業です。

その場所をWSに変換します。

変換した値をPositionにセットします。

ここで生成されるParticleが指定したStatic Meshの形に生成されるようになるようにしています。

次の作業です。

その場所のUVを取ります。

UV値を元にvectorの値を2から4に増やします。

増やした値をDynamic Material Parameterにセットします。

ここではMaterialが一個一個のParticleに貼られるのではなくParticle全体に一個のMaterialが貼られるように指定しています。

以上です。

2.3 前回、作成しなかった残りのEffectも作成する。

これはあんまりやる意義を感じないんで止めます。

3. Cascade Systemの勉強

水のEffectの作成を勉強します。

Waterfall | Detailed Tutorial | Unreal engine 4 Particle Systems [7] を勉強します。

このTutorial、去年作成されたにも関わらず、Cascadeを使用しています。作者曰く、Patronで2年前に作成したWaterのParticle Effectの作り方に良く分からない所がある。と言われたので特別に作り直したそうです。

以下にしめしたEffectを作成するそうです。

f:id:kazuhironagai77:20210822235327p:plain

3.1 Materialの作成

指定されたTextureをDownloadしました。

f:id:kazuhironagai77:20210822235403p:plain

こんなやつです。

f:id:kazuhironagai77:20210822235418p:plain

αには以下のイメージが入っていました。

f:id:kazuhironagai77:20210822235431p:plain

RGBは全く同じイメージでした。

そのTextureからMaterialを作成します。

f:id:kazuhironagai77:20210822235446p:plain

こんな感じです。

f:id:kazuhironagai77:20210822235500p:plain

実装は以下の通りです。

f:id:kazuhironagai77:20210822235533p:plain

まあ、Effect用のMaterialとしては普通の作り方ですね。

次のMaterialを作成します。

f:id:kazuhironagai77:20210822235549p:plain

M_WaterfallSmokeと名付けました。滝の周りに発生する蒸気をするためのMaterialでしょうか?

こんな感じです。

f:id:kazuhironagai77:20210822235602p:plain

実装は以下に示します。

f:id:kazuhironagai77:20210822235617p:plain

ーん。

Radial Gradient Exponentialノードを前に使用した時は何を作成したんでしたっけ?もう忘れてしまいました。

2021-08-09のブログに綺麗にまとめられていました。

f:id:kazuhironagai77:20210822235632p:plain

Densityは白い部分の濃さを表します。数字が小さい程黒く、つまり透明になります。

最後にM_WaterfallSmokeのInstanceを作成します。

f:id:kazuhironagai77:20210822235647p:plain

以上でMaterialの作成は終わりです。

3.2 Particleの作成

Particleを作成します。名前はP_Waterfallとします。

f:id:kazuhironagai77:20210822235710p:plain

まずData TypeをGPU Spritesにします。

f:id:kazuhironagai77:20210822235729p:plain

次にRequired ModuleのMaterialをM_WaterfallMainに変更します。

f:id:kazuhironagai77:20210822235749p:plain

Spawn ModuleのSpawn Rateの設定をDistribution Float UniformにしてMin とMaxを10にします。

f:id:kazuhironagai77:20210822235804p:plain

これって、Min とMaxが同じ値ならConstantを使用して、あえてUniformを選択する必要無いと思うんですが。

前に公式のTutorialで「Uniformをあえて使用してもEffectの計算コストは変わらない。」みたいな話を聞いた事がありますが、Constantの代わりにUniformを使用するのは一般的なんでしょうか?

今度はLife Time Moduleの設定です。Distribution Float Uniformを指定してMin とMaxに3をセットしました。

f:id:kazuhironagai77:20210822235819p:plain

ここでもUniformを使用していながらMin とMaxに同じ値をセットしてますね。

ちなみに今の状態でのReviewのイメージです。

f:id:kazuhironagai77:20210822235832p:plain

全く滝には見えませんね。

今度はInitial Size ModuleのSizeの値を全部200に変更しました。

f:id:kazuhironagai77:20210822235846p:plain

Initial Velocity ModuleのStart Velocityの値を以下の様にしました。

f:id:kazuhironagai77:20210822235900p:plain

こんな感じです。とても滝には見えません。

f:id:kazuhironagai77:20210823000512p:plain

次はSize by Life Moduleです。

このModuleは付属のModuleではないので自分で追加します。

f:id:kazuhironagai77:20210823000528p:plain

以下の様な設定に変更しました。

f:id:kazuhironagai77:20210823000542p:plain

グラフで見るとこんな感じです。

f:id:kazuhironagai77:20210823000557p:plain

次にConstant Accelerationを追加します。

そしてAccelerationの値のzに-300 を追加します。

f:id:kazuhironagai77:20210823000611p:plain

以下の様になりました。

f:id:kazuhironagai77:20210823000625p:plain

なぜ-300にしたんでしょうか?

重力加速度なら-980にすべきでしょうに。

位置を変更すると突然Particleが消える事があります。直すためにBoundsを設定します。

f:id:kazuhironagai77:20210823000644p:plain

しました。

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

f:id:kazuhironagai77:20210823000704p:plain

マイナーな調整でVelocityのMinの値を10にセットしました。

f:id:kazuhironagai77:20210823000719p:plain

以下の様になりました。

f:id:kazuhironagai77:20210823000743p:plain

かなり滝の水飛沫に似て来ました。

これで最初のEmitterの作成は終わりです。

次のEmitterを作成します。

まずEmitterをDuplicateします。

f:id:kazuhironagai77:20210823000808p:plain

Required ModuleのMaterialをM_WaterfallSmokeに変更します。

f:id:kazuhironagai77:20210823000824p:plain

先程Materialの所でInstanceを作成したのになんで使用しないんでしょうか?

このEmitter単体だと以下の様なイメージになります。

f:id:kazuhironagai77:20210823000837p:plain

EmitterのSの箇所をクリックするとそのEmitterだけ表示するそうです。

f:id:kazuhironagai77:20210823000850p:plain

これは知りませんでした。

これで完成だそうです。

Levelに実際に配置してみました。

f:id:kazuhironagai77:20210823000907p:plain

雪のEffectと交わると結構、滝に見えます。

こんな簡単に出来るんですね。

これで終りと思ったらまだ続きがありました。

Starter Kitに付属のP_Steam_LitをcopyしてDuplicateします。

f:id:kazuhironagai77:20210823000928p:plain

名前をP_Waterfall_Smokeにします。

f:id:kazuhironagai77:20210823000942p:plain

これが滝が落ちた所に発生する蒸気を表します。

値を調整して蒸気っぽくします。

f:id:kazuhironagai77:20210823000958p:plain

f:id:kazuhironagai77:20210823001004p:plain

f:id:kazuhironagai77:20210823001011p:plain

f:id:kazuhironagai77:20210823001018p:plain

f:id:kazuhironagai77:20210823001026p:plain

SubImage Index moduleの値です。

f:id:kazuhironagai77:20210823001040p:plain

ここで値を以下の様に変更しました。

f:id:kazuhironagai77:20210823001054p:plain

f:id:kazuhironagai77:20210823001102p:plain

敢えて最初のin Valの値を0.1にする意味を忘れてしまいました。

Blogの何処かにこの理由を書いた記憶があるのですが見つかりません。後で探す事にします。

最後に

f:id:kazuhironagai77:20210823001120p:plain

を追加して値を以下の様にセットしました。

f:id:kazuhironagai77:20210823001141p:plain

これは滝が落ちる位置にこの蒸気を発生させるためだそうです。

これで終わりかと思ったらこっちのParticle Effectにも更にEmitterを追加します。

f:id:kazuhironagai77:20210823001203p:plain

そしてRequired ModuleのMaterialにM_WaterFallSmoke_Instをセットします。

f:id:kazuhironagai77:20210823001220p:plain

ここでInstanceを使用するんですね。

現状、こんな感じです。

f:id:kazuhironagai77:20210823001233p:plain

Spawn ModuleのSpawn Rateを1にします。

f:id:kazuhironagai77:20210823001309p:plain

Lock Axis Moduleを追加します。

f:id:kazuhironagai77:20210823001323p:plain

OrientationのLock Axis Flagsの値をzにセットします。

f:id:kazuhironagai77:20210823001336p:plain

このLock Axis ModuleはSpriteに貼りつけてある板の向きを常にカメラに向けるのではなく、Z軸に向けるようにするためのものだったはずです。

実際Previewを見てみるとZ軸に板が向いているように見えます。

f:id:kazuhironagai77:20210823001350p:plain

更に以下の値も変更しました。

f:id:kazuhironagai77:20210823001403p:plain

f:id:kazuhironagai77:20210823001409p:plain

f:id:kazuhironagai77:20210823001415p:plain

f:id:kazuhironagai77:20210823001421p:plain

f:id:kazuhironagai77:20210823001428p:plain

f:id:kazuhironagai77:20210823001435p:plain

f:id:kazuhironagai77:20210823001441p:plain

これでテストします。

f:id:kazuhironagai77:20210823001455p:plain

こんな感じです。

この後でTutorialでは黒い影が蒸気に見えるのでそれを消すためにMaterialに変更を加えています。

私の蒸気には別に黒い影は見えないのでその部分はパスします。

3.3 BPの作成

ActorクラスからBP_WaterFallを作成します。

f:id:kazuhironagai77:20210823001513p:plain

作成したBPに先程完成したP_WaterfallとP_WaterFallSmokeを追加します。

f:id:kazuhironagai77:20210823001526p:plain

以下の様なイメージになっています。

f:id:kazuhironagai77:20210823001539p:plain

位置を調整します。

f:id:kazuhironagai77:20210823001552p:plain

BPを配置してみます。

f:id:kazuhironagai77:20210823001607p:plain

うーん。下の蒸気が小さすぎます。後、色が少しだけ灰色になっています。

後はいいんじゃないでしょうか。

この後、Tutorialでは滝の音を追加していますが、ここまでで十分です。

3.4 まとめと感想

今回の Tutorialはかなり勉強になりました。やっぱり基本を理解してからこういう応用を勉強すると理解の深さが全然違います。

自分で更に工夫するとしたら

  • 滝の色が白のみだが黒や灰色を追加する
  • MeshにガラスのMaterialを貼り付けて滝に流して見る。
  • 蒸気はもっと大きくして、他の色を追加する。
  • 炎のEmberのような滝の周りに発生した水飛沫を追加する。

なんかが考えられると思われます。

4. 切符を道具として使用した場合の実装

先週、考えたように切符は道具で使用出来ないようします。

まず、切符は道具袋にしまってあるので道具袋にアクセスする時を全て抜き出します。

道具袋は、RPGGameInstanceのItemsにStringとして格納されています。

f:id:kazuhironagai77:20210823001658p:plain

この変数にAccessする関数を全て抜き出します。

f:id:kazuhironagai77:20210823001713p:plain

f:id:kazuhironagai77:20210823001720p:plain

f:id:kazuhironagai77:20210823001727p:plain

f:id:kazuhironagai77:20210823001734p:plain

f:id:kazuhironagai77:20210823001743p:plain

f:id:kazuhironagai77:20210823001751p:plain

f:id:kazuhironagai77:20210823001758p:plain

f:id:kazuhironagai77:20210823001805p:plain

f:id:kazuhironagai77:20210823001813p:plain

f:id:kazuhironagai77:20210823001820p:plain

f:id:kazuhironagai77:20210823001831p:plain

f:id:kazuhironagai77:20210823001838p:plain

f:id:kazuhironagai77:20210823001845p:plain

これらを一個ずつ虱潰しにチェックしていきます。

はい。見つけました。

Item Widgetでボタンをクリックされた時です。

f:id:kazuhironagai77:20210823001912p:plain

そのItemを消費して、HPやMPを回復させます。

f:id:kazuhironagai77:20210823001925p:plain

この後でチェックする事にします。

f:id:kazuhironagai77:20210823001940p:plain

これでいけると思います。

テストします。

f:id:kazuhironagai77:20210823001953p:plain

道具袋を開いて切符をクリックしましたが何も起きません。

出来ていますね。

これと同じやり方で全部やります。

今度は戦闘中にアイテムを選択した場合です。

f:id:kazuhironagai77:20210823002007p:plain

ここで切手かどうかチェックします。

f:id:kazuhironagai77:20210823002025p:plain

これで戦闘中にアイテムを使用する時も切手は選択出来ません。

テストします。

何回やっても出来ません。

何でと良く見たらContains関数のSubstringが切符ではなく切手になっていました。

直します。

もう一度テストします。

f:id:kazuhironagai77:20210823002042p:plain

今度は何回クリックしても切符は選択出来ません。

出来ました。

はい。全部Itemsが使用される箇所をチェックしました。

これで完成です。

5. 駅のバグ出し

先週さらに沢山の機能を駅に追加しました。それらをテストしていきます。

5.1 駅員と話しをします

「駅員と話しをする」をクリックします。

f:id:kazuhironagai77:20210823002113p:plain

駅員からの質問と、Playerが選択出来る回答が表示されます。

f:id:kazuhironagai77:20210823002125p:plain

「この駅について」を選択します。

f:id:kazuhironagai77:20210823002136p:plain

この駅は町から外の世界に出る為に建設されたので、駅員の回答は間違っています。

それぞれの駅で駅員の回答は変わるべきですがそのための機能はまだ作成していません。

5.2 その他の点について

他のバグは見つかりませんでした。

バグではありませんが、絵のキャラが駅員に見えません。直すべきです。

6. 実際のゲームに使用するmap1とテスト用のMap1を分ける

6.1 Map1をduplicateする

Map1は最初にPlayerが冒険するMapなんですが、テストをする為にあらゆるアクターが配置されていて実際のゲームのシナリオが作れません。のでDuplicateしてTest用のMap1とゲームに実際に使用するMap1に分ける事にします。

f:id:kazuhironagai77:20210823002212p:plain

開いて中を確認します。

f:id:kazuhironagai77:20210823002225p:plain

と書かれていますね。

やっぱり単にDuplicateしたら全部解決とはいかないようですね。

Playでmap1_Testの中身を確認します。

f:id:kazuhironagai77:20210823002239p:plain

イキナリErrorです。

直していきます。

RPG Game Mode BPのBeginPlay関数でそれぞれのMapにおけるPlayerの操作するキャラの発生する場所を指定しています。

ここにMap1_Testの場合を追加する必要がありました。

f:id:kazuhironagai77:20210823002252p:plain

しました。

f:id:kazuhironagai77:20210823002306p:plain

もう一回テストします。

墜落して死んでしまいました。

f:id:kazuhironagai77:20210823002319p:plain

良く見たらMap1と違う場所を指していました。

直します。

f:id:kazuhironagai77:20210823002343p:plain

テストします。

f:id:kazuhironagai77:20210823002357p:plain

Nav MeshのRebuildが必要とありますね。後でします。

音楽とかは普通に聞こえます。

Mapの移動が起こるEventはErrorが発生する可能性が高いので最初はそれ以外をテストします。

6.2 別なMapに移動するEventが発生しないEventをテストする

まずは道具屋です。

f:id:kazuhironagai77:20210823002417p:plain

会話をしたり買い物をしたりしましたが普通に出来ました。

問題ありません。

武器屋です。

f:id:kazuhironagai77:20210823002431p:plain

同じように問題ありません。

次はItemを拾ってみます。

f:id:kazuhironagai77:20210823002444p:plain

これも問題無く出来ました。

f:id:kazuhironagai77:20210823002457p:plain

武器を拾ってからの装備も問題無く出来ました。

f:id:kazuhironagai77:20210823002510p:plain

今度はNPCに話しかけました。全員問題無く回答してくれます。

f:id:kazuhironagai77:20210823002524p:plain

しかしNPCの会話は以下のParameterで指定された値で決まっています。今はMap1と同じ指定になっていますが後で調整が必要になると思います。

f:id:kazuhironagai77:20210823002537p:plain

6.3 戦闘をしてみる

今度は、Mapの移動のあるEventを試してみます。

まずは戦闘をしてみます。

途中までは順調でしたが戦闘が終わって石像と話す場面になっても後ろの髑髏が消えません。

f:id:kazuhironagai77:20210823002557p:plain

会話は普通に出来るみたいですね。

f:id:kazuhironagai77:20210823002609p:plain

褒美をもらって元のMapに戻って来ました。

f:id:kazuhironagai77:20210823002621p:plain

Map1とMap1_Testは見た目が一緒なのでどっちに戻って来たのか分かりません。

違いが分かるようにMap1_TestにはAnvil(金床)を置きました。目印です。

f:id:kazuhironagai77:20210823002636p:plain

もう一回戦闘してみます。

戻って来ました。

f:id:kazuhironagai77:20210823002710p:plain

Anvil(金床)がありました。Map1_Testに戻ってきてます。

戦闘が終わった時に空を回っている骸骨が消えないバグはMap1やLandscape4で戦闘した結果も考慮した後に直します。

6.4 宿屋に泊まる

宿屋は泊まって寝ている間は別なMapに移動しています。きちんとMap1_testに戻ってこれるか確認します。

宿屋に泊まってみます。

f:id:kazuhironagai77:20210823002731p:plain

金貨の表示がオカシイですね。後で直します。

泊まりました。

f:id:kazuhironagai77:20210823002809p:plain

Map1ではなくMap1_Testに戻っています。大丈夫みたいです。

ここで問題が発生しました。

敵のMonsterとの戦闘中に「逃げる」を選択して成功したら戦闘場で自由に動けるようになってしまいました。

f:id:kazuhironagai77:20210823002834p:plain

ただし元のMapには戻れません。

バグ発見です。後で直します。

6.5 神殿でセーブする

今度は神殿でセーブしてみます。セーブした後にLoadでゲームを開始してMap1_Testから始まるか試します。

f:id:kazuhironagai77:20210823002907p:plain

始まりませんね。以下に示した様にAnvil(金床)がありません。

Map1が開いています。

f:id:kazuhironagai77:20210823002920p:plain

所持していたItemなどはどうなってるんでしょうか?

f:id:kazuhironagai77:20210823002934p:plain

道具類は持っていますね。

Mapだけが違うようになっています。

しかしこれは設定によって何が正解か変わってくる可能性もあります。例えばH x Hのグリードアイランドではセーブした後で戻ってこられる場所は一か所だけです。

もう少し設定が煮詰まってから考える事にします。

6.6 駅での移動を試す

駅を使用してLandscape4に移動する事は可能なはずです。Landscape4からMap1_testに戻って来る事は出来ませんが。

試してみます。

f:id:kazuhironagai77:20210823002952p:plain

出来ました。

f:id:kazuhironagai77:20210823003005p:plain

6.7 Map1を開く

Nav MeshをRebuildしろと言うmessageがうざいので直そうと思ってMap1を開いたらUE4 Editorがクラッシュしました。

えっ。

もう一回開いて見ます。

f:id:kazuhironagai77:20210823003027p:plain

今度は大丈夫ですね。

Playを押しても大丈夫でした。

f:id:kazuhironagai77:20210823003041p:plain

後、Nav MeshをRebuildしろと言うMessageも消えています。やっぱりMap1のNav Meshが問題を起こしていたんですね。

6.8 Map1_Testで色々やってみる。

Map1の方はゲームの内容に合わせて色々変えてしますので、Map1_Testで今まで作成した機能の管理をします。のでもう少しMap1_Testで色々やってみます。

弓矢を装備しました。

f:id:kazuhironagai77:20210823003101p:plain

隣村に着きました。

f:id:kazuhironagai77:20210823003116p:plain

Blogにコメントを書いている間に夜になってしまいました。

f:id:kazuhironagai77:20210823003151p:plain

Map1の方は一日に長さの調節も必要ですね。

隣村のGateから外に出ました。

f:id:kazuhironagai77:20210823003205p:plain

村の外側を歩いていたら昔作成したWarp Gateがありました。

f:id:kazuhironagai77:20210823003218p:plain

こんなの作成したのすっかり忘れていました。

石橋ですがTextureの貼り方がオカシイ部分があります。

f:id:kazuhironagai77:20210823003231p:plain

倒したMonsterが消滅しません。

f:id:kazuhironagai77:20210823003245p:plain

新たなバグ発見です。

これもMap1やLandscape4で試した後に直します。

6.9 Map1やLandscape4で戦闘をしてみる。

Map1_Testの戦闘で見つかったバグがMap1やLandscape4でも起きるのか確認します。

Map1で試してみます。

Map1で戦闘に勝利するとまず以下のWidgetが表示されます。

f:id:kazuhironagai77:20210823003305p:plain

これはMap1_Testでは表示されませんでした。

閉じるボタンを押してWidgetを閉じます。

f:id:kazuhironagai77:20210823003333p:plain

後ろの骸骨は消えていますね。

石像に話かけました。

f:id:kazuhironagai77:20210823003347p:plain

ここからはMap1_Testも同じです。

Landscape4でも試してみます。

f:id:kazuhironagai77:20210823003401p:plain

Landscape4でもMap1と同じ結果になりました。

f:id:kazuhironagai77:20210823003413p:plain

f:id:kazuhironagai77:20210823003420p:plain

f:id:kazuhironagai77:20210823003426p:plain

今度はMonsterを倒した後、そのMonsterが消えているのかを確認します。

Map1に配置したMonsterと戦います。

f:id:kazuhironagai77:20210823003441p:plain

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

f:id:kazuhironagai77:20210823003454p:plain

Landscape4でも試してみます。

Monsterが2体しかいない赤線で囲った場所で戦ってみます。

f:id:kazuhironagai77:20210823003507p:plain

2体Monsterを倒したら赤線で囲った場所にはMonsterはSpawnしなくなりました。

f:id:kazuhironagai77:20210823003521p:plain

出来ています。

6.10 Map1_TestでMonsterを倒した後に消滅しない理由

これは分かりました。

以下にMap1_TestのLevel BPのBeginPlay関数の一部を示します。

f:id:kazuhironagai77:20210823003540p:plain

ここでこのLevelに生成するMonsterをRPG Game InstanceのArrayであるMonster Spawn Dataから得ています。しかしこのArrayはMap1のMonsterの生成のために作成されたものです。

RPG Game Mode BPで

f:id:kazuhironagai77:20210823003553p:plain

の最後でRemove Defeated Monster from Map1が呼ばれています。

f:id:kazuhironagai77:20210823003606p:plain

ここにMap1_Testを作成しないといけません。

しかしそのためにはRPG Game Instance BPにMap1_Test用のMonster Spawn Dataを作成して、Map1_Test Mapが開かれた時はそこからMonster を生成する必要があります。

更にMap1_Test用のMonster Spawn DataからMonsterを消滅する関数、Remove Defeated Monster from Map1_Testも必要です。

6.11 Map1_TestでMonsterを倒した後に消滅させる

まずは確認のためにRPG Game Mode BPのEventであるFightIsOverの最後で実装されている以下の部分にMap1_Testを追加しました。

f:id:kazuhironagai77:20210823003626p:plain

これでMap1_Test上で戦闘してもMonsterは消えるはずです。

テストします。

戦闘後、倒したMonsterは消えていました。

f:id:kazuhironagai77:20210823003650p:plain

だたし、今のままではMap1に移動しても同じ場所のMonsterは消滅しています。

Map1とMap1_Testは違うMapですのでMap1_TestでMonsterを倒してもMap1のMonsterが消滅してはおかしい訳です。

これを直していきます。

まずRPG Game Instance BPにMap1_Test用のMonster Spawn Dataを作成しました。

f:id:kazuhironagai77:20210823003703p:plain

中身はMonster Spawn Dataと一緒です。Duplicateして作成しただけです。

今度はMap1_Test Mapが開かれた時にMonster Spawn Data Map1_TestからMonsterを生成するようにします。

Map1_Test MapのEvent Begin PlayのMonsterを生成する部分の実装を以下のように変更しました。

f:id:kazuhironagai77:20210823003719p:plain

更にMap1_Test用のMonster Spawn DataからMonsterを消滅する関数を作成します。

f:id:kazuhironagai77:20210823003732p:plain

出来ました。

中身はRemove Defeated Monster From Map1と全く同じで、赤線で囲った部分だけ変更しています。

f:id:kazuhironagai77:20210823003746p:plain

この部分をParameterにして関数にパスするようにすれば、Remove Defeated Monster()関数は一個で済みますね。後で整理する時に考えてみます。

この関数を実装しました。

f:id:kazuhironagai77:20210823003800p:plain

これでいけるはずです。

試してみましょう。

Map1_TestでPlayを開始しました。

Monsterは普通に生成されています。

f:id:kazuhironagai77:20210823003813p:plain

Monsterを一体倒しました。

以下のWidgetも表示されるようになりました。

f:id:kazuhironagai77:20210823003828p:plain

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

f:id:kazuhironagai77:20210823003841p:plain

この後、銀河鉄道に乗って、Landscape4に移動して、更に銀河鉄道に乗ってMap1に移動しました。

Map1の同じ場所のMonsterは消滅していません。

f:id:kazuhironagai77:20210823003854p:plain

出来ています。

6.12 新たなバグの発見

Map1からMap1_Testを開こうとするとUE4Editorがクラッシュします。逆もまたしかりです。

多分ですが、Map1とMap1_Testで同じMemoryを使用してる部分があるからだと思います。直接Map1からMap1_Testは開かないようにします。逆もしないようにします。

今週はここまでとします。

来週は更にMap1とMap1_Testで共同に使用しているData、例えばItemのSpawnのData、を別にしていきます。

今Map1で生成されている事全てがMap1_Testで生成されるようになったらMap1上で本当のRPGを作成していきます。

再来週位にはMap1上でRPGの物語が制作出来るようにしたいです。

裏切りの石像がくれる褒美がパスのままです。後で切符に直します。

これで今週のRPGの実装は終りにします。最後にこのまま閉じてもこのProjectが問題なく開ける事を確認しておきます。

普通に開けました。

f:id:kazuhironagai77:20210823003917p:plain

大丈夫でしょう。

残りは来週やります。

7. 別なマップに移動してる間に別なアニメーションを表示する方法についての調査の続き

7.1 Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [8]の続きを勉強する

先週、途中まで勉強したUnreal Fest Europe 2019のAxel Riffard氏の講演の続きをやります。

f:id:kazuhironagai77:20210823003953p:plain

IActionRPGLoadingScreenModuleはInterfaceなので実装出来ないはず。

と思ったらFActionRPGLoadingScreenModuleクラスがIActionRPGLoadingScreenModuleを継承してActionRPGLoadingScreen.cpp内で宣言と実装を一遍にやっていました。

以下に先週のBlogのその部分について述べた所を示しておきます。

f:id:kazuhironagai77:20210823004009p:plain

Axel Riffard氏のスライドの説明から、予測した時は

f:id:kazuhironagai77:20210823004024p:plain

となっていました。ActionRPGが抜けている以外はほぼ予測通りですね。

後、図ではIModuleInterfaceはFLoadingScreenModuleから呼ばれていますが

f:id:kazuhironagai77:20210823004037p:plain

実際のコードでは

f:id:kazuhironagai77:20210823004050p:plain

IActionRPGLoadingScreenModuleの親Interfaceで、FActionRPGLoadingScreenModuleから直接は呼ばれていませんね。

そうは言っても大体の予測は合ってます。

次の私の予測である

f:id:kazuhironagai77:20210823004115p:plain

を調べて見ます。

SLoadingScreenはActionRPG内ではSRPGLoadingScreenと呼ばれていました。

f:id:kazuhironagai77:20210823004138p:plain

あ、SCompooundWidgetを継承しています。これについては後で述べる事にします。

はい。

FActionRPGLoadingScreenModuleクラスのメンバー関数であるStartInGameLoadingScreen()と

f:id:kazuhironagai77:20210823004207p:plain

CreateScreen()内で使用されています。

f:id:kazuhironagai77:20210823004155p:plain

予測の通りでした。

更にSLoadingScreenからFLoadingScreenBrushが呼ばれると予測していますが、

f:id:kazuhironagai77:20210823004244p:plain

ActionRPGにおけるSLoadingScreenBrushクラスにあたるFRPGLoadingScreenBrushクラスが呼ばれています。

f:id:kazuhironagai77:20210823004259p:plain

これも予想通りでした。

また、

f:id:kazuhironagai77:20210823004312p:plain

と予測しましたが実際は以下に示した様に

f:id:kazuhironagai77:20210823004329p:plain

f:id:kazuhironagai77:20210823004335p:plain

SRPGLoadingScreenクラスはSCompoundWidgetクラスの子クラス、RRPGLoadingScreenBrush構造体はFSlateDynamicsImageBrushの子でした。

大体のコードの実装方法が理解出来ました。

しかしこれThread使ってないですね。

まあこんだけ理解しておけば大丈夫でしょう。講義の内容に戻ります。

f:id:kazuhironagai77:20210823004408p:plain

今度はSlateについてのようです。

SlateはSherif, William氏のUnreal Engine 4 Scripting with C++ Cookbook のAdding Slate Widgets to the screen [9]などで散々勉強したので大体分かるでしょう。

正直、UMGが存在している今、非ProgrammerがSlateを触るメリットはあんまりないと思っています。

私が初めてUnreal Engine 4 Scripting with C++ CookbookでSlateを勉強した時は、UMGとSlateの違いも知らなかったし、Game制作においてC++で書く必要がある部分とない部分の区別もついていませんでした。

今の私が当時の何も分からない状態でSlateを勉強している私にアドバイスを送るとしたら、

  • Game内で表示するWidgetUMGを使用して作成すべき。
  • Slateを使用した方が良い場合は以下の2点のみ
    • UE4Editorの形状に変化を追加したい場合
    • UMGを使用するより速くWidgetを表示したい場合

です。

以下のサイトがSlateについて非常に分かり易く解説されているとありました。

f:id:kazuhironagai77:20210823004450p:plain

覚えておきましょう。

次のSlideです。

f:id:kazuhironagai77:20210823004504p:plain

今度はModule Logicの実装についてです。

Module Logicの実装って先程自分で考証した

f:id:kazuhironagai77:20210823004518p:plain

についての実装なのかと思ったら

f:id:kazuhironagai77:20210823004532p:plain

のメンバー関数についてでした。

ここで重要なのは

f:id:kazuhironagai77:20210823004547p:plain

が呼ばれている事だそうです。

うーん。

f:id:kazuhironagai77:20210823004603p:plain

色んな所で呼ばれていますね。

でもこの関数を呼ぶ事で別なアニメーションを表示出来る訳ですね。

それじゃこのGetMoviePlayer()関数の流れを実際のコードで追ってみますか。

f:id:kazuhironagai77:20210823004619p:plain

まずFActionRPGLoadingScreenModuleが作成されます。

多分ですが、以下のメンバー関数、StartupModule()が最初に呼ばれるはずです。

f:id:kazuhironagai77:20210823004646p:plain

するとStartupModule()関数内に実装されているHelper関数である

f:id:kazuhironagai77:20210823004700p:plain

が呼ばれます。このCreateScreen()関数内には

f:id:kazuhironagai77:20210823004715p:plain

GetMoviePlayer()関数が使用されています。

FActionRPGLoadingScreenModule内の次のメンバー関数である

f:id:kazuhironagai77:20210823004733p:plain

でも全く同じ様にGetMoviePlayer()関数が使用されています。

f:id:kazuhironagai77:20210823004748p:plain

ただしパスされるLoadingScreenのAttributeの値は微妙に変わっています。

CreateScreen()関数では

f:id:kazuhironagai77:20210823004802p:plain

はTrueにセットされていますが、

StartInGameLoadingScreen()関数内では

f:id:kazuhironagai77:20210823004818p:plain

となっています。

CreateScreen()関数が呼ばれた場合はLoadingが終わった瞬間にMovieの再生も終了しますが、StartInGameLoadingScreen()関数が呼ばれた場合はLoadingが終わったとしてもMovieの再生が終わるまでLoading Screenは継続すると考えられます。

これ位しか、理解出来ませんね。

次のSlideを見ます。

f:id:kazuhironagai77:20210823004843p:plain

はい。これが聞きたかった。正直これまでの実装はMulti-threadにあんまり詳しくない私でも理解出来る内容です。

こっからが本番です。

f:id:kazuhironagai77:20210823004904p:plain

えっ。

じゃあ、別に自分でFAsyncTask()関数を呼び出さなくて良いの?

更に次のSlideでこう述べられています。

f:id:kazuhironagai77:20210823004918p:plain

え。どういう事。

つまり上記のコードをそのまま使用すればAsyncになってるって事?

次のSlideでSlateが実際に別なThreadとして作成されている証拠として実際のコードが表示されていました。

うーん。

成程。

この後のSeamless TravelはMulti player用のLoading Screenの作成方法だそうなので勉強するのはここまでとします。

実際にこの方法で作成するとなると、FActionRPGLoadingScreenModuleクラスをBP側で作成出来るのか、それともUEC++側でこのクラスを作成する、別なBPからCallableな関数が必要なのかを調べないといけませんが、それもActionRPGを見れば分かるでしょう。

うーん。思ったより簡単でした。

先週、勉強出来なかった残りの2つのTutorialも見てみます。

7.2 Unreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [8] を勉強する。

まずサラッと全部みました。

それで知らない事が2個があったんです。

まずSub Levelです。

f:id:kazuhironagai77:20210823004946p:plain

次にLoad Stream Levelノードです。

f:id:kazuhironagai77:20210823004959p:plain

このノードでLevelを開くと

f:id:kazuhironagai77:20210823005012p:plain

f:id:kazuhironagai77:20210823005019p:plain

BackgroundでLevelをLoadしてくれるって説明されています。

あれ?

じゃこのノードの使い方さえ分かればAsync でLoading Screenを表示出来るんじゃね?

その後で、説明しているGame InstanceにDispatcher を作成して云々は、まあ誰でも思いつく方法だと思いますのでスキップします。

7.3 Load Stream Levelノードについて

予定を変更してLoad Stream Levelノードを調べる事にします。

公式のDocumentのLevel Streaming [12] に以下の解説ありました。

f:id:kazuhironagai77:20210823005040p:plain

この下にある解説を読むと、分割して(恐らく複数のMapで)管理している広大な世界を、Seamlessな読み込みを行う事でPlayerにとっては一つの大きな世界のように見せる技術があるそうです。

それを可能にするための機能としてLoad Stream Levelノードが使用されているそうです。

へー。

MMOなんかで何千人が同時にPlayするゲームだと非常に広大なMapとかが必要になるんでしょうか?

それは兎も角、今週はLoad Stream Levelノードの使用方法だけ勉強出来れば十分です。

見つからない。

なぜかLoad Stream Levelノードの使用方法だけ説明しているTutorialが見つかりません。そう言えば公式のDocumentも見つかりません。

うーん。これはLevel Streamingを理解してから使用しろという啓示なんでしょうか?

来週、一寸考えてから決断します。

7.4 Sub Levelについて

Sub Levelに関してですが、まず定義が分かりません

広大な一個のMapを分割して、その分割したそれぞれのMapをSub Levelと呼んでいるみたいです。

公式のDocumentであるLevels [13]には

f:id:kazuhironagai77:20210823005126p:plain

f:id:kazuhironagai77:20210823005133p:plain

の二つでSub Levelの使用方法や作成方法についての解説をしています。

これらは複数のMapで管理している広大な世界をSeamlessな読み込みを行うための技術です。

私は単にLoading Screenで鉄道に乗っているシーンを写している間にBackgroundで次のLevelを読んでほしいだけです。Load Stream Levelノードで読み込むLevelは必ずSub Levelになってないといけないんでしょうか?

その辺が良く分かりません。

後、Mathew Wadstein氏のHTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [14]を見つけました。Mathew Wadstein氏のTutorialは分かり易いので後で見てみます。

結論としては、これも来週考えます。

7.5 How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [9] を勉強する。

このTutorialは以下に示したPlug-inを使用して作成する方法を解説しています。

f:id:kazuhironagai77:20210823005155p:plain

これはLoad Stream Levelノードの使用方法を理解した後で勉強したいです。

のでこれは来週に回します。

8. Good Skyの復習

のおおあ。

今週こそはこれを終わらせようとしたんですが時間が無くなってしまいました。

来週やります。

9. まとめと感想

Particle Systemの勉強に関してですが、Niagaraはかなり理解してきました。

Niagaraを使用したParticle systemの作成にはオリジナルなModuleの作成のようなProgrammer向きのTaskと炎のEffectの作成におけるEmber Emitterの作成のようなDesigner向きの Taskがある事が分かりました。

正直中々面白い分野だと思います。

Cascadeは今週は良く勉強できました。選んだTutorialが良かったんだと思います。

Cascadeはもうやらなくて良い気もしているんですが、今止めるとCascadeの使用方法を全部忘れそうなのでもう少しだけ勉強を続けます。

RPGの製作についてですが、以下の2点を行いました。

  • 切符は道具として使用出来ないように実装した。
  • Map1Duplicateして片方をテスト用、もう片方を実際のゲーム用にした。

テスト用のMap1は今までのMap1と同じ挙動を示すためにはもう少し改造が必要です。来週も引き続きテスト用のMap1の改造を行います。それが完成したら実際のゲーム用のMap1を改造します。

Async なLoading Screensの作成方法については、最初のTutorialの勉強は終えました。2番目のTutorialはSteamlessなMapの読み込みに使用するLoad Stream Levelノードを使用してBackgroundでLevelをLoadしています。これを理解するためにはもう少しLevel Streamingの勉強が必要かもしれません。来週までに何を勉強するのかを決めます。

以上です。

10. 参照(Reference

[1] Epic Games [Unreal Engine]. (2019, May 20). Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=ON1_dEHoNDg

[2] CGHOW. (2020, July 21). Nebula Effect | UE4 Niagara Nebula | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=niSWXhWNyQQ&list=PLwMiBtF6WzsqC7_cJmD26ts0YDbtPCCfe&index=11

[3] Epic Games. (n.d.-c). Particle Spawn Group. Unreal Engine Documentation. Retrieved August 22, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/ParticleSpawn/

[4] gameDev Outpost. (2020, December 24). UE4 - Niagara Static Mesh and Surface [Video]. YouTube. https://www.youtube.com/watch?v=lkdFu0rAV18

[5] Werner, P. (2021, August 16). Intro to Curl Noise. Shifting Sands. http://petewerner.blogspot.com/2015/02/intro-to-curl-noise.html

[6] Epic Games. (n.d.-d). What is Scratch Pad Module? - UE4 AnswerHub. UE4 AnswerHub. Retrieved August 22, 2021, from https://answers.unrealengine.com/questions/981653/what-is-scratch-pad-module.html

[7] Realtime 3D NowYoshi. (2020, July 28). Waterfall | Detailed Tutorial | Unreal engine 4 Particle Systems [Video]. YouTube. https://www.youtube.com/watch?v=ZzTsZWkXScQ

[8] Epic Games [Unreal Engine]. (2019b, May 20). Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=ON1_dEHoNDg

[9] Sherif, William. Unreal Engine 4 Scripting with C++ Cookbook (Kindle Locations 5126-5127). Packt Publishing. Kindle Edition.

[10] Reids Channel. (2019, December 15). Unreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [Video]. YouTube. https://www.youtube.com/watch?v=lzGcVDUDU5g

[11] Uisco. (2021, March 3). How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=KpXmcqSITOg

[12] Epic Games. (n.d.-a). Level Streaming. Unreal Engine Documentation. Retrieved August 22, 2021, from https://docs.unrealengine.com/4.26/en-US/BuildingWorlds/LevelStreaming/

[13] Epic Games. (n.d.-b). Levels. Unreal Engine Documentation. Retrieved August 22, 2021, from https://docs.unrealengine.com/4.26/en-US/Basics/Levels/

[14] Wadstein, M. [Mathew Wadstein]. (2015, October 31). HTF do I? Loading Screens using Level Streaming in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=QJVn2mW67YQ

 

 

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する Ticket Systemなどの作成 Part 2

f:id:kazuhironagai77:20210815231212p:plain

<前文>

<徹底的に追いつめられると、何故か土下座して許してもらおうとする日本人>

先週、突然気が付いたんですが、日本人が誤解しているアメリカ、特に日本文化とキリスト教文化の違いから生じる勘違いについて専門的に語っている人がいないんです。山本七平氏の「空気の研究」や井沢元彦氏の「逆説の日本史」のような第三者的な観点から日本文化の独自性について語っている人はいますが、その結果、日本にとって最も重要な国であるアメリカとの関係にどんな影響が生じるのか論じている人はいません。

これ、滅茶苦茶大切な事です。

それで在米歴10年の私が、それについて重点的に語る事にしました。

今週は、日本人と土下座に関してです。

日本人全体に言える事ですが、徹底的に追いつめられると、何故か土下座して謝って許してもらおうとします。

これってアメリカでは全く通じませんから。

戦後、キリスト教文化のrepentanceが歪んだ形で紹介されて、キリスト教では真剣に謝れば許してくれる的な解釈で日本文化に受け入れられたんだと思いますが、repentanceが通じるのはあくまで真摯に反省してそれまでの悪い行いを直す約束をした場合のみですから。

大体、キリスト教的な考えからしたら、悪い事をしていないのに、罪の告白をしたらそれ自体が大変な罪です。後、repentanceは神様に対してするモノで人間に対してするモノではありません。

長年の間、何で日本人は徹底的に追いつめられると、土下座して謝って許してもらおうとするのか、私には不思議でした。

知り合いの人から聞いた話ですが、その人の友人は元ラグビー部で身長が185cmもあったのに、ヤクザに殺された時に包丁で刺されまくっているのに、土下座して謝っていたそうです。

更に重要な問題ですが、土下座された方だって、ヤクザとかじゃなく常識的な人だったら困ってしまうでしょう。だって土下座されても何も問題は解決しないんですから。

そこで、気が付いたんですが、土下座って日本文化なんですよ。

先程の例でもヤクザと土下座なんて、もろに日本文化じゃないですか。

じゃあ、アメリカを含むキリスト教文化の国(もしくは会社でも、個人でも)との関係で徹底的に追いつめられたとき、土下座して謝って許して貰おうとするより良い方法があるんかよ?となりますが、あります。

それは徹底的に自分の無実を主張する事です。

日本人から見ると、不思議なアメリカを含むキリスト教文化の特徴の一つですが、正式な裁判を受ける権利を奪うのは大変な罪なんです。

アメリカ人は謝らないと言うのは嘘です。アメリカ人も日常生活では結構、頻繁に謝ります。

ただし絶体絶命な状態に追い込まれた時、つまり日本人が土下座するような状況になった時は、絶対に謝りません。それは謝ったら無罪を裁判で主張出来ないからです。

ほとんどの日本人にとってアメリカを含むキリスト教圏の関係者から徹底的に追いつめられる事は、現状ではないと思います。しかしもしそういう事態になって、もう土下座してでも良いから許してもらおうと思ったら、そこは踏みとどまって、無罪を主張する方法に変換して下さい。少なくとも土下座するよりはマシな結果になりますから。

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

<本文>

 1.今週の予定

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

  • Particle Systemの勉強
    • Niagaraの勉強
    • Cascadeの勉強
      • 砂のEffectの作成
      • Boundについての復習
    • RPGの作成の続き
      • 駅の実装のテスト(バグ出し)
      • 切符を使用して銀河鉄道に乗る機能の実装
      • 切符を道具として使用した場合の検討
      • 別なマップに移動してる間に別なアニメーションを表示する方法についての調査
    • Good Skyの復習

2. Niagaraの勉強

一応、Niagaraの基本は理解したので、先々週から応用編としてCGHOW氏のTutorialの勉強を始めました。

しかし先々週から始めたTutorialは途中で雲にLight を照らす方法が分からなくてとうとう頓挫してしまいました。

頓挫してしまった理由の一つは、CGHOW氏のTutorialで2019以前に作成されたものは、現在のNiagaraと少し形状が違っていて単純に真似て作成する事が出来ない箇所があったからです。

ので今回はCGHOW氏が、2020年以降に作成されたTutorialで時間が短いものをやってみます。

2.1 CGHOW氏のNebula Effect | UE4 Niagara Nebula [1]をやってみる。

まず、EmptyのNSを作成しました。名前はTestです。

f:id:kazuhironagai77:20210815231400p:plain

Emitter UpdateにSpawn Rate Moduleを追加しました。

f:id:kazuhironagai77:20210815231414p:plain

Spawn Rateに1000をセットします。

f:id:kazuhironagai77:20210815231428p:plain

Sprite が生成されました。

f:id:kazuhironagai77:20210815231442p:plain

Particle Spawn CategoryにSphere Location Moduleを追加しました。

f:id:kazuhironagai77:20210815231507p:plain

以下の様になりました。

f:id:kazuhironagai77:20210815231522p:plain

正し、Tutorialは以下の様になっています。

f:id:kazuhironagai77:20210815231536p:plain

うーん。

Sphere Radiusの半径を100から1000に変更してみます。

f:id:kazuhironagai77:20210815231552p:plain

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

f:id:kazuhironagai77:20210815231605p:plain

これでいきます。

そしたら、TutorialではこのSphere Location Moduleを外して、代わりにStatic Mesh Location Moduleを追加しました。

f:id:kazuhironagai77:20210815231620p:plain

このTutorialによればStatic Mesh Location Moduleの機能は、Sphere Location Moduleと同じだが、Sphereの代わりに指定したMesh内にSpriteを発生させるそうです。

そして使用するMeshを指定するためにSample Static Mesh Moduleの使用が要求されます。

Sample Static Mesh Module内で使用するMeshを指定します。

f:id:kazuhironagai77:20210815231634p:plain

Tutorialと同じMeshをセットしました。

Preview MeshとDefault Meshがどう違うのかは良く分かりませんね。調べようかと思ったら、それを調べるよりもっと大きな問題が起きてました。

f:id:kazuhironagai77:20210815231653p:plain

Sphere Location Moduleを使用した時と同じように、Cube全体が光っています。

Tutorialでは以下のような感じなのに。

f:id:kazuhironagai77:20210815231707p:plain

Sphere Location Moduleを使用した時と同じようにMeshのサイズを大きくしようとしたら、

f:id:kazuhironagai77:20210815231719p:plain

そんな機能はついていません。

ではSpriteのサイズを小さくします。

f:id:kazuhironagai77:20210815231735p:plain

あれ、SpriteのサイズってRendererで指定していませんでしたっけ。

どのModuleでSpriteのサイズを指定出来たのか忘れてしまいました。

Googleで検索したらgameDev Outpost 氏のUE4 - Niagara Adjusting Size [2] で説明されていました。

Initial Particle ModuleのSprite Attributesで指定できます。

f:id:kazuhironagai77:20210815231756p:plain

Uniform Sprite Sizeを10から3に変更しました。

f:id:kazuhironagai77:20210815231810p:plain

今まで、Initial Particle Moduleは何回も使用していたにも関わらずすっかり名前を忘れてしまってました。

結果を以下に示します。

f:id:kazuhironagai77:20210815231836p:plain

大体、Tutorialと同じイメージになりました。

今度はParticle Update にCurl Noise Force Moduleを追加します。

f:id:kazuhironagai77:20210815231853p:plain

Default値がTutorialの値と違います。

f:id:kazuhironagai77:20210815231907p:plain

Previewのイメージはイイ感じです。Spriteのばらつき具合が良いです。

f:id:kazuhironagai77:20210815231925p:plain

値をTutorialと同じにしてみます。

f:id:kazuhironagai77:20210815231941p:plain

バラツキがなくなり一気に下に落ちて行っています。

f:id:kazuhironagai77:20210815231957p:plain

Tutorialのイメージとは全然違います。Tutorialのイメージを以下に示します。

f:id:kazuhironagai77:20210815232014p:plain

Curl Noise Force Module の値を色々いじって見ました。

以下の値の時に綺麗な挙動をします。

f:id:kazuhironagai77:20210815232031p:plain

こんな感じです。

f:id:kazuhironagai77:20210815232152g:plain

取りあえずこれでいきます。

今度は、Particle Update にDrag Moduleを追加します。

f:id:kazuhironagai77:20210815232219p:plain

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

f:id:kazuhironagai77:20210815232240g:plain

Initialize Particle ModuleでSpriteのサイズを1にしました。

f:id:kazuhironagai77:20210815232500p:plain

のわあー。

結局、TutorialでもSpriteのサイズを変えてるじゃないか。

今度は、Emitter Properties ModuleのSim TargetからGPUを使用するように変更しました。

f:id:kazuhironagai77:20210815232520p:plain

Tutorialではこの変更後何も起きていませんが、私の方では、以下の様な警告が出ています。

f:id:kazuhironagai77:20210815232540p:plain

Bound ボタンを押して以下の様なBoundを作成しておきました。

f:id:kazuhironagai77:20210815232555p:plain

勿論、警告は消えました。

勿論、GPUに変更した後はSpawn Rateを増やします。10000にセットしました。

f:id:kazuhironagai77:20210815232612p:plain

こんな感じです。

f:id:kazuhironagai77:20210815232636g:plain

Vortex Force Moduleを追加します。

f:id:kazuhironagai77:20210815232720p:plain

ここまで来て大問題です。

Tutorialでは、以下のStatic Mesh をMayaで作成して使用しています。

f:id:kazuhironagai77:20210815232736p:plain

これの作り方は分かりませんね。

ここは無視して先に進みます。

次はTextureに星雲のイメージを使用する方法を勉強します。

星雲のイメージ自体がないのでUnsplash [3] から以下のイメージをDownloadしました。

f:id:kazuhironagai77:20210815232752p:plain

Materialを作成します。

f:id:kazuhironagai77:20210815232807p:plain

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

f:id:kazuhironagai77:20210815232821p:plain

以下の様なイメージになりました。

f:id:kazuhironagai77:20210815232835p:plain

拡大すると分かりますが一つのParticle にTextureのImage全体が貼り付けられています。

f:id:kazuhironagai77:20210815232852p:plain

Particle全体にこのTextureを貼りたいのです。そのために、

Materialの実装を以下の様に変更して、

f:id:kazuhironagai77:20210815232910p:plain

Particle Spawn のSample Static Mesh ModuleとStatic Mesh Location Moduleを消去します。

f:id:kazuhironagai77:20210815232932p:plain

そしてScratch Moduleを追加します。

f:id:kazuhironagai77:20210815232950p:plain

Scratch Moduleの中身を以下の様に作成しました。

f:id:kazuhironagai77:20210815233005p:plain

おお。初めてModuleの中身を作成しました。内容については後で検討します。

Scratch ModuleのMeshをセットして

f:id:kazuhironagai77:20210815233019p:plain

Reviewを見ると、まだ一個のParticle に対してTexture全体を使用しています。

f:id:kazuhironagai77:20210815233051p:plain

これを直すために、Scratch Moduleの実装を以下の様に変更しました。

f:id:kazuhironagai77:20210815233107p:plain

これも内容については後で検討します。

全部のParticle に対してTexture全体を使用するようになりました。

f:id:kazuhironagai77:20210815233127p:plain

出来た。と思ったら以下に示したTutorialのEffectと同じにするにはまだ色々追加する必要があるそうです。

f:id:kazuhironagai77:20210815233146p:plain

元々、使用しているNebulaのTextureが違うし、Meshの形状も違うので全く同じになる訳がないので、ここからは話を聞く位の軽い感じでTutorialをやっていきます。

まず作成したEffectが3つありました。

f:id:kazuhironagai77:20210815233205p:plain

一番左のEffectが今、私が作成したものと同じヤツだそうですが、以下の点が改良されているそうです。

  • Particleの数を増やしている。
  • Curl Noise Forceが追加されています。
  • Scale Sprite Sizeで以下の様な値をセットしている

f:id:kazuhironagai77:20210815233236p:plain

2番目のEffectは最初のEffectをDuplicateして作成しました。

f:id:kazuhironagai77:20210815233254p:plain

そして以下の点を変更しました。

  • Spawn Rateの数を減少します。
  • 使用しているMaterialを以下の物に変更します

f:id:kazuhironagai77:20210815233322p:plain

  • そのためParticle SpawnInitialize Particle ModuleColorの値を1以上にセットする事が出来ます。

f:id:kazuhironagai77:20210815233351p:plain

最後のEmitterもDuplicateして作成します。

f:id:kazuhironagai77:20210815233406p:plain

そして以下の点を変更しています。

  • Sprite RendererAlignmentVelocity Alignedにセット。

f:id:kazuhironagai77:20210815233445p:plain

  • Initialize Particle ModuleのSprite Sizeの値を以下の様に変更

f:id:kazuhironagai77:20210815233515p:plain

だそうです。

最後にこのTutorialで使用したStatic Meshの作成方法をMayaを使用して説明しています。

2.2 Nebula Effect | UE4 Niagara Nebula [1]をやってみての感想やまとめ

前回のSmokeのTutorialと比べるとかなり本格的なVFXでした。

実装面から言えば、

  • GPUを使用している
  • Sample Static Mesh Moduleを使用している(前半部分)
  • Scratch Moduleを使用してオリジナルのModuleを作成している

という事を新たに学びました。

更に、使用するStatic MeshをMAYAを使用して自分で作成するなど、今まで勉強したモノよりかなり難易度の高いTutorialでした。

しかし、CGHOW氏のTutorialの作成方法は最初に、最終的には使用しないSample Static Mesh Moduleを使用して、視聴者にやりたい事を理解させて、その後でScratch Moduleを使用してオリジナルのModuleを作成する事で、私のような比較的初心者レベルでも付いてこれる様に工夫がされていました。

CGHOW氏は大学教授なんでしょうか?教え方が素人じゃないような気がします。これは勉強しがいのあるTutorialかもしれません。

2.3 来週の予定

来週はCGHOW氏の別なTutorialをやろうと思っていたのですが、今週、Nebula Effect | UE4 Niagara Nebula [1] をやってみて、余りに内容が濃かったので来週は復習や深堀をする事にします。

来週の予定としては、

  • Moduleの勉強
    • Static Mesh Location Moduleについて
    • Curl Noise Force Moduleについて
    • Drag Moduleについて
    • Vortex Force Moduleについて
    • Scratch Moduleについて
  • GPUの使用について
    • 一般的な概要について
    • Boundについて
  • Scratch Moduleの中身の実装について
    • 最初のサラの状態で存在するノードの機能や役割を調べる。

f:id:kazuhironagai77:20210815233628p:plain

    • 左脇に表示されているToolについて調べる

f:id:kazuhironagai77:20210815233808p:plain

  • このTutorialで追加したNodeとその役割について調べる。

f:id:kazuhironagai77:20210815233846p:plain

  • 作成したModuleの機能について解説する。
  • 今回作成しなかった残りのEffectも作成する。

を行います。

3. Cascadeの勉強

3.1 砂のEffectの作成

CascadeのTutorialを探したんですが見つかりません。ので今回は以下のTutorialを見て砂のEffectの作成についての知見を高める事にします。

です。

サッと、最初の5分位見たのですが、両方とも単なるTutorialと言うより、砂の作成における理論と実践方法についての解説と言う感じでした。こういう勉強もたまには良いでしょう。

3.2 Sand Rendering in Journey [4] を見て

Thatgamecompany社のJohn Edwards氏がGDCで講演した内容です。GDCはGame Developer Conferenceの略です。

Sand Rendering in Journey(砂のレンダリングの旅)と言う題から、ゲームにおける砂のRenderingの歴史について語るのかと思ったら全然違いました。この会社が制作しているゲームの名前がJourneyだったんです。つまりそのゲームにおける砂のRenderingについての講演でした。

f:id:kazuhironagai77:20210815234009p:plain

このゲームはPhyreEngineを使用して作成されたそうです。

PhyreEngineは初めて聞くGame Engineです。

ちょっと調べて見ます。

ぱっと見た所、9年前位で開発が止まっていますね。このゲームも2012年に制作されたようです。

まあでも、役に立つ話はあるでしょう。取りあえず聞いて行きます。

<砂のRenderingについて>

MIT Map Sharpening Effectについてです。遠くの景色をSmoothにする効果があるそうです。

これが元のイメージです。

f:id:kazuhironagai77:20210815234031p:plain

こっちがMIT Map Sharpening Effectを使用した場合です。

f:id:kazuhironagai77:20210815234045p:plain

遠くの景色がどこからなのかが分からないですが、砂が柔らかくなっている印象を受けます。特に人が立っている辺りの左右の砂が砂らしいです。

ただし太陽からの光を反射している箇所は、両方ともまるでビニール樹脂のようです。

Anisotropic maskingのEffectについてです。

f:id:kazuhironagai77:20210815234259p:plain

Radioactive Oatmeal on the Silhouettesみたいと語っていますが、ギラギラ光り過ぎていると語りたいのでしょうか?

Anisotropic filteringってどんな技術でしたっけ。全く覚えていないです。

ちょっと調べます。

非常に簡単に言うと、見る角度によってあらゆる物体はちょっと歪んで見えます。その歪みを考慮してTextureを貼る事をAnisotropic filteringと言うみたいです。

実際の計算方法までは調べませんでした。

Filteringの歴史は、なし、Bi-liner、MIP、Tri-Liner、そしてAnisotropic filteringとなるみたいですね。上記のAnisotropic maskingはMIPかTri-Linerを加えた上にAnisotropic filteringを行っているんでしょうか?

Textureを歪ませて貼った結果、現実離れしたギラギラ感が発生してしまったと言う事が言いたいみたいですね。

それよりも私は太陽の光を反射している箇所のビニール感が気になります。

Glitter Specularです。

f:id:kazuhironagai77:20210815234402p:plain

John Edwards氏の説明にあるようにAnisotropic maskingよりギラギラ感が消えています。

Glitter Specularという技術が何を指しているのか不明ですが、砂のキラキラ感を表現する技術なんでしょうか?

Anisotropic filteringを使用する事で砂のキラキラ感がオカシクなってしまったので、別な方法で砂のキラキラ感を計算したんでしょうか。それがここで言うGlitter Specularの事なのかもしれませんね。

Ocean Specularです。

f:id:kazuhironagai77:20210815234436p:plain

何と、太陽の光を反射している箇所のビニール感がなくなりました。

Ocean Specularに関してはJohn Edwards氏は反射を消したとだけ説明しています。

f:id:kazuhironagai77:20210815234452p:plain

単なるLambert Shadingを使用した場合と、カスタム化したDiffuse Shadingを使用した場合だそうです。

この時にスライドで表示された画面がどっちを表しているのかは不明です。

Lambert ShadingってPBRの前に使用されていたDiffuse Lightingを計算する方法でしたっけ。それともPBRの中で使用されているDiffuse Lightingを計算する方法でしたっけ。

覚えていません。

Detail heightmapsです。

f:id:kazuhironagai77:20210815234507p:plain

Displacement Mapを使用し、Landscapeをスムーズにしたそうです。

Displacement MapはLandscapeを本物っぽくするのに非常に重要です。はい。

<砂のRenderingについての各論>

ここからは各論的にそれぞれのイメージについて細かく解説しています。

MIPSについてです。

f:id:kazuhironagai77:20210815234528p:plain

f:id:kazuhironagai77:20210815234535p:plain

正直、同じに見えます。

100 pxを1mとすると

f:id:kazuhironagai77:20210815234549p:plain

1pxの中に400個の砂粒が入っている計算になるそうです。

このリアルさを出すためにノイズを使用しているそうです。

f:id:kazuhironagai77:20210815234604p:plain

このノイズは砂のNormal mapのばらつき具合のランダムさを表現しています。

今度は砂のキラキラについてです。

f:id:kazuhironagai77:20210815234619p:plain

f:id:kazuhironagai77:20210815234625p:plain

f:id:kazuhironagai77:20210815234632p:plain

Glitterが在る場合とない場合ですね。ある場合の方が砂らしさが出ています。

このキラキラですが、太陽とカメラと砂のアングルでたまたま光る状態の砂が光っています。つまりカメラが移動すると光る砂は変わります。

そのために以下の式(N・Vの方)を使用したそうです。

f:id:kazuhironagai77:20210815234702p:plain

しかしその状態でAnisotropic maskingを使用すると以下の様にギラギラした箇所が誕生してしまいます。

f:id:kazuhironagai77:20210815234717p:plain

Anisotropic maskingを使用するとオカシクなる部分を区別出来るようにしました。

f:id:kazuhironagai77:20210815234734p:plain

黒い部分がそれに当たります。この部分にはAnisotropic maskingを使用しない事にする事でギラギラした箇所が発生しないようにしました。

すると砂のキラキラ感がなくなってしまいました。予想以上にカメラに映った背景には黒い部分が占めていたからです。

その対策としてSpecular lightを追加する事にしました。

f:id:kazuhironagai77:20210815234751p:plain

はい。ビニール感が出て来ました。

この変な反射光が生まれる理由は、砂の持つ流動性を考えていないからじゃないのかと、流体に対する反射を作ったそうです。

そうすると以下の様になったそうです。

f:id:kazuhironagai77:20210815234814p:plain

これでも、まだビニール感がありますね。

次はLambert Diffuseを改良した話です。

f:id:kazuhironagai77:20210815234828p:plain

f:id:kazuhironagai77:20210815234834p:plain

Lambert の計算では、Diffuse lightingが正確でないため、あらゆるものが本物らしくなくなってしまったそうです。

f:id:kazuhironagai77:20210815234853p:plain

ここでOren-Nayar Modelの計算方法を採用しようとしたら計算コストが高すぎてゲームが動かなくなってしまったそうです。

そこで解決策として以下の式に適当な数値をぶちこんで本物っぽく見える値を採用したそうです。

f:id:kazuhironagai77:20210815234910p:plain

最後にheight mapについてです。

f:id:kazuhironagai77:20210815234924p:plain

ここでHeight mapに使用されるTextureはUE4のLandscapeに使用されるTextureと同じでしょう。

特に注目すべき内容はなかったです。

以上でした。

<感想>

これは砂のVFXというより砂のLandscapeのRenderingについてでした。そういう意味では途中で止めても良かったんですが、

  1. 砂がキラキラしてるのが砂感を出している。
  2. しかし砂粒は小さすぎて計算出来ないのでNormal Mapでキラキラ感を出す方法を編み出した。
  3. しかしそれをそのまま使用した場合、Anisotropic maskingによって砂がギラギラに光って滅茶苦茶になってしまった。
  4. Anisotropic maskingを使用するとオカシクなる部分を抜き出し、その部分にはAnisotropic maskingを使用しないようにした。
  5. そうするとキラキラ感が全くない部分が多すぎるようになってしまったので、Specular lightingを追加した。
  6. Specular lightingをそのまま使用すると、ビニールみたいな光沢になるので流体に対する反射を考慮してSpecular lightingを計算し直した。

の流れがとても面白かったのでそのまま勉強しました。

この部分自体はUE4の砂のVFXを作成するのには役には立ちませんが、砂らしさは砂のキラキラから来ていると気が付いてからのそれを実装するまでの大変さは、これから自分でUE4VFXを作成する時の参考に絶対なると思いました。

先週のBlogで以下の様に述べましたが、

f:id:kazuhironagai77:20210815234952p:plain

砂のキラキラ感も正にここでいう脇役です。

脇役を一人追加するのがこんな大変だったとは驚きです。それを学べただけでもこれを勉強した甲斐はありました。

VFXを自分で作成する時に、炎におけるEmber、雪における色や形状が微妙に違う雪質の存在、そして砂におけるキラキラ感、のような存在に新たに自分で気が付いても、それを破綻なく実装するのは並大抵の工夫では無理なんだと分かりましたね。

3.3 Making Dynamic Desert Sand in Unreal Engine 4 [5] を見て

時間がないので簡単な感想だけ書きます。

こっちもEffectではなくLandscapeのRenderingが主な話でした。

日本のアニメじゃ砂で攻撃する強キャラは必ず一作品に一人はいますが、アメリカではあんまり無いみたいですね。

砂のVFXは自作するしかないのかもしれませんね。

来週はNiagaraでも探して見ます。

3.4 Boundについての復習

Intro to Cascade: Creating a GPU Sprite Emitter | 05 | v4.2 Tutorial Series | Unreal Engine [6]の5分10秒の当りから詳しいBoundについての解説がありました。

まず最初に訂正です。Boundsの正式名称はfixed bounds boxでした。

GPUで作成したEffectが以下に表示されています。

f:id:kazuhironagai77:20210815235025p:plain

これがカメラを少しずらすと

f:id:kazuhironagai77:20210815235039p:plain

何と、Effectが消えてしまいます。

これはGPUはCameraのView Frustumから外れるとRenderingしなくなるように設定されているからだそうです。

しかしCameraのView Frustumから外れてもGPUで生成したSpriteの端はまだCameraに写っているので、GPUにはRenderingを続けて欲しいです。

Bounds のSet Fixed Bounds を選択するとfixed bounds boxを生成します。

f:id:kazuhironagai77:20210815235055p:plain

Boundsが選択された状態だと、生成したfixed bounds boxを可視化する事が出来ます。

f:id:kazuhironagai77:20210815235110p:plain

新しいfixed bounds boxを生成したらReStart Levelをクリックして下さい。

f:id:kazuhironagai77:20210815235127p:plain

これで新しく生成されたfixed bounds boxがEffectに追加されます。

今度はGPUで生成されたEffectは消えません。

f:id:kazuhironagai77:20210815235141p:plain

新しく生成されたfixed bounds boxがCameraのView Frustum内に入っている限り、GPUはRenderingを続けます。

はい。

これが、fixed bounds boxの効果だったんです。

4. 駅の実装のテスト(バグ出し)

先週作成した駅のテストを行い、バグを洗い出します。

そのためにLandscape1にGalaxy Train Stationを配置して今まで配置していたWarp Gateを消します。

f:id:kazuhironagai77:20210815235212p:plain

テストします。

f:id:kazuhironagai77:20210815235228p:plain

駅の名前もあっていますし行き先もあっています。

銀河鉄道に乗ります。

f:id:kazuhironagai77:20210815235243p:plain

Map1につきました。

今度は、Map1から銀河鉄道に乗ります。

f:id:kazuhironagai77:20210815235300p:plain

Landscape1に着きました。

f:id:kazuhironagai77:20210815235317p:plain

今度は「止めます」ボタンを押します。

f:id:kazuhironagai77:20210815235342p:plain

駅員との会話が終わってしまいました。

f:id:kazuhironagai77:20210815235406p:plain

ここには戻るボタンが欲しいですね。

作成します。

f:id:kazuhironagai77:20210815235449p:plain

前画面に戻りますボタンに実装を追加します。

f:id:kazuhironagai77:20210815235503p:plain

テストします。

「前画面に戻ります」ボタンをクリックします。

f:id:kazuhironagai77:20210815235517p:plain

前画面に戻りました。

f:id:kazuhironagai77:20210815235532p:plain

色々試してみます。

当然ですが、「駅員と会話をする。」「切符の交換」の機能はまだ作成していません。

切符を買うために所持金を100から2000に変更します。

f:id:kazuhironagai77:20210815235547p:plain

ゲームを起動します。

f:id:kazuhironagai77:20210815235601p:plain

金貨2000の2000がはみ出しそうです。

f:id:kazuhironagai77:20210815235615p:plain

直します。

f:id:kazuhironagai77:20210815235630p:plain

Horizontal BoxをBorderでWrapしました。

BorderのBrushのImageに今まで使用していたイメージをセットしました。

f:id:kazuhironagai77:20210815235643p:plain

BorderのSize to Contentをチェックしました。

f:id:kazuhironagai77:20210815235659p:plain

これで後ろのImageからはみ出す事は無いはずです。

テストします。

f:id:kazuhironagai77:20210815235713p:plain

はみ出してはいませんね。

ただし以下の部分の設定の意味が今一分かっていません。

f:id:kazuhironagai77:20210815235731p:plain

この部分は表示するテキストの位置だけを指定しているのか、それともテキストにサイズにも影響を与えるのか、その辺が良く分からないです。

ものは試しなので今度は100000で試してみます。

f:id:kazuhironagai77:20210815235757p:plain

以下の様になりました。

f:id:kazuhironagai77:20210815235812p:plain

金貨の数字の部分がはみ出す事は無いですね。

最初の目的である切符を購入してみます。

f:id:kazuhironagai77:20210815235827p:plain

切符の値段が表示される箇所に、所持金が表示されています。直します。

f:id:kazuhironagai77:20210815235927p:plain

直しました。

今度は切符の値段が表示されています。

f:id:kazuhironagai77:20210815235942p:plain

切符を買ってみます。普通の切符、赤い切符、そして青い切符を買いました。

f:id:kazuhironagai77:20210816000016p:plain

駅から出て、道具袋を開くと普通の切符、赤い切符、そして青い切符を所持している事が分かります。

f:id:kazuhironagai77:20210816000040p:plain

道具袋の左側に表示されるPlayerの操作するキャラのStatusは分かりにくいですね。

日本語で表示するようにします。

後、この道具袋を開いた状態で、左側の切符をクリックすると切符を使用した事になります。

現状、切符には道具としての効果は何もないので切符が消えるだけです。道具としての切符の効果については後で考えます。

色々弄って見ましたが、大きなバグはこれ以外は見つかりませんでした。今回のバグ出しはここまでとします。

5. 駅員との会話の実装

会話用のWidgetのデザインは先週作成した、Start 画面における赤い帽子の魔女との会話用のWidgetと同じにします。

f:id:kazuhironagai77:20210816001006p:plain

駅員の帽子が大きすぎて完全に同じにはなりませんでしたが大体同じデザインになりました。

f:id:kazuhironagai77:20210816001030p:plain

G_Train Station Widgetから先程作成したWidgetを開けるようにします。

f:id:kazuhironagai77:20210816001046p:plain

しました。

f:id:kazuhironagai77:20210816001108p:plain

ついでに戻るボタンも実装します。

f:id:kazuhironagai77:20210816001143p:plain

f:id:kazuhironagai77:20210816001150p:plain

テストします。

「駅員と話しをする」ボタンを押します。

f:id:kazuhironagai77:20210816001206p:plain

先程作成したWidgetが開きました。

f:id:kazuhironagai77:20210816001225p:plain

戻るボタンを押しました。

f:id:kazuhironagai77:20210816001240p:plain

前の画面に戻りました。

それでは会話部分の作成を行います。

会話部分を作成します。

f:id:kazuhironagai77:20210816001258p:plain

NPCと同じ方法で作成しました。

このセリフ部分を表示するための機能を実装します。

NPCとの会話やスタート画面での魔女との会話の実装とほぼ同じやり方です。

f:id:kazuhironagai77:20210816001319p:plain

f:id:kazuhironagai77:20210816001327p:plain

f:id:kazuhironagai77:20210816001334p:plain

テストします。

f:id:kazuhironagai77:20210816001350p:plain

字が小さいですね。

もっと長い文章を表示してみます。

f:id:kazuhironagai77:20210816001412p:plain

文字は白抜きした方が良い気がしますね。後、BorderのPaddingも変更しました。

f:id:kazuhironagai77:20210816001427p:plain

f:id:kazuhironagai77:20210816001433p:plain

白抜きすると変に目立つので背景の紙と同じ色にしました。

結果です。

f:id:kazuhironagai77:20210816001449p:plain

まあ、いい感じです。

以下の様になりました。

f:id:kazuhironagai77:20210816001523p:plain

今度は回答用のボタンを作成していきます。

f:id:kazuhironagai77:20210816001538p:plain

先週、作成したAnswer Button Witch Widgetの丸コピーで作成します。

f:id:kazuhironagai77:20210816001554p:plain

変更した部分はParent Widgetのタイプを今回の親WidgetであるW talk with Staff Widgetにした所だけです。

f:id:kazuhironagai77:20210816001608p:plain

全部のNPCの会話Widgetの原型が判明したらNPC_ParentにVertical BoxとかCustom Eventとかを組み込んで、一気にPolymorphism化して回答ボタンも一種類で対応出来るように作れそうですが、そういうのはこのゲームが完成した後で考えます。

今回はこれでやって行きます。

テストします。

f:id:kazuhironagai77:20210816001625p:plain

回答ボタン「この駅について」を押します。

f:id:kazuhironagai77:20210816001640p:plain

望んでいたセリフが返って来ました。

会話の内容はまだ直さないといけませんが、会話の機能は実装出来ました。

6. 切符を使用して銀河鉄道に乗る機能の実装

今までは切符を使用しなくても銀河鉄道に乗れました。切符を使用しないと銀河鉄道に乗れないようにします。

現状はこんな感じです。

f:id:kazuhironagai77:20210816001716p:plain

銀河鉄道に乗ります。」ボタンを押すと以下のコードが実行されます。

f:id:kazuhironagai77:20210816001731p:plain

はい。これに切符をチェックする機能を追加します。

最初にUIから直していきます。

現在所持している切符の枚数が分からないと銀河鉄道に乗るかどうか決心出来ません。切符を表示するVertical Boxを追加します。

こんな感じに変更しました。

f:id:kazuhironagai77:20210816001746p:plain

普通の切符の枚数は以下の方法で数えられるはずです。

f:id:kazuhironagai77:20210816001801p:plain

テストしてみます。

普通の切符を持っていない状態で話して見ました。

f:id:kazuhironagai77:20210816001816p:plain

0枚と表示されています。

今度は普通の切符を2枚買ってみました。

f:id:kazuhironagai77:20210816001833p:plain

2枚と表示されています。

いますが他の部分がオカシイです。

セリフに「銀河鉄道に乗るには普通の切符が一枚必要です。」が抜けています。更に「普通の切符: 2枚」の位置がずれています。

直します。

まずはセリフからです。

セリフはNPC_Parentで管理されていました。

f:id:kazuhironagai77:20210816001848p:plain

うーん。この辺もData Tableで管理するのか統一しないと訳わからなくなりそうです。

直しました。

f:id:kazuhironagai77:20210816001902p:plain

テストします。

f:id:kazuhironagai77:20210816001916p:plain

直りました。

今度は「普通の切符: 2枚」の位置を直します。

普通の切符の枚数を表示するテキストを含むBorderのAlignmentを以下の様に変更します。

f:id:kazuhironagai77:20210816001930p:plain

テストします。

f:id:kazuhironagai77:20210816001946p:plain

はい。直りました。

今度は、銀河鉄道に乗った時に切符の枚数を減らす機能を実装します。

はい。出来ました。

f:id:kazuhironagai77:20210816002008p:plain

試してみます。

道具袋から普通の切符が全部、消えていました。

f:id:kazuhironagai77:20210816002037p:plain

Remove 関数は同じ名前の要素を全部消してしまうみたいですね。

面倒ですが以下のように実装を変更しました。

f:id:kazuhironagai77:20210816002053p:plain

テストします。

以下の様なItemが道具袋に入っています。

f:id:kazuhironagai77:20210816002110p:plain

切符の数は4枚です。

f:id:kazuhironagai77:20210816002125p:plain

移動した後です。

f:id:kazuhironagai77:20210816002140p:plain

普通の切符が一枚減っています。残りのItemの数は変わっていません。

出来ていますね。

7. 切符の交換機能の実装

駅では、切符の切れ端を10枚集めるとふつうの切符と交換してくれます。

その機能を実装します。

切符の交換用のWidgetを作成します。

W_WarpGate widgetを参考にします。

f:id:kazuhironagai77:20210816002210p:plain

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

名前はW_ExchangeTicketとしました。

f:id:kazuhironagai77:20210816002223p:plain

取りあえずゲーム画面で表示してみます。

f:id:kazuhironagai77:20210816002239p:plain

こんな感じです。

やっぱり交換するボタンは下にあった方が良いですね。

f:id:kazuhironagai77:20210816002255p:plain

これの方が見やすいですね。

それでは交換するボタンを押した時の実装をします。

まず本当に切符の切れ端が10枚あるか確認します。

f:id:kazuhironagai77:20210816002309p:plain

無ければボタンを押しても何も起きません。

在る場合は、以下の方法で切符の切れ端を10枚、道具袋から消します。

f:id:kazuhironagai77:20210816002330p:plain

このやり方は最適ではない気がしますが、結果が間違っている訳ではないので今回はこれで行きます。

その後で、切符の切れ端の数から10を引き、

f:id:kazuhironagai77:20210816002404p:plain

道具袋に普通の切符を追加して

f:id:kazuhironagai77:20210816002425p:plain

画面に表示している普通の切符の数にも1を足します。

f:id:kazuhironagai77:20210816002445p:plain

これで完成です。

Textの表示、切符の枚数の表示、そして戻るボタンの表示の実装方法は、今までにやったやり方と全く同じなので記録はスキップしました。

テストします。

切符の切れ端、10枚持っている状態で交換所に行きます。

f:id:kazuhironagai77:20210816002513p:plain

「交換する」を押します。

普通の切符が1枚、切符の切れ端が0枚になりました。

f:id:kazuhironagai77:20210816002533p:plain

道具袋を開いて確認しても普通の切符が一枚になっています。

f:id:kazuhironagai77:20210816002549p:plain

他にも色々テストしてみましたが問題なかったです。

これで完成です。

8. 切符を道具として使用した場合の検討

はい。これはもう決めました。切符は道具としては使用出来ないようにします。

クリックしても何も起きません。

これが一番簡単です。これで行きます。

9. 別なマップに移動してる間に別なアニメーションを表示する方法についての調査

まずはAnimationではなくて単なるLoad 画面を追加する方法から調べます。

Unreal Engineの公式のビデオであるAsync Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [7]でLoad画面の作成に関しての詳しい説明がされています。パッと見た感じですが、UE4C++から作成しないといけないみたいですね。

もう少しTutorialを探したらUnreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [8]ではBPのみで実装する方法が紹介されていました。

どちらも2019年に制作された動画なので、もっと最近の動画なら更に簡単にLoad画面の実装が出来そうと思い更に調べたらHow To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [9]には無料のplug-inを使用して5分でload screenを示す方法が紹介されています。

更にこの動画には動画をLoad画面に挟む方法も説明されているみたいです。

今回はこの三つの動画を勉強する事にします。

9.1 Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [7] を勉強する。

Axel Riffard氏によるUnreal Fest Europe 2019の講演の記録のようです。フランス人で日本で働いているそうです。

え。

日本で働いているの?

ひょっとすると何処かで会ってたりしてるんでしょうか?

この講演はProgrammerの観点からUE4のAsync Loading Screens and Transition Levelsについての解説のようですね。

以下の内容について講演するそうです。

f:id:kazuhironagai77:20210816002645p:plain

Moduleの作り方ですか。

Sherif, William氏のUnreal Engine 4 Scripting with C++ Cookbook [10] でたしかmoduleの作成方法について勉強したはずと思って見返してみたら、8章にCreating a new editor moduleがありました。

ただもう内容については覚えていません。

というかこの本で勉強した時は、本当に暗中模索な状態でどこまで理解したら良いのか、もしくは何処を勉強すべきなのかが全く分かっていませんでした。

今、もう一回勉強したら完全に自分の血肉に出来るんでしょうが、今はあんまりUE4C++を使用するメリットを感じていません。

Unreal Engine 4 Scripting with C++ Cookbook [10]のCreating a new editor module部分だけ読み返してみます。

今、読み返して分かったんですけど

f:id:kazuhironagai77:20210816002702p:plain

の部分で理論を解説していたんですね。うん。この教科書で勉強した時はこの部分の価値を全く理解していなくて読み飛ばしていました。

この講演を聞くための予習としては十分でしょう。

次に行きます。

Threadについてですね。

うん。AsyncなんだからThreadを使用するのは当然なのか。と思ったんですが、私、CSの専門が 3 D Graphicsで大学の授業以外で全くThreadに触った事がないんです。

「Web の画面の読み込みにAsyncを使用して…」みたいなWeb系なら基本的な内容でも良く知らないんです。勿論、やった事もありません。

のでThread自体あんまり理解してません。

「Thread safeなのを使用すればいいんじゃないの。」位しか知らないです。

Threadについての予習はなしです。理解出来る範囲で聞きます。

Seamless Travelについて。

これについては何を言っているのか分かりません。

取りあえず動画を見てから考えます。

Solo player とMulti playersでAsync Loading Screensの作成方法は違うみたいですね。

私にはSolo playerで十分ですのでそこだけ重点的に見る事にします。

最初のスライドはThreadについての基本的な説明ですね。これぐらいなら私でも知っている内容ですね。

はい。次のスライドからちょっと本格的になって来ました。UE4でAsynchronousなTaskをする場合は

f:id:kazuhironagai77:20210816002719p:plain

を使用するらしいです。

公式のDocumentのAsyncTask [11] には

f:id:kazuhironagai77:20210816002732p:plain

と書かれていました。

使い方の簡単な説明はないのかなと思って探したらUnreal WikiAsyncTask () 関数 [11] についての使用方法の簡単な解説がありました。

f:id:kazuhironagai77:20210816002746p:plain

Unreal Wikiの見た目が全く変わっててびっくりしました。

後、Unreal WikiってCatalyst Softworks社が運営しているんですね。ずっとEpic Games社が運営していると思っていました。

この後、色々なサイトやYouTubeのTutorialを見た結論なんですが、UE4ではasync は兎も角、Multi ThreadはBPでは使用出来ないようにしているみたいなんですね。

それはUE4側では、Multi Threadは完全に理解していない人が使用するとゲームがマジでぶっ壊れるって認識を持っているからみたいなんです。

後、「async は兎も角、Multi Threadは…」みたいな言い方をしているサイトが複数あったんですがそれの意味も分からないです。AsyncってThreadを複数使用しているからMulti Threadの一種でしょう。

やっぱりC++のThreadを先にしっかり勉強する必要がありますね。

UE4でThreadを実装するのはそれからにします。

今回はAsyncTask ()関数はさわりをみるだけにします。

ずっと前にDownloadしたAction RPGを見るとLoading Screenの理想的な実装が書かれているとありました。

f:id:kazuhironagai77:20210816002802p:plain

以下に示した様な分かり易いPower Pointで解説されていました。

f:id:kazuhironagai77:20210816002817p:plain

更に以下の図でもう少し詳しい手順が解説されています。

f:id:kazuhironagai77:20210816002830p:plain

ここで重要な点はGame Moduleから直接EngineにCallしない事だそうです。

Game ModuleからはLoading ModuleしかCallしません。残りはLoading Moduleが全て仕切ります。

私なりの理解を書くと、こうする事でDesignerはBPからLoading Moduleを呼ぶだけが仕事になり、残りのすべての作業はThread を理解したProgrammerがLoading Module内の実装を行う事になり、Multi Threadによる事故が起きにくくなる訳です。

うん。納得しました。

もう少し細かく勉強します。

Game ModuleのBlueprint Useです。

f:id:kazuhironagai77:20210816002851p:plain

これはBP内でLoading ModuleのILoadingScreenModuleを呼び出すNodeを使用していると考えられます。

f:id:kazuhironagai77:20210816002906p:plain

正しこのNodeはUE4C++側で実装されているため、上記のPower Pointでは間に

f:id:kazuhironagai77:20210816002919p:plain

が書かれています。これだけがBP側で行う事です。

BPから呼び出された

f:id:kazuhironagai77:20210816002936p:plain

はInterfaceなので実際はそのInterfaceから派生したクラスを呼び出すはずです。それが

f:id:kazuhironagai77:20210816002951p:plain

なのでしょう。

このクラスの実装に必要なクラス(もしくは関数)である

f:id:kazuhironagai77:20210816003007p:plain

が呼ばれます。

今度はこのSLoadingScreenを実装するのに必要なクラス(もしくは関数)である

f:id:kazuhironagai77:20210816003023p:plain

が呼ばれます。

FLoadingScreenBrushからはEngine の

f:id:kazuhironagai77:20210816003035p:plain

が呼ばれ、

SLoadingScreenからは

f:id:kazuhironagai77:20210816003128p:plain

が呼ばれ、そして

FLoadingScreenModuleからは

f:id:kazuhironagai77:20210816003142p:plain

が呼ばれます。

Engineから呼ばれた3つのクラス、FSlateDynamicImageBrush、SCompoundWidget、そしてIModuleInterfaceについて少しだけ調べます。

そしたらこのサイト[12]に日本語に翻訳されたスライドがありました。

f:id:kazuhironagai77:20210816003158p:plain

うーん。

ぱらっと見た感じでは全く同じみたいですね。

もうYouTubeの動画で勉強を始めちゃったのでYouTubeの動画で勉強を進めます。

FSlateDynamicImageBrushについては、公式DocumentのFSlateDynamicImageBrush [13] しか見つかりませんね。

f:id:kazuhironagai77:20210816003213p:plain

SCompoundWidgetは何回が使用した記憶があります。

Sherif, William氏の Unreal Engine 4 Scripting with C++ Cookbook [10]では9章のCreate a custom SWidget/ UWidgetで使用方法が解説されています。

f:id:kazuhironagai77:20210816003231p:plain

今、作成しているRPGでもたしか使用したはず。

と思って確認したら使用していたのはUUserWidgetでした。

f:id:kazuhironagai77:20210816003248p:plain

ちょっと違いました。

IModuleInterfaceはUnreal Engine 4 Scripting with C++ Cookbook [10]でEditor Moduleの作成の時に使用しています。

f:id:kazuhironagai77:20210816003304p:plain

FLoadingScreenModuleの親クラスとして使用するのでしょうか?

今度は使用方法についての説明です。

Blueprint側だそうです。

f:id:kazuhironagai77:20210816003323p:plain

f:id:kazuhironagai77:20210816003329p:plain

BPからやるのかこれだけだそうですが、ちょっと分からない部分がありますね。

まずFade in and Show Loading Screenを呼び出し、Fade in and Show Loading ScreenからPlay Loading Screenを呼び出しています。いきなりPlay Loading Screenを呼び出しちゃいけないんでしょうか?

それともFade in and Show Loading Screenを呼び出す所が前のSlideの

f:id:kazuhironagai77:20210816003344p:plain

に当たり、Play Loading Screenを呼び出す所が

f:id:kazuhironagai77:20210816003357p:plain

を表しているんでしょうか?

(ここは解説で、Play Loading ScreenはBP callable functionでUE4C++側で作成すると言っているので予測の通りでした。)

後、Load Game Level ノードと言う多分始めて見るノードを使用しています。

f:id:kazuhironagai77:20210816003413p:plain

よくよく考えたら以下に示したノードの左端のマークの意味が分かりません。

f:id:kazuhironagai77:20210816003428p:plain

f:id:kazuhironagai77:20210816003441p:plain

これの意味が分かったらもう少し正しい推測が出来るんですが…

後、このBPの実装は全てGame Instance BP内に書かれています。Levelの移動をするんだから当たり前ですが、何か不思議です。

Open LevelのLevel NameにはAbsolute Pathを必ず使用するようにと説明されていました。そうしないと指定されたLevelを全てのLevelから探して時間が余計にかかるそうです。これは勉強になりました。

ここからProgrammer専門の話になるそうです。

最初のSlideはModuleについてです。

Loading Screenとは直接関係ないのでスキップします。

次のSlideはAction RPGのFolderです。

f:id:kazuhironagai77:20210816003457p:plain

f:id:kazuhironagai77:20210816003505p:plain

これってMarket PlaceからDownload出来る無料のAction RPGと同じなんでしょうか?

確認します。

同じみたいです。

f:id:kazuhironagai77:20210816003528p:plain

f:id:kazuhironagai77:20210816003535p:plain

次のSlideです。

今度はModuleのLoadの順番についての解説です。

Loading ModuleはGame Moduleより先にInitializeしないといけません。その方法について解説してます。

.uprojectのLoadingPhaseで指定します。

f:id:kazuhironagai77:20210816003551p:plain

次はInterfaceについてです。

このSlideで紹介されているInterfaceも先程のAction RPGのActionRPGLoadingScreen内にあるものと全く同じでした。

f:id:kazuhironagai77:20210816003607p:plain

f:id:kazuhironagai77:20210816003613p:plain

成程、IModuleInterfaceを継承していますね。

f:id:kazuhironagai77:20210816003628p:plain

Interfaceなので当然Virtualです。

f:id:kazuhironagai77:20210816003641p:plain

このGet関数はVirtualじゃないですね。Interfaceでもこんな書き方もあるんですね。

一見単純なGet()関数に見えますが、Staticで返したり、Inlineを使用している所など、ちょっと私の今のC++の知識では100%の理解は出来ないですね。

Inlineは高速化のためなんでしょうか?

たった一行の関数ですが、結構考えさせられます。

当分、UE4C++の勉強はやるつもりはないので今回はコードの内容については深入りはしません。

次のSlideはInterfaceの実装についてです。

いや、Interfaceは実装は出来ないでしょう。Interfaceから派生したクラスの実装は出来ますが。と思ってActionRPGLoadingScreen.cppを見たら納得しました。

f:id:kazuhironagai77:20210816003720p:plain

FActionRPGLoadingScreenModuleクラスが先程作成したInterfaceであるIActionRPLoadingScreenModuleを継承しています。このクラスの宣言と実装をActionRPGLoadingScreen.cppで一辺に行っていました。

ここで時間が尽きてしまいました。

今週はここまでです。

9.2 Unreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [8] を勉強する。

来週やります。

9.3 How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [9] を勉強する。

これも来週やります。

10. Good Skyの復習

これもやるやる言ってずっとやっていません。来週こそやりたいです。

11. まとめと感想

今週は色々なTutorialの勉強に時間を取られ過ぎました。勉強するのは楽しいですが、RPGを完成させるのが目的なので本質を見失わないようにしないとどんどん脇道に逸れてしまいます。

その辺の見定めが必要ですね。

来週からはもっとゲームを完成させる事に労力を注ぎます。

12. 参照(Reference

[1] CGHOW. (2020, July 21). Nebula Effect | UE4 Niagara Nebula | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=niSWXhWNyQQ&list=PLwMiBtF6WzsqC7_cJmD26ts0YDbtPCCfe&index=9

[2] gameDev Outpost. (2021, April 4). UE4 - Niagara Adjusting Size [Video]. YouTube. https://www.youtube.com/watch?v=erIc7rcsmps

[3] Unsplash. (n.d.). 100+ Nebula Pictures [HQ] | Download Free Images on. Retrieved August 15, 2021, from https://unsplash.com/s/photos/nebula

[4] Edwards, J. [GDC]. (2018, February 25). Sand Rendering in Journey [Video]. YouTube. https://www.youtube.com/watch?v=wt2yYnBRD3U

[5] dotplusplusplus. (2021, April 21). Making Dynamic Desert Sand in Unreal Engine 4 [Video]. YouTube. https://www.youtube.com/watch?v=o-MXAmfCY5U

[6] Epic Games [Unreal Engine]. (2014, July 8). Intro to Cascade: Creating a GPU Sprite Emitter | 05 | v4.2 Tutorial Series | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=DcesEW380lc&t=310s

[7] Epic Games [Unreal Engine]. (2019, May 20). Async Loading Screens and Transition Levels | Unreal Fest Europe 2019 | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=ON1_dEHoNDg

[8] Reids Channel. (2019, December 15). Unreal Engine 4 - Easy Loading Screen Tutorial - Blueprints Only [Video]. YouTube. https://www.youtube.com/watch?v=lzGcVDUDU5g

[9] Uisco. (2021, March 3). How To Make A Loading Screen In 5 Minutes Unreal Engine 4 Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=KpXmcqSITOg

[10] Sherif, William. Unreal Engine 4 Scripting with C++ Cookbook (Kindle Location 4359). Packt Publishing. Kindle Edition.

[11] Catalyst Softworks. (n.d.). AsyncTask Function | Unreal Engine Community Wiki. The Unreal Engine Community Wiki. Retrieved August 15, 2021, from https://unrealcommunity.wiki/asynctask-function-mfdnmfca

[12] エピック・ゲームズ・ジャパン Epic Games Japan. (n.d.). 非同期ロード画面 Asynchronous Loading Screen. 非同期ロード画面 Asynchronous Loading Screen. Retrieved August 13, 2021, from https://www.slideshare.net/EpicGamesJapan/ss-135771323

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する Ticket Systemなどの作成

f:id:kazuhironagai77:20210808231920p:plain

<前文>

最近、YouTubeを見てて知った話に、何でアメリカでバッファローが絶滅寸前になったのかがあります。

その理由はネィティブ・アメリカンの生活のほとんど全てがバッファローに依存している事に気が付いた白人移植者たちが、アメリカ大陸におけるネィティブ・アメリカンの勢力を弱らせるために、バッファローを狩りまくったからだそうです。基から白人移植者たちはバッファローを絶滅させると言う目的があったそうです。

そしてネィティブ・アメリカンの勢力がほぼ殲滅した途端、バッファローの保護に乗り出しました。

しかし今回の話は、別にアメリカ人が偽善的であると言う軽い話ではありません。もっと深い話を書きます。

この話、自分達を白人移植者の立場に置き換えて考えると、アレっと思いませんか?

もし日本人が同じ事を過去にしたら、徹底的に秘密にしてそんな事実は存在しないように歴史を改ざんするでしょう。公的な資料を燃やして、証拠を隠滅したり、そういう研究をする学者に予算を配らないように嫌がらせしたりするはずです。

何故、アメリカ人はそれをしないのでしょうか?

私はずっと、アメリカにも色々な政治、宗教団体がそれぞれ複雑な利害関係があって一見、アメリカ人を叩いているような話でも、実はアメリカ全体としては利益が出るような仕組みが存在していると思っていました。それも正しい事は正しいですが、それよりももっと直接的な理由があったんです。

そして、そこには、アメリカ人を含めたユダヤキリスト教文明圏における独特の宗教観が関係していたんです。

その話を今回はここでします。

皆さん、戒律って知っていますか?

ある宗教を信仰する人達が守らなければならない決まりの事です。例えばユダヤ教イスラム教の人が豚を食べない、とかキリスト教の人が日曜日に教会に必ず行く。とかです。

この戒律って凄く重いんです。日本人が考える道徳と戒律は全く違います。道徳は守ったら素晴らしいですが守らなくても問題ないです。しかし戒律は違います。戒律を守らないとその宗教を信仰する人達から人として扱ってもらえません。

日本で言う村の掟みたいなもんです。

では、その戒律ってどうやって生まれるのか知っていますか?

これが日本の文化には全くない発想なんです。

それは罪と罰から生まれるんです。

ユダヤ教に始まる一神教は激烈な砂漠気候である中東で始まった事に関係してか、その思想も日本人から見るとかなり過激です。その過激な思想に基づいた厳格な罪の判断とその罪に対する非情な罰がセットになっています。

良く、日本だと、被害者が加害者の厳罰を望まないと言うと裁判で罪が軽くなったりしますが、アメリカでは、少なくとも私がいた州ではそんな事は全くなかったです。

それは何故かと言うと、罪を許せるのは罪を犯した事がない人が代わりにその罰を受けた場合だけで、被害者には加害者の罪を軽くする権利なんか元からないからです。

つまり、罪を犯したら必ず罰を受けるんです。

この辺の感覚がまず日本人には分かりません。ホントにポカーンです。罪を犯したのに、罰ッせられてないヤツなんて星の数ほどいるし、その逆に無実の罪で罰せられているヤツだって沢山いるでしょう。と。

残念ながらそんな風に考えるアメリカ人は全くいません。だからアメリカ人は滅茶苦茶主張するんです。無実だと。そしてもし無実の罪で罰せられたことが判明したら、その保証も物凄い金額になります。

では、本当に罪を犯してしまった時はどうするんでしょうか?

罪を犯してしまった場合、100%罰せられます。しかも激烈な罰をです。しかし、この罰を受けないで済む方法があるんです。

罪を犯してしまったが、その行為を心の底から反省した場合は、罰の執行が延期されます。

ここで戒律が誕生するんです。

その犯した罪に応じて、その行為を心の底から反省した場合においてのみ適切な戒律を定められます。その罪人はその戒律を守っている限りにおいて罰の執行が延期されるんです。

これが、ユダヤキリスト教文明圏における戒律なんです。

最初のバッファローの話に戻ります。

何で、アメリカ人が自分達の先祖が犯した罪をそんなに公の場で激烈に主張するのかと言うと、別にアメリカ人がマゾでもアホだからでもなく、そうする事で、彼らが信じる宗教観から、自分達の犯した罪に対する罰の執行を延期出来ると感じるからなんです。

ある民族を殲滅してその土地を奪った。そしたらその奪った民族も神の罰によって殲滅させられます。しかし今のアメリカ人はその罪を認めて、心の底から反省しているし、そういう歴史をきちんと記録に残している。だからアメリカに移民した白人はその罪に対する罰の執行は免れる事が出来るはず。と考えているです。

だからアメリカでは、先住民を殲滅するためのバッファローを狩りまくった話をしても、誰も政治問題化しないんです。

日本人は、この感覚を理解しないと「アメリカの言論の自由は本物だ。何でも言って良いんだ!」と浅くかつ間違って理解して、アメリカ文化のタブーが日本以上にあるのに、そのタブーに軽率に触れて、アメリカ社会における自分の社会的な立場を一瞬で失ってしまったりします。

これからはこういう深い話を前文で書く事にします。

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

<本文>

1.今週の予定

今週は以下の事を行います

  1. Particle Systemの勉強
  2. RPGの作成
    • スタート画面の続きで、魔女との会話を実装
    • 切符の実装方法
    • 駅における切符の購入の実装
    • 駅における移動の実装方法の検証
    • 実際に別なマップに移動してる間に別なアニメーションを表示する方法についての調査
    • Good Skyの復習

それでは始めます。

2.Niagaraの勉強

2.1 Unreal Engine Niagara Cloud Tutorial | Download Project Files [1] の勉強

先週、勉強したCGHOW氏のUnreal Engine Niagara Cloud Tutorial | Download Project Files [1]の残り半分をやります。

Materialとして使用しているM_CouldでOpacityの計算にDepth Fadeを追加します。

f:id:kazuhironagai77:20210808232038p:plain

Depth Fadeの機能は以下に示した2021-07-18のブログで勉強しました。

f:id:kazuhironagai77:20210808232053p:plain

しかし実際にDepth Fadeを付けなくても公式のDocumentのDepth Expression [2] の説明にあるような醜い線は見られません。

以下に示したのがDepth Expression有のMaterialを使用した場合です。

f:id:kazuhironagai77:20210808232109p:plain

こちらはDepth Expression無しのMaterialを使用した場合です。

f:id:kazuhironagai77:20210808232123p:plain

あんまり変わりませんよね。

公式のDocumentのDepth Expression [2] の説明には

f:id:kazuhironagai77:20210808232137p:plain

とありますが、この場合煙は、透明な物体に当たるのか不透明な物体に当たるのかが良く分かりません。

ひょっとすると透明な物体(ガラスのようなモノ)とこの煙が重なった時に、Depth Expression有無の違いが見られるのかもしれません。

ガラスの球体を設置してみました。

Depth Expression無しのMaterialを使用した場合です。

f:id:kazuhironagai77:20210808232200p:plain

Depth Expression有のMaterialを使用した場合です。

f:id:kazuhironagai77:20210808232215p:plain

あれ。ガラス越しの物質が見えやすい?

いやいや。これは単にScreenshotを取った時の角度の問題でしょう。でも心配なので一応角度を固定して確認してみます。

以下の様にガラス玉を配置しました。

f:id:kazuhironagai77:20210808232229p:plain

Depth Expression有のMaterialを使用した場合です。

f:id:kazuhironagai77:20210808232243p:plain

Depth Expression無しのMaterialを使用した場合です。

f:id:kazuhironagai77:20210808232257p:plain

うーん。どうなんでしょう。煙の濃さも影響しますので一概には言えないかもしれませんが、特別、ガラス越しの物質が見え易くは無いみたいです。

それでは本題のガラスと煙の境目はどうでしょうか?

Depth Expression有のMaterialでガラス球の部分を拡大した場合です。

f:id:kazuhironagai77:20210808232311p:plain

Depth Expression無しのMaterialでガラス球の部分を拡大した場合です。

f:id:kazuhironagai77:20210808232325p:plain

煙の濃さが同じではないので、一概には言えませんが、Depth Expression有のMaterialの方がガラス球の境界線が綺麗に出ているような気はします。

この後、tutorialではParticleのサイズやSpawn Rateなどの値を調整しますが、重要な個所ではないのでスキップします。

今度はこの雲にLightsを追加します。

まず、ES_Smokeをコピーして新しいNiagara Emitter を作成します。名前はES_Lightとしました。

f:id:kazuhironagai77:20210808232357p:plain

まずSprite RendererにセットされているMaterialをM_radial _Rampに変更します。

f:id:kazuhironagai77:20210808232414p:plain

Sub UVの値も元に戻します。

f:id:kazuhironagai77:20210808232429p:plain

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

f:id:kazuhironagai77:20210808232446p:plain

そしてSet Sub Image Index Moduleを外すと

f:id:kazuhironagai77:20210808232501p:plain

以下の様になりました。

f:id:kazuhironagai77:20210808232514p:plain

SizeやSpawn Rateなどを微調整しました。

f:id:kazuhironagai77:20210808232527p:plain

Niagara Systemに追加します。

f:id:kazuhironagai77:20210808232551p:plain

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

次にTutorialでは以下に示したNiagara Light Renderer PropertiesをLight EmitterのRenderに追加しています。

f:id:kazuhironagai77:20210808232629p:plain

その結果、2つのEmitterを使用しているCloud_Sysでは、以下の様に発光するようになりました。

f:id:kazuhironagai77:20210808232644p:plain

この機能は、今のVersionにおけるLight Rendererと同じです。Light RendererをES_Lightに追加します。

f:id:kazuhironagai77:20210808232659p:plain

その結果です。

f:id:kazuhironagai77:20210808232717p:plain

あれ?

光っていない。

Lighting Rendererの使用方法を間違えている?ちょっとLighting Rendererの復習をしますか?

2.2 Lighting Rendererの復習をする。

Lighting Rendererは公式のDocumentのCreate a Particle Light [3]で勉強しました。2021-05-24のブログに勉強した記録があります。

以下にその時に作成したNSのScreenshotを示します。

f:id:kazuhironagai77:20210808232746p:plain

床が赤く光っています。これがLighting Rendererの効果です。

ひょっとするとNS_SmokeのLighting Rendererも効果は出ているんですが良く見えていないだけかもしれません。

ES_LightのLighting Rendererの設定を以下の様に赤く光る様に変えてテストしてみます。

f:id:kazuhironagai77:20210808232800p:plain

更に光の無いLevelを新たに作成してそこでテストしました。

f:id:kazuhironagai77:20210808232816p:plain

床が赤くなっています。

と言う事はLighting Rendererは効いてはいるみたいです。

しかしTutorialでは以下に示した様に、雲自体が凄く光っています。

f:id:kazuhironagai77:20210808232835p:plain

色々試して、分かったんですがES_LightのLight Rendererで作成された光は煙に写らないんです。

f:id:kazuhironagai77:20210808232850p:plain

所が、Tutorialの雲にはLighting Emitter内でLight Rendererで作成された光は写っています。

うーん。

私がどこかでケアレスミス的な設定のミスをES_Smoke側でしていて雲に光が写らない可能性もありますが、Niagaraの仕様が変わっている可能性もあります。

ここはLighting Rendererが生成する光が雲に反射しない(もしくは雲が透過光の影響を表示しない)以上、撤退を考える必要があるかもしれませんね。

2.3 Unreal Engine Niagara Cloud Tutorial | Download Project Files [1] の勉強の続き

残念な結果に終わってしまいましたが、光が雲に対して反射しないならこれ以上進めても意味がないです。一応、tutorialは最後まで見る事にします。

最後まで見ましたが、この雲に対して光の反射が写るように出来れば同じEffectは作成出来そうです。

f:id:kazuhironagai77:20210808232912p:plain

2.4 SmokeにLighting Rendererの効果を写すには?

イキナリですが、これからのNiagaraの勉強で課題が生まれてしまいました。「SmokeにLighting Rendererの効果を写す方法を解明する」です。今は、まだどうやればこれが出来るのか不明ですが、いつかこの問題は解決したいです。

と思ったらUnreal Engine Niagara Cloud Tutorial | Download Project Files [1]のコメント欄で以下の様に書かれていました。

f:id:kazuhironagai77:20210808232948p:plain

これ見ればいいじゃんと思ったら

f:id:kazuhironagai77:20210808233003p:plain

有料でした。

流石にこの謎を解くためだけに10ドルは払えません。

UEのVFXの専門家になる訳ではないので、今回はFreeで勉強出来る範囲でCGHOW氏の動画で勉強させてもらう事にします。というか、こういう勉強ってお金払って答え教えてもらっても、本質は身に付かなかったりするのなので、回り道かもしれませんが自分で解答を探す事にします。

2.5 次のTutorialはどれをやるべきか?

CGHOW氏の動画を色々見たら、2020年以降に作成されたTutorialは今と同じNiagaraになっているみたいでした。2020年以降に作成されたTutorialで簡単そうなのを次は勉強します。

ちょっとだけ見たのですが、Nebula Effect | UE4 Niagara Nebula [4] は2020年以降に作成されている上に時間も短くて、今の私でも出来そうです。来週はこれを勉強する事にします。

今週は、Niagaraの勉強はここまでとします。

3.Cascade:炎以外のEffectの実装

今回、雪のParticle systemを勉強する事にしました。

Dean Ashford氏のUE4 - Tutorial - Snow Particle System [5] を勉強する事にします。

3.1 先週、まとめ忘れていた事

先週、Unreal 4 Particles Tutorial - Simple Flame, Embers, Smoke. [6]を勉強して気が付いたんですが、本物そっくりの炎の作成にEmberやSmokeの存在が如何に大切かでした。

Designについては全く勉強した事ないので、Designerにとっては常識なのかもしれませんが、脇役の存在の大切さを知りました。

今まで、実際に使用されているParticle Systemを見ると、Effectが4つも5つもあるので、複雑過ぎて理解出来ませんでしたが、要するに主役と脇役を合わせて一つのParticle Systemに乗せていたわけです。

これから炎や雷などの実際にゲームで使用される形のEffectを勉強する訳ですが、この主役と脇役のEffectそれぞれについても注目して勉強しようと思います。

3.2 UE4 - Tutorial - Snow Particle System [5] の勉強

<Materialの作成>

まずはMaterialから作成します。Snow_Mとします。

f:id:kazuhironagai77:20210808233049p:plain

Blend ModeをTranslucentにしてParticle SystemからのInput が受け取れるようにParticle Colorを使用します。

f:id:kazuhironagai77:20210808233106p:plain

ここまでは一般的なParticle system用のMaterialの作成と同じなのでスキップしても良かったですが、Multiply ノードを作成する時にほとんどのTutorialでMを押して作成するんです。

その方法が分かりました。Mを押したまま、Mouseの左クリックをするとMultiply ノードが表示されます。

Multiply ノードのB側にはRadial Gradient Exponentialノードを繋げます。

このRadial Gradient Exponentialノードについてはあまり良く知りませんので、ちょっとここで調べる事にします。

<Radial Gradient Exponentialノードについて>

まずRadial Gradient Exponentialノードですが、検索するとGradientとMiscの2つに存在しています。

f:id:kazuhironagai77:20210808233125p:plain

ただしそれぞれからRadial Gradient Exponentialを作成してみると

f:id:kazuhironagai77:20210808233140p:plain

こんな感じで全く同じNodeの様です。

名前からですが、以下の様な円形のGradationを作成するためのNodeと推測されます。

f:id:kazuhironagai77:20210808233153p:plain

ただ使い方が分かりません。

いいTutorialを見つけました。Mathew Wadstein氏のWTF Is? Material: Radial Gradient Exponential in Unreal Engine 4 ( UE4 ) [7]です。これみて使い方を勉強しましょう。

f:id:kazuhironagai77:20210808233221p:plain

あれ、Radialの発音がRadioに聞こえます。ちょっと寄り道しますが、発音のチェックをします。

Radialの発音記号はˈreɪdiəl、Radio の発音記号はˈreɪdiˌoʊです。

əlの音はダークLに変化しているのでしょうか?

Lの発音の仕方で「舌を噛んで、アイウエオと言ってオと言った時の音がそう。」と言う話を聞いた事があったんですが、Radialのəlの音はオーにしか聞こえません。

一方でRadioの最後の音はoʊですね。2重母音のoʊです。日本語で書けば、オウが近いでしょうか。ただ最後の音はW に聞こえますね。英語に2つあるウの音のもう一方のであるuはアメリカ英語ではWが最後に混じるとは聞いていましたが、ʊもこうやってしっかり聞くとWが混じっていますね。もしくはoʊがouに変化しているのかもしれません。

Googleの発音記号を見るとRadialの発音は

f:id:kazuhironagai77:20210808233236p:plain

Radio の発音は

f:id:kazuhironagai77:20210808233250p:plain

となっています。この発音記号、IPAとの関連が良く分からないのですが、Googleで発音を検索すると必ず一番最初に表示されるので、参考にする事にします。UhlのUhですがアメリカ人は良くShort Uの音を表す時にUhと書きます。つまりʌの音です。アメリカ英語ではʌとəはストレスの有り無しの違いなのでIPA表記であるəと同じ音を表しているから結局IPAと同じ事を言っているみたいです。こっちの発音を何回も聞くとウールって言ってるように聞こえてきます。こっちの発音ではLの音がしっかり聞こえます。

もう一回、Mathew Wadstein氏のRadialの発音を聞くと確かに最後にLの音が聞こえます。Radioの場合は発音の最後にWの音が聞こえるのでそれで区別出来ますね。

はい。寄り道はお終いです。

Radial Gradient Exponentialの勉強に戻ります。

WTF Is? Material: Radial Gradient Exponential in Unreal Engine 4 ( UE4 ) [7]をみたら使い方、完全に分かりました。

気を付けないといけない点は

  • UVsの値を1以上にしてもtile状にはならない。
  • Invert DensityにするとDensityの値は白さが基準から黒さが基準に変わる

位でしょうか。

UE4 - Tutorial - Snow Particle System [5]では結局、以下の様に実装しました。

f:id:kazuhironagai77:20210808233313p:plain

<Materialの作成の続き>

Opacityを以下の方法で指定します。

f:id:kazuhironagai77:20210808233332p:plain

Particle Colorのαが1ならば、以下の〇の白い部分がそのまま表示されて、黒い部分は透明になります。

f:id:kazuhironagai77:20210808233356p:plain

Particle Colorのαが0ならば全部透明になります。

<Particle Systemの作成>

Snow_Pと名付けます。

f:id:kazuhironagai77:20210808233414p:plain

Required ModuleのMaterialに先程作成したSnow_Mをセットします。

f:id:kazuhironagai77:20210808233428p:plain

次にType Dataの設定をGPU Spriteに変更します。

f:id:kazuhironagai77:20210808233442p:plain

Spawn Rateを5000にします。

f:id:kazuhironagai77:20210808233455p:plain

Life Timeの値を以下の様にします。

f:id:kazuhironagai77:20210808233509p:plain

Particle のサイズも変更します。

f:id:kazuhironagai77:20210808233522p:plain

Initial Velocityも変更します。

f:id:kazuhironagai77:20210808233535p:plain

こんな感じです。

f:id:kazuhironagai77:20210808233548p:plain

コーン状に雪が降るのはおかしいです。それを直すためにInitial Location Moduleを追加します。

Initial Location Moduleの設定は以下の通りです。

f:id:kazuhironagai77:20210808233602p:plain

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

f:id:kazuhironagai77:20210808233636p:plain

この時点でかなり雪です。

Initial Rotation Moduleを追加します。

f:id:kazuhironagai77:20210808233650p:plain

設定は以下の通りです。

f:id:kazuhironagai77:20210808233704p:plain

ここは良く分かりませんね。Max値が1で180°の回転じゃなかったんでしょうか?

公式DocumentであるRotation Modules [8] によるとInitial Rotation ModuleのStart Rotationは

f:id:kazuhironagai77:20210808233719p:plain

となっていました。

つまり、1は180°ではなく360°でした。

にしても10に設定する意味があるんでしょうか?

良く分からないです。

今度はInitial Rotation Rate Moduleを追加します。

f:id:kazuhironagai77:20210808233741p:plain

こっちは常に回転する、つまり回転/Sを決めるModuleなはずです。

値はDefault値のままでした。

今度はCollision Moduleを追加します。

f:id:kazuhironagai77:20210808233757p:plain

Responseの設定をKillにします。

f:id:kazuhironagai77:20210808233809p:plain

これで雪が地面に落ちた時に溶けてなくなる現象が再現出来るはずです。

最後にBoundをセットします。

f:id:kazuhironagai77:20210808233822p:plain

この機能は良く分かりません。後で調べます。

テストします。

f:id:kazuhironagai77:20210808233836p:plain

f:id:kazuhironagai77:20210808233845p:plain

雪には見えませんが、なんか降っている感じはします。この時点ではかなりいい感じです。

Tutorialだとblurred(ぼんやりしている)と表現されています。

これからそれを直すそうです。

<Particle Systemの改善>

MaterialのEmissive ColorにConstant Nodeを追加します。

f:id:kazuhironagai77:20210808233906p:plain

値は1にします。

更にOpacityの計算方法を以下の実装に変更しました。

f:id:kazuhironagai77:20210808233919p:plain

これは何をやっているんでしょうか?

ここはMaterialの分野なので、後で時間があったら検討します。

結果をみます。

f:id:kazuhironagai77:20210808233933p:plain

確かに雪がはっきり見えます。

<Emitterの追加>

Material、Snow_Unlit_MをSnow_MをDuplicateする事で作成します。

f:id:kazuhironagai77:20210808233950p:plain

Shading Modelの設定をUnlitにします。

f:id:kazuhironagai77:20210808234003p:plain

Base Colorにつないでいた線をEmissive Colorにつなぎ直します。

f:id:kazuhironagai77:20210808234100p:plain

Snow_PのParticle EmitterをDuplicateして

f:id:kazuhironagai77:20210808234114p:plain

新しく作成した方のEmitterに先程作成したMaterialであるSnow_Unlit_Mをセットします。

f:id:kazuhironagai77:20210808234127p:plain

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

f:id:kazuhironagai77:20210808234141p:plain

確かに真っ白な雪と灰色の雪が見えます。かなり雪っぽくなって来ました。

今度はSnow Flakeのイラストを使用します。

ないので自分で作りました。

f:id:kazuhironagai77:20210808234156p:plain

あんまり雪っぽく見えませんがまあしょうがないです。

このTexture用のMaterialを作成します。

Snow_MをDuplicateします。名前はSnowflake_Mとします。

Radial Gradient Exponentialノードを外して代わりに先程のTextureを使用します。

f:id:kazuhironagai77:20210808234210p:plain

こんな感じです。

Snow_PのParticle EmitterをDuplicateして、新しく作成したEmitterのMaterialにSnowflake_Mをセットします。

テストします。

f:id:kazuhironagai77:20210808234224p:plain

これはかなり雪っぽくなりました。

雪の結晶そのものが見えるからと言うよりは、角ばった雪が降って来る感じです。それが雪らしさを強調しています。

雪なんでよく見てないので気が付かなかったですが、丸いだけじゃなくて色々な形状があるみたいですね。

これで終わりかと思ったらまだEmitterを追加します。

今度はSnowflake_MをDuplicateしてUnlitのVersionを作成します。名前はSnowflakeUnlit_Mです。

やり方はSnow_MからSnowUnlit_Mを作成した時と同じです。

このMaterialを新らしくDuplicateしたEmitterのMaterialにセットします。

結果です。

f:id:kazuhironagai77:20210808234239p:plain

かなり雪です。

この後でTutorialでは雪の色を調節していますが、それはまあいいでしょう。

出来ました。

3.3 UE4 - Tutorial - Snow Particle System [5] のまとめ

このTutorialを勉強する前までは、どうやって雪を作成しているのか不思議でしたが、勉強したら何の事はない、単にParticleをGPUで大量に作成して空から降らしているだけでした。

ただしここでも脇役というか4種類のSpriteを作成して、微妙なSpriteの変化が雪質をリアルにしています。

やはり、VFXの質を決めるのは、沢山の脇役のEffectの存在ですよ。

炎を、炎足らしめるのは、Frameの存在だけでは足りず、その脇を舞うEmberや、煙の存在だったし、今回の雪のEffectも微妙に色や形の違う雪質の存在が雪を雪足らしめています。

それを踏まえた上で、更に今回、良いEffectを作成するのに大切だと思う事をここにまとめます。

<良いMaterialの作成>

良いEffectは良いMaterialからしか作れない。体感ですが、Effectの成果の30%位は、Materialに依存しています。

ただしMaterialの作成では、複雑な計算からTextureを作成しているが、本当に単純にTextureを読み込むより総合的に言って得なのか?この辺をキチンと評価する手段は確立されているのか?は不明で、もっとTextureを使用した方が質の高いEffectを作成するためのMaterialが作成出来る様な気がします。

まだMaterialについては、本格的に勉強した事はないので、その辺はMaterialを勉強する時に調査します。

3.4 GPUとBoundについて

これについては来週調べます。

3.5 Opacityの計算方法について

UE4 - Tutorial - Snow Particle System [5]のOpacityの計算については時間がある時に勉強します。

f:id:kazuhironagai77:20210808234348p:plain

4.スタート画面の続きで、魔女との会話を実装

まず、赤い帽子の魔女のWidgetを作成します。

今回は、世界観とかは置いておいて、金の切符を探す事がこのゲームの目的である事、のみをPlayerは赤い帽子の魔女から聞かされます。

4.1 Widgetの作成

BGIは以下の様にしました。

f:id:kazuhironagai77:20210808234416p:plain

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

f:id:kazuhironagai77:20210808234430p:plain

NPCWidgetを参考にしますが、一から作成します。名前はTalk with Witchにしました。

まだ実装は一切していませんが、Start screenから開ける様にします。

f:id:kazuhironagai77:20210808234501p:plain

あれ。文字がはみ出ています。

WrappingのAuto Wrap TextにチェックすればTextははみ出ないはずですが...。

試しにWrapping PolicyをAllow Per Character Wrappingに変えてみます。

f:id:kazuhironagai77:20210808234514p:plain

直りました。

f:id:kazuhironagai77:20210808234527p:plain

なんで?

Allow Per Character Wrappingってどういう意味なの?と思って調べたら

f:id:kazuhironagai77:20210808234541p:plain

と書かれていました。

同然でした。一wordとして認識されていたわけです。

テスト用のTextをその辺からコピペしました。

勿論、Wrapping Policyは

f:id:kazuhironagai77:20210808234556p:plain

に直しました。

f:id:kazuhironagai77:20210808234611p:plain

はい。出来ています。

日本語の場合も念のためにテストします。

f:id:kazuhironagai77:20210808234627p:plain

大丈夫ですね。

スタートボタンの機能も追加します。

f:id:kazuhironagai77:20210808234640p:plain

テストします。

f:id:kazuhironagai77:20210808234654p:plain

出来てます。

4.2 会話のData Tableの作成

会話のData Tableの型はNPCの時と同じくNPC_ConversationBaseを使用します。

以下の会話を作成しました。

f:id:kazuhironagai77:20210808234710p:plain

最後のYES、NOは表示されないセリフで、YESならば、ゲーム開始のボタンが表示され、NOならゲームが終了します。

このセリフを先程のWidgetに表示されるようにしましょう。

この辺はこんなに複雑になると思っていなかったので、先週、コードの実装方法についての下調べをしていませんでした。

今から勉強し直します。

NPC用のWidgetを開きます。

f:id:kazuhironagai77:20210808234724p:plain

まずはセリフが表示されるテキストの実装をみます。

以下の様になっています。

f:id:kazuhironagai77:20210808234738p:plain

Comment 変数にData Tableから読み取ったセリフがセットされているはずです。それをMake Literal Text() 関数が何かをしています。

f:id:kazuhironagai77:20210808234753p:plain

公式のDocumentにMake Literal Text [9] がありました。

f:id:kazuhironagai77:20210808234815p:plain

いやいや、そのLiteralの意味が分からないんです。

Mathew Wadstein 氏のWTF Is? Make Literal in Unreal Engine 4 ( UE4 ) [10] に簡単な解説がありました。

Mathew Wadstein 氏の説明は明快です。

例えば以下の例のようにあるArrayがある要素を保持しているのかどうかをContains()関数を使用して調べたい時があるとします。

f:id:kazuhironagai77:20210808234830p:plain

普通は上記の様にString の変数を作成してその変数に調べたい要素を保持さます。

しかしこのためだけに、あえて一個の変数を作成するのはコードのスパゲッティ化を促しかねません。

それを防ぐのがMake Literal関数です。

以下の様にMake Literal関数(この場合はMake Literal String関数)を使用する事で新たな変数の作成を避ける事が出来ます。

f:id:kazuhironagai77:20210808234856p:plain

なるほど。

と言う事はやっぱり要らない?

ひょっとしてですが、参考にした元のコードは以下の様な実装だったんじゃないでしょうか?

f:id:kazuhironagai77:20210808234911p:plain

これなら一個変数を減らせます。

次のノードはFormat Textです。

f:id:kazuhironagai77:20210808234925p:plain

このノードの機能は覚えています。

Data Tableで行替えに使用している、

f:id:kazuhironagai77:20210808234939p:plain

{next line}をInput変数に保持されている値に変換します。勿論Input変数には行替えの値が保持されています。

Talk with Witchウィジェット内の魔女のセリフ表示用のTextには以下の実装をしました。

f:id:kazuhironagai77:20210808234953p:plain

これで問題が在る場合は、NPCのセリフ表示用のTextの実装と同じにします。

今度は、Dialogue変数に適切なセリフをData Tableから読み取るための実装を作成します。

しかしそのためには最初にNPCWidgetを見てどのように実装しているのか確認する必要があります。

最初からCustom Eventを読んで終わりです。

f:id:kazuhironagai77:20210808235007p:plain

これは、Widgetを作成された時以外もこの実装を呼ぶ必要があるからです。勿論それは、回答ボタンを押した時です。

それでは作成されたCustom EventであるConversation Startの実装を一個ずつ見て行きます。

f:id:kazuhironagai77:20210808235022p:plain

これは村によってセリフが変わる為にどの村の住人か確認しています。

f:id:kazuhironagai77:20210808235034p:plain

今回のTalk with Witchウィジェットとは関係ないです。ので次に行きます。

関係ないノードは飛ばす事にします。

Get Data Table Row Namesノードを使用してData Tableに存在するRow Nameを全て抜き出します。

f:id:kazuhironagai77:20210808235233p:plain

変数、Comment Numberの値、Defaultでは0、に対応するセリフとその回答ボタン用のセリフを抜き出します。

f:id:kazuhironagai77:20210808235247p:plain

はい。それぞれの返り値をそれぞれの変数にセットします。

f:id:kazuhironagai77:20210808235305p:plain

回答用のボタンのテキストを専用のボタンにセットします。

f:id:kazuhironagai77:20210808235320p:plain

復習してて思い出しましたが、最近この部分の実装を勉強してました。完璧に思い出しました。

それではTalk with Witchウィジェットにおけるこの部分の実装を作成します。

f:id:kazuhironagai77:20210808235336p:plain

f:id:kazuhironagai77:20210808235341p:plain

まだ回答ボタンを作成していないのでその部分は空白です。

この時点でテストします。

f:id:kazuhironagai77:20210808235408p:plain

あれ。Next Lineが作用してません。

直します。

f:id:kazuhironagai77:20210808235436p:plain

Format Textノードでnextlineの指定を忘れていました。

f:id:kazuhironagai77:20210808235452p:plain

出来ました。

今度は回答ボタンのwidgetを作成します。

最初はNPCの回答ボタンを参考にします。

デザインはこんな感じです。

f:id:kazuhironagai77:20210808235507p:plain

f:id:kazuhironagai77:20210808235513p:plain

Canvas Panelは無いですね。

Graph側を見ます。

変数は4つあります。

f:id:kazuhironagai77:20210808235542p:plain

この内の二つの変数、Parent WidgetとAnswer Commentは

f:id:kazuhironagai77:20210808235555p:plain

Widgetを作成する時に、値がPassされています。

f:id:kazuhironagai77:20210808235610p:plain

ボタンに表示されるTextは以下の実装で行っています。

f:id:kazuhironagai77:20210808235625p:plain

最後にボタンがクリックされた時の実装です。

f:id:kazuhironagai77:20210808235652p:plain

Answer Comment変数にセットされている整数をParent WidgetのComment Numberにパスします。

その後、回答ボタンが表示されているParent WidgetのVertex Box内のChildren(つまり回答ボタン)を全部消します。

最後に、Parent WidgetのEvent 、Conversation Startを開始します。

はい。

分かりました。

それでは、Talk with Witchウィジェット用の回答ボタンを作成します。

名前はAnswer Button Witchとしました。

デザインは全く同じです。

f:id:kazuhironagai77:20210808235719p:plain

作成した変数です。

f:id:kazuhironagai77:20210808235732p:plain

NPCの回答ボタンにあった、Comment Numberは使用していないので作成しませんでした。

変数、Parent WidgetとAnswer Buttonの値はWidget作成時にパスされます。

f:id:kazuhironagai77:20210808235744p:plain

Button内のTextは以下の方法で実装しました。

f:id:kazuhironagai77:20210808235757p:plain

回答ボタンを押された時の実装は以下の通りです。

f:id:kazuhironagai77:20210808235812p:plain

実装の内容はNPCの回答ボタンの時と全く同じです。

それではテストします。

f:id:kazuhironagai77:20210808235841p:plain

ボタンが少しはみ出しています。微調整します。

f:id:kazuhironagai77:20210808235855p:plain

イキナリ全部一辺に表示されるので何処から呼んでいいのか分かりません。

やっぱりタイプライター効果が欲しいです。

後、回答ボタンは少し遅れて表示されるか、回答ボタンである事がPlayerに分かる仕組みにしないと読みにくいです。

この部分は後で考えます。

f:id:kazuhironagai77:20210808235910p:plain

この回答に対する実装をします。

「分かりました。やってみます。」を選択した場合は、下に「ゲームを始める」のボタンが表示されます。「残念ですが、他を当たってください。」を選んだ場合はゲームが終了します。

まず、「ゲームを始める」ボタンは既に表示されていますので、それを消します。

以下の実装で消しました。

f:id:kazuhironagai77:20210808235943p:plain

「分かりました。やってみます。」を選択した場合、data TableはYESを返します。また「残念ですが、他を当たってください。」を選んだ場合は、Data TableはNOを返します。

f:id:kazuhironagai77:20210809000011p:plain

Switchを使用してData TableがYES、またはNOを返した時の対応を追加します。それ以外のTEXTをData Tableが返した時はいつもと同じ実装です。

テストします。

「分かりました。やってみます。」を選択した場合です。

f:id:kazuhironagai77:20210809000033p:plain

出来てます。ボタンが表示されました。

「残念ですが、他を当たってください。」を選びました。

ゲームが終了しました。

出来ています。

一応、これで完成です。

4.3 魔女との会話を実装のまとめ

思ったよりも時間がかかってしまいました。最初の予定では30分位で完成出来ると思っていましたが、全然そんな事なかったです。

UIはもっと見やすく出来るはずです。しかしどうすればいいのか分かりません。

後、魔女の登場シーンもアニメーションか何かがあると分かり易いですね。もう少し改良が必要ですが今週はここまでです。

5.駅の実装

5.1 切符の作成

切符は駅で買えるようにします。

まず、切符の絵を作成します。

f:id:kazuhironagai77:20210809000108p:plain

出来ました。

切符のData Tableを別に作成します。

f:id:kazuhironagai77:20210809000122p:plain

うーん。この設定方法だと、売り買い出来てしまいますね。

Itemや切符のデータの整理方法についても考える必要がありますね。

5.2 切符の実装方法について

切符の実装方法についてって一体何の事なのかすっかり忘れてしまったんですが思い出しました。

以下の事について検討する必要があります。

  • Itemとして保持するのか?別なArrayを作成するのか?
  • 駅で使用する時の実装について
  • 戦闘中にItemとして使用した場合

これらの事は何となくですが既に検討していますね。戦闘中の切符の使用方法についての検討は考える必要があります。がそれも後で良いでしょう。それよりも駅の製作です。駅を作って行きます。

5.3 駅の実装

当然ですが、今Warpに使用してるBP、A_WarpGateKeeperを改良して作成します。

f:id:kazuhironagai77:20210809000156p:plain

名前はGalaxy Train Stationにします。

銀河鉄道の英訳ってGalaxy Railroadになってるんですけど、あんまりRailroadにピンと来ません。

でも鉄道の駅はRailroad stationって言い方もしていますね。Train Stationと言う言い方も勿論ありましたが。

f:id:kazuhironagai77:20210809000231p:plain

まずは駅員に話しかけた時に開くWidgetを作成します。

そう言えばWidgetの発音もwɪʤɪtなのでカタカナで書くならばウィジェットではなくてウィヂェットですね。発音を正確に聞くとウィヂェットというよりウィヂュィトって感じですね。

因みにʒの音とʤの音はLとR以上に日本人の苦手とする音で、日本語表記でジとヂがあるから簡単に区別つけられると思っていると結構足元をすくわれます。私も聞き分けは出来てないですし、あんまり発音も自信が無いです。

言語学者によると日本語表記におけるジとヂの違いは音から来てるものではないからで、例えばじじいと言うときの発音は実際は、ぢじいと発音してるらしいです。

言われてみるとそんな気がします。確かにじじいの最初のジはヂに聞こえます。

で、ウィジェットをウィヂュィトと書いても誰も理解出来ないので、これからはウィジェットと言う言葉は使用せずに、Widgetを使用します。

後、私はWidget BPの事をWidgetと読んでいますが、Widgetの正確な定義はWidget BP内で使用している以下のパーツの事を指しているはずです。

f:id:kazuhironagai77:20210809000245p:plain

でもUE4

f:id:kazuhironagai77:20210809000258p:plain

と言っていますしあんまり厳密じゃないのかもしれません。

こんな感じにして見ました。

f:id:kazuhironagai77:20210809000325p:plain

試しに開くとこんな感じです。

f:id:kazuhironagai77:20210809000338p:plain

良いですね。

Third Person CharacterのBPはIn Warp Gate Keeperをそのまま使用させてもらいます。

f:id:kazuhironagai77:20210809000356p:plain

<「駅から出る」ボタンの実装>

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

f:id:kazuhironagai77:20210809000413p:plain

特にコメントもありません。

テストします。

f:id:kazuhironagai77:20210809000427p:plain

普通に戻れました。

<「銀河鉄道に乗る」ボタンの実装>

これはW_WarpGate Widgetを開いてW_WarpGate Widgetに全部任せる事にします。

f:id:kazuhironagai77:20210809000446p:plain

テストします。

普通に開けました。

f:id:kazuhironagai77:20210809000459p:plain

「ワープします。」をクリックします。

f:id:kazuhironagai77:20210809000515p:plain

出来ました。

セリフに問題があるので直します。

NPC_Parent WidgetNPC Warp Gate Keeper変数のセリフを以下の様に変更します。

f:id:kazuhironagai77:20210809000527p:plain

そしてW_WarpGate WidgetのTextの表示を以下の様にします。

f:id:kazuhironagai77:20210809000540p:plain

テストします。

f:id:kazuhironagai77:20210809000602p:plain

f:id:kazuhironagai77:20210809000609p:plain

出来ていますね。

6.駅における切符の購入の実装

はい。ここからが今週の本番です。先週、道具屋の所で散々調べたので実装方法は理解しているはずです。

6.1 Widgetの作成

まずデザインです。

f:id:kazuhironagai77:20210809000632p:plain

Playerの所持金と所持しているItemを表示する実装は簡単なのでここでやってしまいます。

Playerの所持金を表示する実装です。

f:id:kazuhironagai77:20210809000645p:plain

所持しているItemを表示する実装は以下の通りです。

f:id:kazuhironagai77:20210809000658p:plain

テストします。

f:id:kazuhironagai77:20210809000712p:plain

出来ていますね。

6.2 購入出来る切符の表示

次に切符を表示するためのWidgetを作成します。

先週復習した道具屋の実装を参考にして切符購入用のボタンを作成しました。Ticketと名付けました。

f:id:kazuhironagai77:20210809000730p:plain

Ticket Widget内の機能は後から実装します。

W_BuyTicket Widget内で購入出来る切符を表示するための実装です。

f:id:kazuhironagai77:20210809000745p:plain

テストします。

f:id:kazuhironagai77:20210809000800p:plain

はい。出来ています。

6.3 切符ボタンにcursorを合した時にその切符を解説するWidgetが表示さえる機能の実装

はい。

<切符を解説するWidgetの作成>

名前はDisplay Ticket Imageです。

Designは以下の通りです。

f:id:kazuhironagai77:20210809000857p:plain

TicketのImageを表示する実装です。

f:id:kazuhironagai77:20210809000912p:plain

はい。

これ以外は普通の実装なので記録は省略します。

<Display Ticket Imageを表示する機能の実装>

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

f:id:kazuhironagai77:20210809000930p:plain

Ticketを購入した時にもDisplay Ticket Image Widgetは消さないといけないのでCustom Event、Remove Display Ticket Image Widgetを作成し、そこに実装しました。

テストします。

f:id:kazuhironagai77:20210809000946p:plain

はい。Cursorを普通の切符に重ねると普通の切符のDisplay Ticket Image Widgetが表示されています。

勿論、Cursorを退かせばDisplay Ticket Image Widgetは消えます。

f:id:kazuhironagai77:20210809001009p:plain

出来ています。

6.4 切符の購入の実装

それでは切符の購入の実装を行います。

f:id:kazuhironagai77:20210809001026p:plain

一個ずつ実装内容を説明します。

まずticketの名前がData Table、Ticketsにあるか調べます。

f:id:kazuhironagai77:20210809001043p:plain

当然あるはずですが、ItemはEnumで管理していないので念のためにしています。

次はその切符を買えるお金を持っているかチェックします。

f:id:kazuhironagai77:20210809001057p:plain

持っていない場合は何も起きません。持っている場合は、所持金から切符代が引かれます。

f:id:kazuhironagai77:20210809001126p:plain

そして買った切符が、所持品として追加されます。

f:id:kazuhironagai77:20210809001139p:plain

買った切符がW_BuyTickets Widgetの左側の道具袋の欄にも表示されるようにします。

f:id:kazuhironagai77:20210809001159p:plain

以上です。

テストします。

所持金が金貨100しかないので、切符の切れ端を買います。

f:id:kazuhironagai77:20210809001221p:plain

買えました。

あれ?

戻るボタンがありません。追加します。

f:id:kazuhironagai77:20210809001240p:plain

実装は以下のようにしました。

f:id:kazuhironagai77:20210809001253p:plain

テストします。

切符の切れ端を買いました。

f:id:kazuhironagai77:20210809001309p:plain

戻るボタンを押します。

f:id:kazuhironagai77:20210809001323p:plain

「駅から出る」を押します。

f:id:kazuhironagai77:20210809001349p:plain

出れました。

f:id:kazuhironagai77:20210809001403p:plain

道具袋を開いて見ます。

先程購入した切符の切れ端がありました。

今度は、駅から出るボタンを押さずに「銀河鉄道に乗る」を押します。

f:id:kazuhironagai77:20210809001416p:plain

普通に乗れますね。

出来ていますね。

7.駅における移動の実装方法の検証

7.1 切符を徴収する機能を追加

これは、銀河鉄道に乗る前に、切符を徴収する機能を追加するためにはどうしたら良いのかを検証しておく。と言いたかったんです。

簡単なAlgorithmを以下にまとめます。

  • 切符があるかどうかの確認。
  • 切符が無い場合
    • 「必要な切符を持って言いません。」と連絡して前の画面に戻る。
  • 切符が在る場合
    • 切符を一枚減らす。
    • 移動する。

こんなもんですね。

それではそれぞれのAlgorithmを実装するために必要なnodeを検討しましょう。

切符があるかどうかの確認

一番簡単な方法は、Playerが所持しているItemの名前をチェックする事です。

もしItemの名前の一部に切符があるかどうかは以下のノードでチェック出来ます。

f:id:kazuhironagai77:20210809001454p:plain

所持しているItemに普通の切符があるかどうかのチェックは以下の方法で出来ます。

f:id:kazuhironagai77:20210809001510p:plain

前の画面に戻る方法

これは、W_BuyTicket Widgetの戻るボタンで実装した方法と全く同じで良いはずです。

f:id:kazuhironagai77:20210809001531p:plain

<切符を一枚減らす>

公式DocumentのArray Nodes [11] に詳しい解説がありますが、

f:id:kazuhironagai77:20210809001549p:plain

で行けそうです。これって同じ名前のItemを全部消してしまうと思っていたんですが、Array Nodes [11] に以下の様な解説がありました。

f:id:kazuhironagai77:20210809001602p:plain

多分このnodeで大丈夫でしょう。

<移動する>

現時点での移動は以下の実装で行っています。

f:id:kazuhironagai77:20210809001626p:plain

これは一個のmapに一個の駅しかないから可能な方法です。いずれ一個のマップ内に沢山の駅を配置する事になります。

将来的にはRPG Game Instance BPに新しい変数を作成してどの駅に到着するのかを指定する必要があります。新しいmapを開いたらその駅名を元にPlayer の操作するキャラをSpawnさせる場所を決めます。

もう時間が無くなってしまいました。今週はここまでとします。

8.実際に別なマップに移動してる間に別なアニメーションを表示する方法についての調査

来週、調査します。

9.Good Skyの復習

これも来週以降になってしまいました。

10.まとめと感想

今週