UE4の勉強記録

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

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

f:id:kazuhironagai77:20210524004026p:plain

<前文>
パレスチナ空爆とSavage
アメリカで生活していると、結構、ユダヤ系の人と仲良しになる事は多いです。ただし、傾向としては積極的にはユダヤ系とは名乗らない人が多かったです。アメリカのクリスマスって日本の正月とほぼ同じで、みんな家で過ごすんですが、その時に家に帰らないので、ユダヤ系なのかと分かったりします。
そういうわけで、今回のイスラエルによるパレスチナ空爆みたいなニュースを、アメリカ人の友人と話題にする事は、非常にSensitiveで腫物を扱うような対応が必要になります。
単純に「イスラエル悪い」と言っていると、ユダヤ系の友人といつの間にか縁遠くなったりします。ユダヤ系の人は本当に絶妙な消え方をします。
だからと言って「イスラエル正しい」と、アクロバティックな擁護をすると、イスラエルの政策に批判的なユダヤ系のアメリカ人も、実は多くて、そのタイプだった場合、激高させてしまったりします。
本当なら触れないで過ごしたい話題ですが、これだけ大きなニュースになると触れない事もある種の意思表示になってしまいます。
そこでSavageの出番です。
野蛮と言う意味ですが、あまり非難的なニュアンスやネガティブな意味は無い気がします。アニメだとDragon ballベジータとか、進撃の巨人のリヴァイとかがよくSavageと言われています。Badassに近いニュアンスがある気がします。Badassは危ない奴と言う意味と、格好いい奴という二つの意味があって、オラついている感じの人を後腐れなく表現する時に使用出来てこれまた便利な単語です。ただし、今回のような国際問題について語る時に、おケツと言うのはちょっと問題ですのでSavageの方が相応しいと思います。
イスラエルはSavage。」位の感想なら、ニュースで見たままの感想なので、相手がどのタイプでも、縁を切られたり、激高される事はないと思われます。
それでは今週の勉強を始めます。

<本文>
1.今週の予定

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

  • NiagaraCascadeの勉強
  • Block1にもっとモンスターを出現させる
  • Block2,3を作成する時に簡単に出来る様にBlock1をActor化する。
  • Block2,3を作成する。
  • 魔法陣の改良

2.Niagaraの勉強

もうちょっとだけVFXの勉強をします。
ただし、そろそろ手段が目的化し始めているので、目的をはっきりさせます。つまりこれ以上は勉強する必要がないラインを極めておきます。
「自分でVFXを作る。」
ハッキリ言うと最初からこれが目的でした。別にNiagaraでもCascadeでもどっちでも良いんですが、Tutorialをみてそのまま作成するのではなく、自分で最初から作成出来るように勉強を始めたんです。
何を作りますか?
花火。
花火を作ります。
これを目的に勉強します。
期限も決めます。7月までに完成させます。
花火を作成する事を踏まえて何を勉強するか今から決めます。

f:id:kazuhironagai77:20210524004434p:plain

Sprite Particleを使用するのかMesh Particleを使用すべきなのか?何を基準に決めるのでしょうか?分かりません。
Sprite Particleを使用する場合は、CPUかGPUを選ぶ必要があります。多分Eventを使用する事になるのでCPUで行きましょう。
次にParticle Lightを使用すべきかどうかですね。これは勉強しないと分かりませんね。
Beam やRibbonも必要かもしれません。

2.1 SpriteかMeshか?
UE4Niagara関連の記事でこれについて論じているサイトは見つかりませんでした。しかしVFX全般でSpriteやmeshは使用されているはず。と思い調べたらSprites vs Meshes [1] にSpriteやmeshの長所短所が説明されていました。

f:id:kazuhironagai77:20210524004649p:plain

うーん。
Spriteって2DゲームでTextureを貼る奴ですよね。
確かOpenGLでSpriteを勉強した時は、点にTextureを貼り付けた気がします。そのTextureが常にカメラの方を向いているんじゃなかったでしたっけ。この点自体は3D空間に作成したはずです。
もう忘れてしまいました。
そうだ公式のDocumentのCreate a Sprite Particle Effect in Niagara [2] を見れば何か書いてあるかも。

f:id:kazuhironagai77:20210524004754p:plain

ありました。
やっぱり、Sprite 自身は3d空間に生成され、そのSpriteにTextureがカメラに向いた状態で貼られている様です。
MeshもCreate a Mesh Particle Effect in Niagara [3] に説明があります。

f:id:kazuhironagai77:20210524004859p:plain

こっちはやっぱり単なるStatic Meshを使用しているんですね。
Spriteに比べると細部に渡って正確な表現が出来ると書かれています。
コストはどうなんでしょうか?
何となくですがSpriteの方が低コストで出来そうです。ネットを探してもこれに関する記述が見つからないので後でSpriteとMeshで全く同じEffectを作成して比較してみましょう。
機能的な違いとしてはSpriteはGPUで計算出来たり、Light particleを使用出来たりしますが、Meshはそう言う事は出来ないと言う事ですね。
ただこれだけだとSpriteを選択すべきかMeshを選択すべきかの基準は分かりません。
現状、分かる事はこれ位ですね。

2.2 Particle Light の勉強
Create a Particle Light [4] を勉強します。
最初の説明分を以下に示しておきます。

f:id:kazuhironagai77:20210524005021p:plain

この説明によるとParticleに発光する機能を追加する機能みたいですね。
ざっと全体を読むとLight Rendererを使用していますね。このDocumentではSprite RendererにLight Rendererを追加して使用していますが、Mesh Rendererの場合もLight Rendererを追加出来るのでしょうか?
更に疑問ですが、Material自体も発光出来ますよね。発光出来るMaterialを使用したparticleとはどう違うんでしょうか?
取りあえず、このDocumentをサラッとやってみて疑問点を書き出してみましょう。それからそれらの疑問点をどう解決するかを考えましょう。
以下のように出来ました。

f:id:kazuhironagai77:20210524005046p:plain

それでは疑問点を書き出していきます。
まず。Light Rendererが何をしているのかが分かりません。
以下にLight Rendererの設定を0にした場合を示します。
f:id:kazuhironagai77:20210524005109p:plain

f:id:kazuhironagai77:20210524005119p:plain

普通に光っていますよね。
今度は赤に光らせます。赤なら青とは違いLight Rendererが何をやっているのかが分かり易いはずです。

f:id:kazuhironagai77:20210524005143p:plain

うん。地面が赤くなっている。
キャラを近づけると、キャラは紫色になりました。

f:id:kazuhironagai77:20210524005205p:plain

分かりました。Light RendererはLight Actorと同じ働きを一つ一つのParticleでしているんです。
分かり易いように、全く光のないLevelを作成してこのVFXを配置します。
Light Renderの設定を0にしてみます。

f:id:kazuhironagai77:20210524005226p:plain

Particleは発光していますが、まわりの物質を照らす事はありません。地面や直ぐ側にいるThirdPersonCharacterは真っ黒なままです。
ここにLight Rendererを追加すると、まわりの物質を照らします。以下に示した例は赤だけ発光させています。

f:id:kazuhironagai77:20210524005507p:plain

f:id:kazuhironagai77:20210524005516p:plain

しかし何故紫色で発光しているんでしょうか?
どこかで青色も拾っているんでしょうね。
手に持って遊ぶ花火ならこの機能は大切です。一方で空に打ち上げられる花火の場合はこの機能は別に要らないですね。
Mesh Renderer にLight Rendererは追加出来るのでしょうか?
試してみます。

f:id:kazuhironagai77:20210524005545p:plain

何これ?
よく考えたらMesh Rendererについてキチンと勉強してませんでした。次はこれを勉強します。

2.3 Create a Mesh Particle Effect in Niagara [3] の勉強
Create a Mesh Particle Effect in Niagara [3] を勉強します。
出来ました。

f:id:kazuhironagai77:20210524005741p:plain

4.2で忘れていた事についてまとめます。
まずMaterialを追加する事を忘れていました。
MaterialはMesh RendererのOverride Materialsにチェックを入れて、かつ+を押す事でelementを追加する事で使用出来ます。

f:id:kazuhironagai77:20210524005801p:plain

次にRenderに元々あるSpriteを消す必要があります。

f:id:kazuhironagai77:20210524005822p:plain

更にParticle Spawn CategoryのInitialize Particle moduleのparameter、Sprite Attributesの値をUnsetにします。

f:id:kazuhironagai77:20210524005846p:plain

一方でMesh AttributesのParameterはUnsetから変えます。

f:id:kazuhironagai77:20210524005909p:plain

これらの手順がMesh particleを使用するために必要でした。

2.4 Mesh ParticleでLight Renderが使用出来るか試す。
このMesh ParticleでLight Rendererが使用出来るか試します。
まず2.3で作成したNSを光の全くないLevelに配置します。

f:id:kazuhironagai77:20210524005937p:plain

真っ暗です。
2.2でしたようにParticle SpawnのInitialize ParticleのColor ModeのColorのRの値を1から50に変更します。

f:id:kazuhironagai77:20210524010006p:plain

Spriteと違って発光する事はありませんでした。

f:id:kazuhironagai77:20210524010202p:plain

今度は、使用したMaterialにEmissive Colorを追加して発光させます。

f:id:kazuhironagai77:20210524010225p:plain

Particle SpawnのInitialize ParticleのColor ModeのColorと違う事を示すため緑にしました。

f:id:kazuhironagai77:20210524010250p:plain

今度は光っています。
これにLight Rendererを追加してみましょう。

f:id:kazuhironagai77:20210524010310p:plain

2.2でやったようにRadius ScaleとColor Addの値を変更します。

f:id:kazuhironagai77:20210524010332p:plain

結果です。
地面が赤くなっています。

f:id:kazuhironagai77:20210524010354p:plain

つまりLight RendererはMesh Particleと併用出来ると言う事ですね。

2.5 Mesh ParticleとSprite Particleの違いを示す。
以下の様なMaterialを作成しました。

f:id:kazuhironagai77:20210524010426p:plain

Sprite RenderingのMaterialにセットします。

f:id:kazuhironagai77:20210524010450p:plain

以下の様になっています。

f:id:kazuhironagai77:20210524010514p:plain

これでも問題ないですが、端の黒い部分は絵を描くときに敢えて透明にしたので消したいですね。
そこだけ直します。
MaterialのBlend ModeをTranslucentにしました。

f:id:kazuhironagai77:20210524010537p:plain

f:id:kazuhironagai77:20210524010546p:plain

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

f:id:kazuhironagai77:20210524010631p:plain

Particleを見る角度を変えましたが、Materialは常にこっちを正面としています。

f:id:kazuhironagai77:20210524010655p:plain

上から見てもMaterialは正面を向いています。

f:id:kazuhironagai77:20210524010722p:plain

今度はMesh Particleを作成します。

f:id:kazuhironagai77:20210524010826p:plain

CubeにMaterialが貼られた状態でCubeがParticle として生成されています。

f:id:kazuhironagai77:20210524010847p:plain

2つを並べると違いが一目瞭然です。

f:id:kazuhironagai77:20210524010908p:plain

斜めから見た状態です。

f:id:kazuhironagai77:20210524010929p:plain

Shader Complexityも一応チェックしてみます。

f:id:kazuhironagai77:20210524010948p:plain

重なっていない部分はそんなに差がないように見えます。
1000個、Spriteを生成してみました。
FPSは4.20になりました。

f:id:kazuhironagai77:20210524011034p:plain

今度は、1000個、Meshを生成しました。
FPSは4.30でした。

f:id:kazuhironagai77:20210524011056p:plain

この結果だけではハッキリとは言えませんが、MeshとSpriteはコスト的には同じ位なのかもしれません。

2.6 ちょっとだけ花火を作成してみる。
以下に結果だけ示します。

f:id:kazuhironagai77:20210524011119p:plain

f:id:kazuhironagai77:20210524011128p:plain

f:id:kazuhironagai77:20210524011135p:plain

何か違います。

3.Cascadeの勉強

もうあんまり良いTutorialも見つからないので、何か自分で作成してみる事にします。
Particle systemを作成します。MyCascadeと名付けました。

f:id:kazuhironagai77:20210524011209p:plain

何を作るか以前に、サンプルに使用されているTextureが常にカメラに向かって正面を向いているのか分かりません。

f:id:kazuhironagai77:20210524011228p:plain

先程作成したSmileマークに変更します。
Spawn moduleのMaterialをSmile_Matに変更します。

f:id:kazuhironagai77:20210524011251p:plain

暗い。

f:id:kazuhironagai77:20210524011313p:plain

試しにBGCを明るい黄色にしてみましたが、Effect自体は真っ黒なままです。

f:id:kazuhironagai77:20210524011335p:plain

実際のPlay画面です。

f:id:kazuhironagai77:20210524011358p:plain

暗い事はないですね。
これは、Effectを作成する時はPreviewだけでなく実際のLevelに配置したEffectも見ながら作成すべし。という教訓ですね。
Unlitにしてみました。

f:id:kazuhironagai77:20210524011416p:plain

これは見やすい。
見やすいから絶対正しい訳ではないですが、これで行きます。
まず、生成されるParticleの量が多すぎますので、数を減らします。
生成されるParticleの量を管理しているのは、間違いなくSpawn moduleです。

f:id:kazuhironagai77:20210524011436p:plain

Spawn moduleを見てみます。

f:id:kazuhironagai77:20210524011453p:plain

Spawn、Burstの項がありました。
思い出して来ました。
Particleの生成方法にはSpawnとBurstの2種類があったんでした。その2つの違いが良く分からないと。前に勉強した時はそうでした。
Spawnの方の設定は以下の様に成っていました。

f:id:kazuhironagai77:20210524011520p:plain

RateのConstantが20にセットされていますが、1秒間に20個のParticleが生成されるのでしょうか?
Burstの方は、Burst Listが0ですが、この設定でもParticleの生成に、何らかの影響を与えているのでしょうか?

f:id:kazuhironagai77:20210524011558p:plain

分かりませんね。
取りあえず、SpawnのRateのConstantを5にします。

f:id:kazuhironagai77:20210524011626p:plain

生成さられるParticleの量が減りました。
今度は、SpawnのRateのConstantを1にしました。

f:id:kazuhironagai77:20210524011703p:plain

大体、1秒間に1個生成されている感じです。
そう言えば、Distributionについての詳しい説明が公式のDocumentにあったはずです。

f:id:kazuhironagai77:20210524011724p:plain

今こそそれを勉強しましょう。

3.1 Distributionの勉強
公式のDocumentのDistributions [5] を勉強します。
最初にDistributionの説明です。

f:id:kazuhironagai77:20210524011845p:plain

あれ。これParticleの勉強を始めたばかりの時に読みましたよね。あの時は五里霧中で勉強していたので何を言っているのか良く分かっていなかったです。今は違います。今、上記の文章を読むと以下の意味で言っていると分かります。
Distributionはある値を返す方法を指定します。以下の種類から選択出来ます。

  • 定数を返す。
  • 指定した2つの値の範囲からランダムな値を選び返す。
  • 指定したグラフから補間して計算した値を返す。
  • 指定したParameterから割り出した値を返す。

あれ、4つしか説明していませんね。
実際は以下に示した様に5種類あります。

f:id:kazuhironagai77:20210524011942p:plain

それは兎も角として、前回勉強した時、上記の説明で訳わからなくなったのは、シンプルにDistributionsの機能、値を返すと言う事の説明が無かったからです。その値の返し方に、4または5種類の方法があります。と説明されていれば初心者でも理解出来ました。
これは自慢じゃなくて確実に本当の事ですが、私、人に物を教えるのが滅茶苦茶、上手いです。多分、1万人に一人とかのレベルの才能があります。その私の才能が言っていますが、Distributionを説明するのに、値を返すと言うDistributionの機能を説明しなかったら誰も理解出来ないと。
今の時点で私の中でどのように初心者にParticle systemを教えるのかの最初の部分の構想が出来ています。

基礎編

  1. VFXとは何かについて(映画とCGを使用した特殊効果の関係からVFXが生まれた!)
  2. 3D GraphicsにおけるVFXの逆輸入とUE4VFX(Particle system)
  3. UE4におけるParticle system(Sprite、Emit、Moduleなど)
  4. Particleをコントロールする。(Distributionなど)
  5. 残りはこれから勉強する内容で今は不明。)

応用編

  1. 炎の作成方法
  2. 煙の作成方法
  3. 雷の作成方法
  4. 以下略

この方法で教えたら、多分、BPが使いこなせるデザイナーなら自在にParticle Effectを使いこなせるようになると思います。
ここは大切なので少し詳しく記録しておきますが、前の議論で出て来た、以下に示しているProgrammerの種類とは別な話です。

f:id:kazuhironagai77:20210524013236p:plain

といっても100%別な話ではありません。これについては後でまとめ直します。
<Distribution Baking>
以下のヤツの解説です。

f:id:kazuhironagai77:20210524013308p:plain

カーソルを乗せると以下の説明が出て来ました。

f:id:kazuhironagai77:20210524013328p:plain

FRawDistributionってなんでしょうね?この説明では兎に角、Trueにしておけと言う事みたいです。
Document に完璧な説明がしてありました。

f:id:kazuhironagai77:20210524013347p:plain

要するに、前もって計算しておいて、その結果を使用するのがCan be Bakedをチェックした場合です。
Edgeつまり端は前もって計算出来ないのでチェックを外す必要があるそうです。でも具体的にEdgeはどこを指すんでしょうね。
<Distribution Types>
FloatとVectorがあります。以上です。一応書いておきますが、Computer scienceにおけるVectorは2個以上の値を保持する場合全てを指します。物理系みたく2又3個の値に縛られる事はないです。
<Float Distributions>
Floatの場合に選択出来る、それぞれの方法についての解説です。
<<Distribution Float Constant>>
定数で返します。

f:id:kazuhironagai77:20210524013458p:plain

一番、分かり易いですね。
<<Distribution Float Uniform>>
最低値と最高値を指定します。その間の値からランダムに返します。

f:id:kazuhironagai77:20210524013536p:plain

これも分かります。1とか4とかの値がランダムに返されるだけです。
<<Distribution Float Constant Curve>>
これが分かりにくいやつ、第一弾です。これを選択するとPointsという項目が出現し、Elementを追加出来る様になります。
追加すると以下に示した様に、0、In Val、Out Val、Arrive Tangent、Leave Tangent、そしてInterp Modeの項目が出て来ます。

f:id:kazuhironagai77:20210524013641p:plain
このそれぞれの項目が何を指しているのか直観的に理解出来ません。
はい。そこで公式のDocumentの説明です。ここではCurveを以下のように定義しています。

f:id:kazuhironagai77:20210524013700p:plain

まず、1でグラフ上の2点を指定します。そして2でその間を曲線でつなぎます。曲線の引き方を指定するために3のTangent lineを使用しています。
うん。これは分かりますね。
しかし実際のParameterを見ると??となってしまいます。

f:id:kazuhironagai77:20210524013858p:plain

まず、上のグラフで1の値を示すParameterがIn ValとOut Valだそうです。In Valがx軸、Out Valがy軸の値を指しています。
でもそれだと一点しか表せないですよね。
となると色々な可能性が出て来ます。
例えば以下に示した関係が考えられます。

f:id:kazuhironagai77:20210524013920p:plain

でもこれだと最低でも要素は2個必要になるはずです。
分からんですな。
この場合、どうにかしてCurve editorに表示出来ないんでしょうか?そうすると非常に分かり易くなります。

f:id:kazuhironagai77:20210524014008p:plain

この説明みるとCurve Editorで調節出来そうですが?
もう一つ分からない箇所があります。
Tangent ですが-150から150の間となっています。

f:id:kazuhironagai77:20210524014027p:plain

これって具体的にどの角度なんでしょうか?
これも分かりませんでした。
今の所これ以上の情報がないので、Distribution Float Constant Curveに関してはここで調査は打ち切りです。
うーん。何か前も同じような事をやってここで中止したような気がします。デジャヴかも知れないですが。
ただ結局、普通の人で特別に細かい調整がしたい場合を除けば以下に示したような、

f:id:kazuhironagai77:20210524014110p:plain

①のような、直ぐに値が高くなってその後は徐々にしか値が上昇しない。②のように値はLinearで上昇する。③のように値は中々上昇しないが最後で急激な上昇をする。の3パターンの選択が出来れば十分な気がします。
<<Distribution Float Constant Curve パート2>>
本当に偶然なんですが、以下の白枠で囲ったアイコンがなんかグラフっぽいなと感じてクリックしてみました。

f:id:kazuhironagai77:20210524014148p:plain

そしたら、今まで、うんともすんとも言わなかったCurve Editorにグラフが表示されています。

f:id:kazuhironagai77:20210524014215p:plain

あれ。これ今迄の疑問が解けちゃう?
以下の様な設定にしてみました。

f:id:kazuhironagai77:20210524014238p:plain

グラフをみると

f:id:kazuhironagai77:20210524014255p:plain

出来てる。
ああっ。解ける。謎が解けます。
まず、Interp Modeの謎から解いていきます。
Point 0のInterp Modeを変えると何か影響するんでしょうか?LinearからCurve Autoに変えてみます。

f:id:kazuhironagai77:20210524014316p:plain

おお、カーブの形状が変わりました。

f:id:kazuhironagai77:20210524014336p:plain

上の図の予測は違っていましたね。要素1つまりPoint 1のIntra Mode(スペルも間違っていた。Interp modeでした)ではなく要素0のInterp modeによって変化しました。

f:id:kazuhironagai77:20210524014438p:plain

Curve Autoに変えた事でTangentの調整するためのバーも出現しました。

f:id:kazuhironagai77:20210524014508p:plain

今度はこのTangentの角度を変えてみました。

f:id:kazuhironagai77:20210524014529p:plain

あれ、Arrive TangentとLeave Tangentの両方の値が変わっています。

f:id:kazuhironagai77:20210524014559p:plain

うーん。これは?

公式の最大値である150も試してみます。

f:id:kazuhironagai77:20210524014618p:plain

こんな感じです。

f:id:kazuhironagai77:20210524014635p:plain

垂直ではないんですね。
Arrive TangentとLeave Tangentの値が同じなのは、Point 0からCurveが始まっているからかもしれないと思いPoint 0とPoint 1の間にもう一個Pointを作成してそのTangentを変化させてみました。

f:id:kazuhironagai77:20210524014656p:plain

この場合もArrive TangentとLeave Tangentの値は一緒でした。

f:id:kazuhironagai77:20210524014745p:plain

と言うかこれって微分しているだけじゃん。
あ。だからTangentなんだ。うーん。何でこんな簡単な事に今まで気が付かなかったんでしょう。
何か、Curve Editorで実際のCurveと比較できるようになったら一発で分からない事が全部分かるように成っちゃいましたね。
<<Distribution Float Uniform Curve>>
これも公式のDocumentで理論は理解できました。
以下の図の黄色の範囲からランダムな値が選ばれます。Distribution Float Uniformと違うのが範囲が時間によって変化する所です。

f:id:kazuhironagai77:20210524014826p:plain

だたし、これもそれぞれのParameterが何を言っているのか分かりません。

f:id:kazuhironagai77:20210524014853p:plain

しかしCurve Editorにグラフとして表示してみると

f:id:kazuhironagai77:20210524014910p:plain

全部分かります。
本当に拍子抜けする位簡単に全部のParameterの意味が分かります。
<<Distribution Float Particle Param>>
これは値をBPなどからコントロールする時に使用するみたいです。今回は関係ないのでパスします。
<Distributionのまとめ>
SpawnのRateに使用されているDistributionについて勉強しました。
今回の勉強で、ほぼ完全に理解する事が出来ました。その上でこれからParticle Systemを勉強する人が混乱しないように、学習に必要なポイントをここにまとめておきます。

  • Distributionは値を返す働きの事です。その上でどのように値を返すのかの選択が出来ます。
  • それぞれのDistributionのタイプの理論的な意味は、公式のDocumentであるDistributions [5]を見ると理解できます。
  • Distributionに使用するParameterの意味は、公式のDocumentであるDistributions [5]を読んでも理解出来ません。というか間違っています。正しい意味はCurve editorにCurveを表示させる事で理解出来ます。

3.2 その他の勉強した事
Distributionを調べている仮定で以下のものについても分かったので記録しておきます。
<Rate Scale>

f:id:kazuhironagai77:20210524015041p:plain

単にDistributionで返した値をRateの値に掛けているだけです。何故Rateだけで管理しないのかは分かりません。
<Process Spawn Rate

f:id:kazuhironagai77:20210524015114p:plain

Process Spawn RateがfalseだとSpawn ModuleがStackに積まれた場合、実行されなくなるそうです。

4.Block1の名称を決める。

先週、Landscape4のBlock1の設計方法の問題点や改善点について検討しました。その結果、一応考えられる問題点や、予想されるバグの解決方法などの対応策を実装する事が出来ました。

f:id:kazuhironagai77:20210524015157p:plain

しかしその後で、戦闘後、沼にワープする事があるバグを修復するに当たってBlock1とTerritory1のサイズを同じにすると、ゲームとして面白くもないし、親切でもない事が分かりました。

色々検討を重ねた結果、以下のようにTrigger boxを2個作成して、

f:id:kazuhironagai77:20210524015217p:plain

Trigger 1でモンスターの出現、Trigger2でTerritory内に侵入したと言うFlagを建てるようにしました。これで一応問題なく動いている事も確認しました。
しかし、今週改めて考えてみると、この新しく作成したBlock1、先週行った旧式のBlock1に対しての検討を行っていません。色々な問題点に対応出来るのかの検討をする必要があります。
しかし、検討する前に一つしなければならない事があります。
それは、このモンスターをSpawnするシステムの名称を考える事です。

f:id:kazuhironagai77:20210524015237p:plain

名称がなければこのような抽象的なEntityを表す事は大変難しいからです。
Area、Sanctuary、Village、House、Nestと色々考えましたがあんまりピンと来ません。
Zoneと言う名称はどうでしょうか?何かイイ感じがします。
Monster Zoneと名付ける事にしました。
Monster Zoneは以下の様な構成になっています。

f:id:kazuhironagai77:20210524015258p:plain

まず、Trigger1はBlock1と呼ばれています。この中に侵入するとMonsterが現れます。現れますが、Monsterがあなたを攻撃する事はありません。
Block1の中にはTerritoryがあります。このTerritoryは2つのComponentで構成されています。Trigger 2と Nav Mesh Bounds Volumeです。
Trigger2に侵入すると、RPG Game Instance BPのMonster Territory Number変数の数字を1に変更します。更にNav Mesh Bounds Volumeに侵入するとMonsterはあなたを攻撃してきます。
Monster Territory Number変数は、戦闘から戻って来た時に、その番号が表すTerritory内のMonsterを生成するために使用されます。

5.先週行った「モンスターの配置についての考察」の内容がこのMonster Zoneに対しても通じるのかについての検証

先週、Landscape4のBlock1の設計方法の問題点や改善点について検討した内容を見直しました。「5.モンスターの配置についての考察」、「6. モンスターの配置についての考察-その2」で考察した内容とその対策が、Monster Zoneに対しても通用するかどうかを検討します。

5.1 Trigger boxのサイズについての検討
これは、二つのMonster ZoneのTrigger 1が重なった状態でも正しく運用できるのかについてです。
<Pattern 1>Monster Zone1のBlock内にいながらMonster Zone2のBlock2に侵入した時

f:id:kazuhironagai77:20210524015409p:plain

<Pattern 2>Monster Zone1のTerritory内にいながらMonster Zone2のBlock2に侵入した時。

f:id:kazuhironagai77:20210524015521p:plain

<Pattern 3>Monster Zone1のBlock内にいながらMonster Zone2のBlockに侵入した時。

f:id:kazuhironagai77:20210524015610p:plain

これは先週のBlogの「8.2 Triggerを追加した場合の理論的考察」で既に考察されています。

5.2 Monster Territory Numberの値は常に正しく表示されるのか?
Monster Territory Numberは、数字を保持します。この数字はそれぞれのTerritoryに対応しています。戦闘後にLandscape4などの元々いたLevelに戻って来た時にこの変数に記録されている番号と対応するterritoryのモンスターが生成されます。
Pattern 1の場合、Monster Territory Number は0です。戦闘に遭遇する事はありません。ので0で正しいです。
Pattern2の場合、Territory 1に侵入しているためMonster Territory Number は1になります。戦闘後、このLevelに戻って来ますと、Territory 1のモンスターは生成されます。しかしBlock2に侵入しているのにTerritory2のモンスターは生成されません。されるべきですが。
はい。一つ目の、問題が見つかりました。
Pattern3の場合、Monster Territory Number は2です。戦闘後、このLevelに戻って来ますと、Territory 2のモンスターは生成されます。しかしBlock1に侵入しているのにTerritory1のモンスターは生成されません。
これも問題です。

5.3 Remove Defeated Monster from Landscape 4 () 関数について
これは戦闘後の話で、Monster Zoneを作成したとしても影響ないはずです。

5.4 戦闘画面に移動する場合もOn Actor End Overlap (Trigger box) が呼ばれている事について
<別なレベルに移動する時、必ずOn Actor End Overlap (Trigger box)は呼ばれるのか?呼ばれなかった場合はどうなるのか?>
はい。これが問題になるのは、戦闘に移行する時だけです。戦闘に移行する時は、Monster Zoneの場合も前となにも変わっていないはずなので同じで良いはずです。
<戦闘画面からBlock1内に戻って来た時に、On Actor Begin Overlap (Trigger box)は呼ばれるのか?呼ばれなかった場合、それぞれのParameterはどうなっているのか?>
呼ばれません。これもMonster Zoneに変更したからと言って何も変わりません。
<Block1内から移動する時、必ずMonster Name in Fighting 変数の値はNoneになっているのか?>
これも、Monster Zoneを作成しても変わらない事の一つです。Noneになっているはずです。
<Block1内から直接、Block2に移動した時はどうなるのか?>
これは、Monster zoneになった事でかなり複雑になった事の一つです。ただしこの検証は「5.2 Monster Territory Numberの値は常に正しく表示されるのか?」で既に行われています。

5.5 Territory 1に一端侵入した後に、Territory 1から逃走するとMonsterが消滅しなかった事について
これも既に検討されています。

5.6 Landscape4、Territory 1における戦闘
これも既に検討されています。

5.7 この章のまとめと感想
先週、Monsterの配置と生成で検討した内容を、もう一度Monster Zoneに対して検討する事は出来ました。ほとんどの質問は重複してたり、Monster Zoneに変わったとしても同じ結果になるものでした。
ほとんど唯一と言って良い発見したバグは、Pattern 2とPattern 3の場合、再生されるモンスターの内容が違っている事でした。

6.Monster ZoneのActor化

管理し易いようにMonster ZoneのActorを作成してみます。

6.1 Monster Zone クラスの考察
Monster Zoneをクラスとしたら何が必要か?どう作成するのが良いのかを考察します。
以下のような構成を考えています。

  • 今回はBPで試作して、それからUEC++にするかどうかを検討します。
  • Actorクラスを継承して作成します。
  • 追加するComponentは、Trigger box を2つ、Nav Mesh Bound Volumeを一つです。
  • 追加する変数は、Monster Zone Numberです。

他に必要な変数や関数があるかLandscape4をみて確認します。
<Trigger Box Blockに侵入した時>
一番外側のTrigger Box に侵入した時のEventです。Game Instance内にある指定されたDataTable通りのMonsterを生成します。

f:id:kazuhironagai77:20210524015930p:plain

実装部です。

f:id:kazuhironagai77:20210524020031p:plain

Monster CleanというBoolean 変数と、Monster Territory 1と言うMonsterBPタイプのArrayが使用されています。
<Trigger Box Blockから退散した時>
一番外側のTrigger Box から退散した時のEventです。退散の仕方は2つあり、一つは普通にBlockから脱出した場合です。二つ目は、Block内でモンスターと戦闘になり戦闘画面に飛ばされた時です。

f:id:kazuhironagai77:20210524020115p:plain

普通に退散した場合、Territoryに存在する全てのモンスターは分解・消滅のアニメーションをPlayします。
その後で、全てのモンスターはDestroy Actor関数によって消滅します。

f:id:kazuhironagai77:20210524020136p:plain

戦闘画面に飛ばされた時は、既にTerritoryに存在する全てのモンスターは消滅しているのでIsValid()関数によってアニメーションなどの実行は中止されます。
この部分で特別に使用されている変数や独自に作成された関数はありませんでした。
<Trigger Box Territoryに侵入した時>
内側のTrigger Boxに侵入した時です。RPG Game Instance BPクラスの変数、Monster Territory Numberの値を1にします。

f:id:kazuhironagai77:20210524020203p:plain

これだけです。
<Trigger Box Territoryから退散した時>
内側のTrigger Boxから退散した時です。通常に退散した時は、Monster Territory Numberの値を0に戻します。戦闘画面に移動した時はそのままです。

f:id:kazuhironagai77:20210524020228p:plain

Monster Zone クラスに必要な機能や関数、変数が大体分かりました。

6.2 Monster Zone クラスの構成
<変数>
以下の変数を作成します。
<<Monster Zone Number>>
タイプ:Int
コメント:このクラスのInstanceはそれぞれ独自の番号を持つ。RPG Game Instance BPに同じ名前の変数がある。戦闘開始時にその変数に値をパスする。
RPG Game Instance BPにある同じ名前の変数は、戦闘から戻って来た時にどのTerritoryのMonsterを生成するかと、戦闘勝利時にどのモンスター生成を管理するData Table群からどのData Tableを選択するのかを指定する働きがある。
<<Monster Clean>>
タイプ:Boolean
コメント:生成されたモンスターのActorが全て破壊されたらTrueになり、新しいMonsterが生成されるとFalseになります。
モンスターが破壊される前に新しいモンスターが生成されるのを防ぐために作成されました。
<<Monster Territory 1>>
タイプ:Monster BP(array)
コメント:生成したMonsterをassignしたarrayです。生成したmonsterを消滅し易くするために作成されました。
<関数>
使用している関数は一個だけです。
<<Spawn Monsters>>
Monsterをモンスター生成を管理するData Tableの情報を元に作成します。
以下に実装部を示します。

f:id:kazuhironagai77:20210524020346p:plain

<Event>
Eventは4種類です。
<<On Actor Begin Overlap(Block)>>
Monster を生成します。
<<On Actor End Overlap(Block)>
生成したmonsterを破壊します。
<<On Actor Begin Overlap(Territory)>
Monster Territory Numberの値を指定した値にセットします。
<<On Actor End Overlap(Territory)>>
Monster Territory Numberの値を0に戻します。

6.3 Monster Zone クラスの作成
色々、試しましたが、結構難しいです。以下の方法が他よりマシみたいです。
まずActor、Monster Zoneを作成します。

f:id:kazuhironagai77:20210524020535p:plain

正しcomponentにはなにも追加しません。

f:id:kazuhironagai77:20210524020559p:plain

その代わり変数として、BlockとTrigger、そしてTerritoryを追加します。

f:id:kazuhironagai77:20210524020625p:plain

BlockとTriggerはTrigger Boxです。TerritoryはNav Mesh Bound Volumeです。
それぞれInstance Editableにします。

f:id:kazuhironagai77:20210524020652p:plain

Level上に静的に配置されたTrigger BoxのInstance、2つとNav Mesh Bound Volumeのinstance、一つを以下にそれぞれセットします。

f:id:kazuhironagai77:20210524020716p:plain

この方法を採用する事で、以下の問題を解決できました。

  • Nav Mesh Bound Volume をBPで作成出来ない。(静的にも動的にも出来なかった。)
  • BP内でBlockとTriggerをcomponentとして追加するとそれぞれのInstanceでサイズが変更出来ない。

ベストな作成方法ではないでしょうが一応、作成するに当たって発生した問題は解決したのでこのやり方で試してみます。
更にMonster Zoneクラスに必要な変数を追加します。

f:id:kazuhironagai77:20210524020805p:plain

これらの変数はそれぞれのInstanceで値が変わります。ので

f:id:kazuhironagai77:20210524020827p:plain

にチェックを入れました。
これを入れればそれぞれのInstanceの値をバラバラに出来るのは知っていますがチェックしないと全てのInstanceで同じ値になってしまうのかどうかを忘れてしまいました。ちょっとそれを先に確認します。

7.Blue Printにおける変数についてのテスト

今までInstance Editableにチェックを入れない限り、変数の値は全てのInstanceで変化すると思っていました。

f:id:kazuhironagai77:20210524021008p:plain

最近、BPを頻繁にいじるようになってPrivateの変数でInstance毎に値を変える実装は簡単に出来る事に気が付きました。
それで、やっぱりPrivateの変数でも、それぞれのInstanceで違う値が取れるのではないのかと思いテストし直してみます。

f:id:kazuhironagai77:20210524021026p:plain

f:id:kazuhironagai77:20210524021034p:plain

以下の変数をPrivateで追加します。

f:id:kazuhironagai77:20210524021055p:plain

以下の実装をしました。

f:id:kazuhironagai77:20210524021115p:plain

Box内に侵入する毎にTest1Privateの値が1ずつ増加します。
このActorの二つのInstanceを並べました。

f:id:kazuhironagai77:20210524021155p:plain

これでテストします。

f:id:kazuhironagai77:20210524021214p:plain

5回、右のInstanceに侵入しました。Test1Private変数の値は5 になっています。
今度は左のInstanceに侵入します。

f:id:kazuhironagai77:20210524021239p:plain

Test1Private変数の値は1でした。
ああ。変数の値はそれぞれのInstanceで独立していました。UE4C++で、EditDefaultsOnly、EditInstanceOnly、とEditAnywhereの関係と

f:id:kazuhironagai77:20210524021255p:plain

は同じだとずっと思っていました。今週はもう時間がないので来週この問題をもう一度検討します。

8.Monster ZoneのActor化 : Part 2

「7.Blue Printにおける変数についてのテスト」の結果を踏まえて、Monster ZoneのActorを作って行きます。
変数のInstance editableの設定は以下のようにします。

f:id:kazuhironagai77:20210524021326p:plain

Territory、Block、TriggerそしてMonster Territory NumberはそれぞれのInstanceの値をEditorから操作する必要があるので、Instance Editableにします。Spawned MonstersとAllMonsterAreDeletedはEditorから操作する必要は全くないのでInstance Editableにはしません。
次に、いつもの変数を作成します。

f:id:kazuhironagai77:20210524021405p:plain

Eventの実装を行います。
<On Actor Begin Overlap(Block)>
最初にこのEventで使用する関数Spawned Monsterを作成します。
Spawned Monsterだと生成されたモンスターと言う意味で、間違いではないですが、この関数の機能は「モンスターを生成せよ。」の方がより実態を表していると思われるのでSpawn Monstersに変更しました。

f:id:kazuhironagai77:20210524021434p:plain

実際の実装は以下のように行いました。

f:id:kazuhironagai77:20210524021452p:plain

Monster Spawn Dataは後で作成します。
<On Actor End Overlap(Block)>
以下のように作成しました。

f:id:kazuhironagai77:20210524021517p:plain

All Monster Are Cleared変数にチェックが入っていません。
入れました。

f:id:kazuhironagai77:20210524021545p:plain

こういう細かいミスが原因で何時間もバグの修正に時間を取られるのは馬鹿らしいです。今見つかって良かったです。
<On Actor Begin Overlap(Territory)>
Monster Territory Numberをセットします。

f:id:kazuhironagai77:20210524021614p:plain

Monster Territory Numberは戦闘後にこのLevelに戻って来た時に生成するモンスター群を決定する働きも司っています。
そして「5.2 Monster Territory Numberの値は常に正しく表示されるのか?」で発見されたある条件において、生成するモンスター群が足りないバグは直していません。
このバグはMonster Zone Actorがきちんと作動する事を確認してから作成します。
<On Actor End Overlap(Territory)>
Territoryから退出した時の実装です。
やっている事は、Monster Territory Numberを0にセットしているだけです。

f:id:kazuhironagai77:20210524021651p:plain

戦闘画面に移動する時は、Monster Territory Numberを0にセットしたら意味が無くなるのでMonster Name in FightingがNoneでない事で確認しています。On Actor End Overlap(Block)でもこの方法を採用し他方が実行されるコードが少なくなる気がします。
これについても、Monster Zone Actorがきちんと作動する事を確認した後で検討します。

9.Monster Zone 2を作成する。

9.1 Monster Zone 2を作成する
「8.Monster ZoneのActor化 : Part 2」で作成したMonster Zone Actorのテストを兼ねて、Monster Zone 2を作成します。

f:id:kazuhironagai77:20210524021727p:plain

Monster Zone 2で対応しているActorは以下のモノです。

f:id:kazuhironagai77:20210524021746p:plain

f:id:kazuhironagai77:20210524021754p:plain

Monster Zoneの場所をはっきりさせるためにCubeを追加しています。
次に生成するMonsterのためのData Tableを作成します。
RPGGameInstanceBP内に以下のArrayを作成します。

f:id:kazuhironagai77:20210524021813p:plain

要素に一個だけモンスターを追加しました。

f:id:kazuhironagai77:20210524021859p:plain

作成したMonster Spawn Data をセットします。

f:id:kazuhironagai77:20210524021917p:plain

早速、バグが見つかりました。この個所を今作成したData tableに変更すると、全てのMonster Zoneで同じData Tableを使用しなければならなくなってしまいます。
それぞれのMonster ZoneのInstanceは別のData Tableを使用します。それが出来る様にコードを直します。
以下の方法で実装しました。
関数、Get Monster Spawn Data()を作成しました。

f:id:kazuhironagai77:20210524021937p:plain

Monster Territory NumberよりどのData Tableを使用するのかを指定する関数です。
この関数を使用して以下の様に実装しました。

f:id:kazuhironagai77:20210524021955p:plain

これでテストしてみます。
Block2に侵入しました。Monsterが生成されるはずです。

f:id:kazuhironagai77:20210524022013p:plain

されました。
Block2から退散しました。Monsterは分解消滅するはずです。

f:id:kazuhironagai77:20210524022031p:plain

しました。
今度はMonsterが分解消滅する前にもう一度、Block2に侵入します。

f:id:kazuhironagai77:20210524022050p:plain

Monsterが消滅してから新しいMonsterが生成されています。出来ています。

9.2 Monster Zone 2と戦闘
今度は戦闘に関してのコードを作成します。
Monster Spawn Data Landscape 4-1で調べて見ると2か所、戦闘に関連してDataTableを使用しています。

f:id:kazuhironagai77:20210524022126p:plain

最初の箇所は、戦闘終了後に、Landscape4に戻って来た時です。Trigger Box のOn Actor End Overlapは別なレベルに移動した時も発動するのに、On Actor Begin Overlapは最初からそのLevel内で生成された時は発動しません。
その問題を回避するために、Monster Territory Numberが0でない場合、つまり戦闘から帰還して生成される場所があるTrigger Box内の場合は、以下の部分で特別にMonsterを生成させています。

f:id:kazuhironagai77:20210524022331p:plain

同様の機能をMonster Zone 2に関して作成します。
正し、Monster Zoneは生成したモンスターの管理はLevel BPに任せずMonster Zone内で行っています。

f:id:kazuhironagai77:20210524022352p:plain

ので上記の機能は、Monster Zone内で作成します。
以下のように作成しました。

f:id:kazuhironagai77:20210524022411p:plain

細かい説明は省きますがこれで行けるはずです。
DataTableを使用している2番目の箇所は、戦闘後に倒したMonsterを記録する処です。
ここは全く同じ使用で、Monster Spawn Data Landscape 4-1をMonster Spawn Data Landscape 4-2に変更しただけです。

f:id:kazuhironagai77:20210524022432p:plain

以下に示した様に、DataTableだけ変更して他は全く同じ事を繰り返しています。

f:id:kazuhironagai77:20210524022450p:plain

これはもっと簡便な方法で実装出来るはずですが、今回は直しません。後で時間があるときに直します。
これでMonster Zone内で戦闘出来るはずです。テストしてみます。
戦闘のテストをするためにはMonsterの数を増やす必要があります。
一匹だけ足しました。

f:id:kazuhironagai77:20210524022509p:plain

これで試してみます。
Monsterが2体生成されています。一体だけ倒してみます。

f:id:kazuhironagai77:20210524022542p:plain

戦闘から戻って来ました。
Monsterは一体も生成されません。

f:id:kazuhironagai77:20210524022604p:plain

Monster Zone の以下の部分の設定がNoneになっていました。
直しました。

f:id:kazuhironagai77:20210524022627p:plain

もう一回テストします。

f:id:kazuhironagai77:20210524022645p:plain

今度はMonsterは一体だけ生成されました。
出来ました。
もう少しテストが必要ですが時間が無くなってしまいましたので今週はここまでとします。

10.魔法陣の改良

もう時間がないので今週は出来ません。
実際のPlay画面を見ると魔法陣が地面にめり込んで消えている部分があります。

f:id:kazuhironagai77:20210524022721p:plain

来週以降ですが、これも直します。

11.まとめと感想

今週は以下の事について勉強しました。

  • Niagaraの勉強をしました。
  • Sprite Renderer とMesh Rendererの違いについて
  • Light Rendererについて
  • 花火の作成について
  • Cascadeの勉強をしました。
  • Distributionsについて
  • Monster Zoneの作成をしました。
  • Monster Zone Classの構成
  • Monster Zone Actorの作成
  • 実際に作成したMonster Zoneのテスト

更にMonster Zoneの作成の途中で、Instance editableについて勘違いしていた部分が合った事にも気が付きました
来週は、

  • NiagaraCascadeの勉強の続き
  • Monster Zoneのテストの続き
  • Instance EditableとUE4C++おけるEditDefaultsOnly、EditInstanceOnly、とEditAnywhereの関係についての確認
  • Particle systemの勉強方法について
  • On Actor End Overlapから退散する時に戦闘中かそうでないかについての確認方法は、Monster Name in FightingがNoneでない事で確認した方が効率が良い件について
  • Monsterを倒した後で、DataTableの設定を変える時のコードの変更
  • 魔法陣の直し

などを行います。
多過ぎで直しきれない気がすでにしています。来週は直しだけでやる事にします。

12.参照(Reference)

[1] Codea Talk. (2012, July 23). Sprites vs Meshes. Codea. https://codea.io/talk/discussion/1378/sprites-vs-meshes
[2] Epic Games. (n.d.-c). Create a Sprite Particle Effect in Niagara. Unreal Engine Documentation. Retrieved May 23, 2021, from https://docs.unrealengine.com/en-US/RenderingAndGraphics/Niagara/HowTo/SpriteEffect/index.html
[3] Epic Games. (n.d.-a). Create a Mesh Particle Effect in Niagara. Unreal Engine Documentation. Retrieved May 23, 2021, from https://docs.unrealengine.com/en-US/RenderingAndGraphics/Niagara/HowTo/MeshEffect/index.html
[4] Epic Games. (n.d.-b). Create a Particle Light. Unreal Engine Documentation. Retrieved May 23, 2021, from https://docs.unrealengine.com/en-US/RenderingAndGraphics/Niagara/HowTo/ParticleLights/index.html
[5] Epic Games. (n.d.-d). Distributions. Unreal Engine Documentation. Retrieved May 23, 2021, from https://docs.unrealengine.com/en-US/Basics/Distributions/index.html