UE4の勉強記録

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

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 戦闘後のアイテム収得 Part 3

f:id:kazuhironagai77:20210801231212p:plain

<前文>

別にオリンピックを見て急に気が付いた訳ではないでしょうが、最近になって、ほとんどの日本人にも、日本って国が終りを迎えている事がはっきり認識出来る様になって来ました。

私は前々から思っていたので、はっきりと書きますが、日本人と日本文化は世界で最も優秀な部類に入ると思っています。

しかしそれと国の衰退は全く別な話です。

私はアメリカに10年も暮らしていたので、日本が終焉を迎える日が来るのは凄く前から感じていました。

そして悲しい事ですが、国の支えが無くなったら他国の人から日本人は奴隷のように扱われます。賃金を払わなくても誰からも文句を言われないから、僅かしか払われないでしょうし、暴力を振るっても逮捕される事もない訳ですから、暴行される事も度々起きるでしょう。

のでその解決策も同時にずっと考えていました。

これは、私にとっての解決策なので、ゲーム関連のProgrammerの人にしか参考にならないですが。そのアイデアの一端をここに記しておきます。

それは一個のゲームに対して一個の会社を作る事です。

今、ゲーム会社で一番割を食っているのはProgrammerです。アメリカの大学でCSを勉強している学生の間では「絶対にゲーム会社には就職するな」と言われていました。

その理由は単純で、ゲーム会社の給料が他の産業に比べて格段に低いのに長時間働かされるからです。

この状況はProgrammerに会社のStockの数十パーセントを分ける事で回避出来るはずです。一個のゲームに対して一個の会社ならそれが可能です。もしそのゲームが世界的なヒットを出せば、その会社の株価もとんでもない値段になります。更にProgrammerが自分で会社を興した場合は、そのゲームのIPはずっと自分で所有出来ます。

日本のゲーム会社はLoot Boxを採用する事でゲーム自体の収入を上げてその結果、Programmerの給料も高くするという戦略を取っているみたいですが、Loot Box自体がアメリカなどの西洋諸国では違法、もしくはほぼ違法と見られているため、本格的に海外進出する事は出来ません。

それに比べて私の「一個のゲームに対して一個の会社」戦略は、世界的な大ヒット作を制作しなければならないという制約が付きますが、ゲーム関連のProgrammerもとんでもない大金持ちになれます。

そしてここが大事ですが、とんでもなく大金持ちに成れる事が確実なら、世界的な大ヒット作だって作成出来ます。

日本の漫画は、アメリカのコミックより全然面白いです。

その理由は、日本の漫画家は大ヒット作品を描けば大金持ちに成れるからです。アメリカのコミックライターは給料制で、そのコミックが売れたからと言って大金持ちに成れるわけではありません。

今のゲーム会社のProgrammerも同じです。彼らの製作しているゲームが売れたからと言って、彼等は大金持ちには成れません。

その結果、頑張る質が変わってしまいます。

世界的な大ヒット作を制作するために頑張るのではなく、会社で出世するために頑張るようになってしまいます。

ゲームは漫画と違い、一人で作成する事は出来なくはないですがかなり大変です。最低でも5人くらいは必要でしょう。それ故に真のゲームの制作者は誰にも分からないです。だから会社にそのゲームを所有させてその会社の株でそのゲームの所有権の割合をはっきりさせるのです。

全体の5%しか株を貰えないなら、かんばりも5%位になります。20%も貰えるなら結構頑張るって良いゲームを作るかもしれません。

そしてここも大事ですが、お金を出すから株よこせと言うヤツは絶対に仲間にしない事です。面白いゲームを作れるのが保証されていれば、いくらでもファンからの寄付で制作費は集められます。労働以外の対価で株を得る事が分かったらみんなやる気をなくします。

更に、最近知ったのですが、株を売って得た収入はどんなに稼いでも最高で20%の税率にしかならないそうです。3億円とか稼いでも、給料だと半分持っていかれる訳です。それが株で稼いだ場合、2割で済むそうです。これは聞いた話でまだ自分では確認していないのですが配当金も税金は2割で済むらしいです。

ゲームの制作は最低でも2~4年はかかるでしょう。その間、ずっと少ない給料で我慢してやって来て、いざ大金が入るようになったら、全部税金で持っていかれるとなるとこれまたやる気をなくします。その問題も株で対価を払う事で回避できる訳です。

まあ、国が崩壊した後は、税金もどれだけの人が払うのか疑問ですが。イタリアなんかだと地方によっては経済の半分位はアングラらしいですし。

そう言えば、突然思い出したんですが、昔私、VRで酔う理由の一つ、しかも大きな理由の一つがFPS以外にある事を発見しました。それは画面の旋回方法についてなんですが、同時に、私がそれを実装出来たとしても、私に入るお金は0と言う事も気が付きました。結局やらなかったです。そしたらとうとうVR産業自体が無くなってしまいました。

勿論、VR産業が崩壊した理由は色々あるでしょうが、VRを使用すると悪酔いするのはもっとも大きな理由でしょう。それに対する解決策を提示しても大金持ちに成れないんじゃ、やる気は全く起きません。

こういうやる気の問題も一個のゲームに対して一個の会社にしてStockの数十パーセントを分ける事で回避できます。

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

<本文>

1.今週の予定

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

  • Niagaraの勉強としてCGHOW氏のUnreal Engine Niagara Tutorials [1]のどれかを勉強する。
  • Cascadeの勉強の続き、もしくは英語で書かれたUE4Effectについての本を読む
  • 戦闘後のアイテムの入手の作成の続き
  • Warp Passの作成
  • Good Skyの検証

2. Niagaraの勉強としてCGHOW氏のUnreal Engine Niagara Tutorials [1]のどれかを勉強する。

無難に一番最初のヤツをやります。

2.1 Unreal Engine Niagara Cloud Tutorial | Download Project Files [2] を勉強する

T_Smoke_SubUVを使用するそうです。

f:id:kazuhironagai77:20210801231339p:plain

またSmoke関連か。と思いましたがCGHOW氏のTutorialは初めてなので、それも良いかもしれません。

Niagara Emitter とNiagara Systemを作成しました。

f:id:kazuhironagai77:20210801231354p:plain

が、今の形式と違います。

Emitterで、どのTemplateを選んだのかが分かりません。

Tutorialの映像を見ると

f:id:kazuhironagai77:20210801231416p:plain

Particleが飛んでいるので何かしらのTemplateが選択されたと思われますが、以下に示した様にSystem Overviewが表示されていないのでどんな設定なのか良く分かりません。

f:id:kazuhironagai77:20210801231433p:plain

今のNiagara Systemとかなり違います。

Mar 2, 2019に制作されたとあるので、たった2年前です。2年の間に、Niagara Systemの形式がこんなに進化しているなんてびっくりしました。

取りあえずこの部分はスキップしてMaterialの作成を先にします。

Materialは以下のように作成しました。名前はM_Smokeとしました。

f:id:kazuhironagai77:20210801231449p:plain

これ以上ない位シンプルなMaterialですね。

Depth Fadeノードは使用していませんね。

後、MaterialのBlend Modeの設定をTranslucentにする時、

f:id:kazuhironagai77:20210801231502p:plain

「HoudiniとUnreal Engine 4で学ぶリアルタイムVFX」で半透明にするとどうしてコストが余計にかかるのかの説明図が、ブアッと頭の中に浮かんできて「こんなにコストがかかるのに本当に半透明にする必要があるの?」と心の中で問いかけて来ました。

「HoudiniとUnreal Engine 4で学ぶリアルタイムVFX」を見返したんですが、この本には検索機能がついていません。

f:id:kazuhironagai77:20210801231515p:plain

どこに書かれているのか見つかりませんでした。

普通は検索機能がついているんですが、何が違うんでしょうね。

f:id:kazuhironagai77:20210801231529p:plain

先週、気がついていたらこの本に対する不満点にこの事を追加していました。

Tutorialに戻りますが、Emitter Systemの説明をしていますが、一向にSystem Overviewは表示されません。

Tutorial ではEmitter SystemのModule内のParameterについての説明をしてます。

仕方がない。EmitterのTemplateは適当に選んで、この説明で表示されているModuleと同じModuleを追加します。

一番、見た目が似ているFountain Templateを選択します。

f:id:kazuhironagai77:20210801231543p:plain

TutorialのEmitter Systemですが、

f:id:kazuhironagai77:20210801231556p:plain

<Emitter Spawn

Emitter Spawn Category内にEmitter Properties Moduleがあります。見た事ないModuleです。

<Emitter Update

Emitter Update Category内にはEmitter Life Cycle ModuleとSpawn Rate Moduleが表示されています。Emitter Life Cycle Moduleも見た事ありません。

多分Spawn Rate Module以外は別のModuleに進化したんだと思いますが、一応調べて見ましょう。

f:id:kazuhironagai77:20210801231642p:plain

やっぱりありませんね。

どのTutorialで学んだのか忘れてしまったのですが、Emitter Spawn Categoryは基本的にはノータッチで良いと書かれていた気がします。これって結構初心者には大切な情報だと思うんですが。

ひょっとしてCGHOW氏って結構投げっぱなしな人なのかもしれません。

普通、Tutorialを作成している人ならこれだけ変更されたら新しいTutorialを作り直すと思うんですが。

Emitter Update Category内のModuleも見てみましょう。

やはりEmitter Life Cycle Moduleはありませんでした。

ただしこっちのModuleはParameterを見てみると

f:id:kazuhironagai77:20210801231658p:plain

Emitter State Moduleと同じような事をしてそうです。

f:id:kazuhironagai77:20210801231712p:plain

Emitter Life Cycle ModuleのNext Loop DurationとEmitter State ModuleのLoop Durationは何となく同じParameterのような気がします。

その他のParameterのある程度は一致しそうです。

Emitter Life Cycle ModuleはEmitter State Moduleに進化したと仮定して先を見てみましょう。

<Particle Spawn

TutorialのParticle Spawn Categoryです。

f:id:kazuhironagai77:20210801231731p:plain

Fountain Templateの方は以下のModuleを使用してます。

f:id:kazuhironagai77:20210801231751p:plain

こっちはパッと見には結構似ています。Add Velocity ModuleとAdd Velocity Cone、Sphere Location ModuleとSphere Location Module、そしてSet Variables ModuleとInitialize Particle Moduleです。

最初に最も似ていないSet Variables ModuleとInitialize Particle Moduleを比べてみます。

Set Variables Moduleには3つのParameterがあります。

f:id:kazuhironagai77:20210801231805p:plain

Initialize Particle ModuleにはParticle Lifetimeによく似たParameter、Lifetime Modeがあります。

f:id:kazuhironagai77:20210801231819p:plain

Initialize Particle ModuleのNiagara Module Scriptを表示すると、Lifetime MinとLifetime Maxの値をParticle Lifetimeにセットしています。

f:id:kazuhironagai77:20210801231833p:plain

ただ、Input Lifetimeが何を表しているのか不明です。

f:id:kazuhironagai77:20210801231846p:plain

その後ろのノードを見たら分かりました。Input LifetimeはLifetimeのModeがRandomでなく直接値を入力する時に使用します。

他のParameterはどうでしょう。

Sprite Rotationを調べて見ます。

まずSprite RotationというParameterが存在するのかを調べます。

f:id:kazuhironagai77:20210801231859p:plain

ありますね。

ではInitialize Particle Module内でSprite Rotationの値を指定してるのか調べます。

Sprite Rotation ModeというParameterがSprite Attributes内にあります。

f:id:kazuhironagai77:20210801231912p:plain

これがSprite Rotationの値を指定していそうです。

Initialize Particle ModuleのNiagara Module Scriptを開いてSprite Rotationの値がどうやって決定されているのか調べて見ましょう。

ありました。しかも3つもありました。

f:id:kazuhironagai77:20210801231925p:plain

その次のノードを見るとSprite Rotation ModeがRandomの場合は二番目の実装が実行されるとあります。

f:id:kazuhironagai77:20210801231937p:plain

このStatic Switchノードみたいな繋ぎ方をするノードって他にもあるんでしょうか?

右から左に戻って読まなければならない結構不思議なノードですよね。

Randomの場合を遡ってノードを追っていきます。

f:id:kazuhironagai77:20210801231950p:plain

あれ、Sprite Rotation Angle MinとSprite Rotation Angle Maxの値を入力しています。後、これらのParameterの左側にある数字ですが、Default値でしょう。

Emitter Systemに戻ってInitialize Particle ModuleのSprite Rotation Modeを見たらSprite Rotation Angle MinとSprite Rotation Angle Maxはありました。隠れていただけでした。

f:id:kazuhironagai77:20210801232003p:plain

0と360がDefault値として指定されていますね。

最後のParameterであるSprite Sizeを調べます。

これですね。

f:id:kazuhironagai77:20210801232024p:plain

Initialize Particle Module 内でSpriteSizeの値を指定してそうな所と言えばこれしかありません。

f:id:kazuhironagai77:20210801232038p:plain

Initialize Particle ModuleのNiagara Module Scriptを開いて調べて見ましょう。

はい。ありました。

何となくですがNiagara Module Scriptの見方が分かって来ました。

f:id:kazuhironagai77:20210801232054p:plain

Sprite Size ModeでRandom Uniformを選択した場合の実装を追っていきます。

f:id:kazuhironagai77:20210801232108p:plain

はい。ParameterであるSpriteSizeにUniform Sprite Size MinとUniform Sprite Maxで指定された値からうにゅうにゅして出て来た値をセットしています。

あれ。

Initialize Particle Module 内でUniform Sprite Size MinとUniform Sprite Size Maxの値を以下の様にセットしましたが、

f:id:kazuhironagai77:20210801232121p:plain

Niagara Module ScriptではDefault値は5.0と10.0になっていますね。

f:id:kazuhironagai77:20210801232134p:plain

これはInputされた値が無い場合は、5.0と10.0がDefault値になると言う事なのでしょうか?

ちょっと分かりませんね。

細かい点ではまだまだ分からない事が沢山ありますが、Tutorialで使用しているSet Variables ModuleとFountain Templateで使用されているInitialize Particle Moduleはほぼ同じ事をしている事が分かりました。

因みに、Initialize Particle Moduleではその他に

f:id:kazuhironagai77:20210801232147p:plain

f:id:kazuhironagai77:20210801232154p:plain

f:id:kazuhironagai77:20210801232159p:plain

f:id:kazuhironagai77:20210801232205p:plain

f:id:kazuhironagai77:20210801232211p:plain

f:id:kazuhironagai77:20210801232216p:plain

のParameterの値も指定していました。

次にAdd Velocity ModuleとAdd Velocity Cone Moduleですが、この二つのModuleはParticleの初期速度を設定しているだけでしょう。

Particle Spawn CategoryのVelocityの項目を見るとAdd VelocityとAdd Velocity Coneがありますし。

f:id:kazuhironagai77:20210801232231p:plain

そうだ。公式のDocumentを見てみましょう。Particle Spawn Group [3]を見るとVelocity Modulesについての項目があります。

ここの解説を見ると

f:id:kazuhironagai77:20210801232252p:plain

f:id:kazuhironagai77:20210801232257p:plain

となっています。Parameter, Velocityに値をセットするのはAdd Velocity In Cone Moduleだけなの?Add Velocity ModuleだってParameter, Velocityに値をセットしそうですが。

それだけ調べて見ます。

Add Velocity Moduleを追加して

f:id:kazuhironagai77:20210801232323p:plain

Add VelocityのNiagara Module Scriptを開きます。

はい。

Add Velocity ModuleもParameter, Velocityに値をセットしています。

f:id:kazuhironagai77:20210801232337p:plain

Add Velocity ModuleのNiagara Module Scriptの全体像です。

f:id:kazuhironagai77:20210801232350p:plain

あれ。これだけ。これなら私でも理解出来そうです。ちょっと読んでみましょう。

2.2 Add Velocity ModuleNiagara Module Scriptを読む

f:id:kazuhironagai77:20210801232408p:plain

InputであるVelocityとScale Added Velocityを掛けています。Add Velocity ModuleにScale Added Velocity なんでParameterあったけな?と思ったら。

f:id:kazuhironagai77:20210801232423p:plain

ありました。

確かDistributionの勉強をした時にScale何とかと言うParameterがあって、その機能は単純に値を掛けているだけ。と結論づけた時がありました。それと同じ機能ですね。

次にTransform Vectorノードに繋がっています。

f:id:kazuhironagai77:20210801232449p:plain

Transform Vectorノードは先程のVelocityの値だけでなくSource SpaceというParameterからも値を受け取っています。

このSource Spaceの値は

f:id:kazuhironagai77:20210801232502p:plain

から来ています。

Add Velocity ModuleのCoordinate Spaceをみると

f:id:kazuhironagai77:20210801232515p:plain

となっていてCoordinate Spaceの値は数字じゃないです。

となるとこのTransform Vectorノード内でSource SpaceがLocalの時は○○の値を追加。みたいな事をやっているはずです。

f:id:kazuhironagai77:20210801232528p:plain

クリックしたらTransform Vectorノードの中身が見れました。

f:id:kazuhironagai77:20210801232545p:plain

これです。このSource SpaceノードからLocalはパスされてNF Transform Baseノード内である値に変換されています。

ただここまで深く潜ってしまうと正直何をやっているのかさっぱり分かりません。

今回は実際のコードを見るのはTransform VectorノードまでとしてTransform Vectorノードに表示されている情報からSource Spaceの役割を推測する事にします。

Source Spaceが取り得る値は、World、Local、そしてSimulationだけです。と言う事はWorld Coordinateの時は、VelocityにParticleの位置を足す必要があります。Local CoordinateならばParticleの位置は0になるので何も足す必要はありません。

はい。

Transform Vectorノードは、これをやっているんじゃないでしょうか?

次のノードです。Aには先程、Transform Vectorノードで計算した値が入っています。

f:id:kazuhironagai77:20210801232601p:plain

Bですが、なんとParameter、Velocityそのものの値が来ています。

f:id:kazuhironagai77:20210801232628p:plain

あれ、Parameter、Velocityの値を決めるためのModuleなのに何でParameter、Velocityの値が前から存在しているの?

と思ったんですが、このAdd Velocity Module、次のParticle Update Categoryからも呼び出せるはずです。その場合は前のVelocityを足す必要があるはずです。

最後に計算された値をParameter、VelocityにセットしてOut Putします。

f:id:kazuhironagai77:20210801232641p:plain

これがAdd Velocity Moduleの仕組みでした。

2.3 Unreal Engine Niagara Cloud Tutorial | Download Project Files [2] をもう一度勉強する

Add Velocity ModuleとAdd Velocity Cone Moduleに戻りますが、取りあえずはどっちでも良いかなと思っています。後で変更します。

Particle Spawn Categoryの最後のModuleであるSphere Location ですがこれは同じModuleを使用しています。

<Particle Update

Particle Update Categoryを見て行きます。

こちらがTutorialのParticle Update Categoryです。

f:id:kazuhironagai77:20210801232704p:plain

こっちがFountain TemplateのParticle Update Categoryです。

f:id:kazuhironagai77:20210801232718p:plain

した二つのModule、Solve Forces and VelocityとColor(Scale Color)は同じ、もしくはほぼ同じでしょう。

Gravity Force ModuleとAcceleration Force ModuleもAcceleration Force Moduleが重力の計算をしている限り同じ機能でしょう。

Drag Moduleは空気抵抗の計算をしているんだと推測されます。

となると残りはUpdate Age ModuleとParticle State Moduleです。

現在のVersionのNiagaraにはUpdate Age Moduleは存在しません。

f:id:kazuhironagai77:20210801232734p:plain

TutorialでもUpdate Age Moduleが何を担当しているのかの説明は全くないのでこれ以上の推測は出来ません。

のでUpdate Age Moduleが進化したのがParticle State Moduleであると仮定して次へ行きます。

<Render

TutorialでRenderに使用されているModuleはSprite Rendererとほぼ同じModuleのようです。

Tutorialの説明に沿って使用するMaterialを先程、作成したSub UVのヤツに変更します。

f:id:kazuhironagai77:20210801232752p:plain

設定もSub UV用に変更します。

f:id:kazuhironagai77:20210801232804p:plain

あれ。

f:id:kazuhironagai77:20210801232817p:plain

何かオカシイです。

Materialのalphaの代わりにRGBAを繋げていました。

直しました。

f:id:kazuhironagai77:20210801232830p:plain

イメージも正しくなりました。

f:id:kazuhironagai77:20210801232844p:plain

Aminationを追加します。

その前にPreview の設定を変更します。

f:id:kazuhironagai77:20210801232856p:plain

こんな感じに変更しました。

これは見やすいです。この方法は覚えておきましょう。

まずWindowからPreview Scene Settingsを選択します。

f:id:kazuhironagai77:20210801232918p:plain

するとSelectionの隣にPreview Scene Settingsが表示されます。

Show Environmentのcheckを外し、Environment Colorに黒をセットします。

f:id:kazuhironagai77:20210801232939p:plain

以上です。

後、Tutorialでは、煙の動きを変えるためにVelocityの値やAcceleration Forceの値を弄りました。これらは本質的な事ではないのでスキップします。

<Animationの表示>

TutorialではSub Image Index Moduleを追加してAnimationを表示しています。

f:id:kazuhironagai77:20210801232957p:plain

こんな感じです。

f:id:kazuhironagai77:20210801233010p:plain

む。これって確か2021-07-18のブログでやった方法で作成出来たはずです。

Particle Update CategoryにSet new or existing parameter directly Moduleを追加します。

f:id:kazuhironagai77:20210801233024p:plain

追加するparameterにSub Image Indexを選びます。

f:id:kazuhironagai77:20210801233038p:plain

はい。

Tutorialと同じになりました。

f:id:kazuhironagai77:20210801233051p:plain

2021-07-18のブログでやった時はSet new or existing parameter directly ModuleはParticle Spawn Categoryに追加しました。今回はParticle Update Categoryです。

これだとアニメーションも自動で更新され続けるんでしょうか?

Sub Image Indexの値の設定方法をFloat from Curveに変更します。

f:id:kazuhironagai77:20210801233105p:plain

0の値を0、1の値を64にセットします。

f:id:kazuhironagai77:20210801233120p:plain

64個だから0から63だと思うんですがどうなんでしょう?

問題が起きたらTutorialの先の方で直すはずなのでこのままで行きます。

Animationが発動している事を確認します。

f:id:kazuhironagai77:20210801233424g:plain

出来てますね。

<Cylinder Locationの追加>

Sphere Location Moduleを外してCylinder Locationを追加します。更にサイズを以下の様に横に広く高さが無いようにします。

f:id:kazuhironagai77:20210801233459p:plain

Spawn Rateを1000に変更します。

f:id:kazuhironagai77:20210801233512p:plain

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

f:id:kazuhironagai77:20210801233524p:plain

もう大体理解しました。

このCylinder Location Moduleの設定を横に広く高さが無いようにすれば霧が満ちている世界を作成出来るんです。分かりました。

f:id:kazuhironagai77:20210801233541p:plain

ちょっと発生する煙が沢山重なった時の挙動に納得できないので色々弄って見ました。

f:id:kazuhironagai77:20210801233555p:plain

こんな感じです。

正直、これだけ分かれば十分です。

後、Niagaraを勉強する時間も無くなって来ましたのでTutorialの残りは来週やる事にします。

3. Cascadeの勉強の続き、もしくは英語で書かれたUE4Effectについての本を読む

先週「HoudiniとUnreal Engine 4で学ぶリアルタイムVFX」を読んでこんな凄い本あるのかと驚いたんですが、英語の本でも同じ位凄い本があるんじゃないかと思ってアマゾンUSAで探したんですが見つからなかったです。

と言うか、UE4を学ぶ事に対する熱量が全く感じられませんでした。

これと同じ雰囲気を前に感じたのがRuby on Railsです。

Ruby が持っていた市場は一気にPythonに奪われました。Python原理主義者たちは、Rubyの息の根が止まるまで追撃の手を緩めませんでした。これが機械学習とか、科学計算に関してならPython原理主義者の言う事もそれなりに納得出来ますが、Back end用の言語としてRuby on railsが特別Pythonに劣ってるとは、私には全然思えませんでした。

ただWeb関連のProgrammingは、私はちょっと齧った程度なので専門家ではありませんから、Pythonの信者達からそう言われたら黙るしかありません。

ちょっと小耳に挟んだだけなのでどれだけ本当なのかは不明ですが、カナダのある都市ではUnityに対する求人広告3000件に対してUE4は1~5件だそうです。

UE4が第二のRuby on Railsとして一気に市場から消えるかどうかは神ならぬ私が知る由もないですが、そういう可能性は結構ありそうです。

そういうわけで、UE4VFX関連の洋書を読む計画は一端中止にして、Cascadeの勉強をします。

3.1 Cascade 応用編

CascadeにしてもNiagaraにしても一応基礎は理解したので応用としてゲームに使用するEffectの作成を勉強しようと思います。

ゲームで作成するEffectについて思いつくまま書いて行くと

魔法関連

  • 魔法陣
  • 爆発
  • 回復
  • 状態異常や呪い

でしょうか。

この中で炎、煙、雷、魔法陣については一応、一回以上は作成した記憶があります。氷や水のEffectはあまり見た記憶がありません。

<氷のEffect

氷のEffectについて調べて見ました。

Particle Systemで作成しているのか不明ですが以下のAssetは段違いで本物そっくりです。

f:id:kazuhironagai77:20210801233658p:plain

こっちはNiagaraですがCGHOW氏が作成したIce Effectです。(Ice Hit Effect | Unreal Engine Niagara Tutorial [4] より)

f:id:kazuhironagai77:20210801233714p:plain

圧巻の一言です。やっぱりCGHOW氏のEffectは凄いです。

別な動画を見ていたら、先程、紹介したAsset、Ice Coolは2019年の9月にFreeで配布されているとありました。

えっ。

調べたら持っていました。

f:id:kazuhironagai77:20210801233734p:plain

それではこのAssetをもっとよく見てみます。

3.2 Ice Coolの調査

デモ画面を開きます。

f:id:kazuhironagai77:20210801233753p:plain

凄い。これが作成出来れば氷のエフェクトとしては完璧でしょう。

f:id:kazuhironagai77:20210801233806p:plain

これで十分でしょう。

元になっているMaterialを見ましたがチンプンカンプンです。

f:id:kazuhironagai77:20210801233820p:plain

Effectは付いていませんでした。

氷のEffectを作成するには、このMaterialを使用したMeshをMesh Renderingで表示して使用する事になりそうです。

以上です。

3.3 Cascade 応用編の続き

水のEffectも探してみます。

<水のEffect

いきなり凄いのを見つけました。

f:id:kazuhironagai77:20210801233841p:plain

と思ったらこれもCGHOW氏のTutorialでした。名前はStylized Water Splash | UE4 Niagara Water Splash | Download Project Files [5] です。勿論、Niagaraを使用しています。

後は、4.26から付属になったWater Simulationの使用方法です。

f:id:kazuhironagai77:20210801233910p:plain

これはParticle Systemではないんで今回はパスします。

そう言えばWater Simulationではなく4.24で使用しているUIWS(Unified Interactive Water System)の方にEffectが何個かあった気がします。見てみます。

f:id:kazuhironagai77:20210801233924p:plain

f:id:kazuhironagai77:20210801233931p:plain

f:id:kazuhironagai77:20210801233940p:plain

他のも大体同じ感じです。

Particle Systemをみると

f:id:kazuhironagai77:20210801233956p:plain

Mesh Dataを使用しています。

水のEffectもこれを使用すれば作成出来そうです。

<雪のEffect

雪のEffectについてです。

そうだ思い出しました。

Particle Effectsという色んなEffectを紹介したProjectがあったんです。

f:id:kazuhironagai77:20210801234018p:plain

その中に確か雪があったはずです。

見てみます。

f:id:kazuhironagai77:20210801234033p:plain

空を舞う雪の粒はP_Blizzerdと言うEffectで作成されていました。

f:id:kazuhironagai77:20210801234049p:plain

ところがこのEffect、Viewportでは全く雪の粒が表示されていません。

f:id:kazuhironagai77:20210801234122p:plain

何か私がまだ知らない仕組みがあるみたいです。

Particle Effectsには、水のEffectがありました。

f:id:kazuhironagai77:20210801234137p:plain

P_WaterFall_Mist_Lightと言う名前のEffectでした。

f:id:kazuhironagai77:20210801234154p:plain

これだけ見ると簡単そうですが、使用されているMaterialを見ると

f:id:kazuhironagai77:20210801234212p:plain

こんな感じでとても一筋縄で理解出来るとは思えません。

雪のEffectですが、YouTubeに一杯ありました。こっちを先に勉強します。

f:id:kazuhironagai77:20210801234227p:plain

<砂のEffect

砂のEffect のTutorialもYouTubeに結構ありました。

f:id:kazuhironagai77:20210801234250p:plain

<風のEffect

まずYouTubeにそのものずばりのTutorialがありました。

f:id:kazuhironagai77:20210801234308p:plain

Niagaraですが他にも風のTutorialがあります。

f:id:kazuhironagai77:20210801234324p:plain

GameDev Outpost氏のTutorialは雪が風で舞う様子を作成するためのTutorialみたいですね。

もう一人のRimaye氏は聞いた事がありません。ちょっと動画を見て確認して見ます。

f:id:kazuhironagai77:20210801234628p:plain

英語じゃなかった。一応、言葉が分からなくても理解出来るように頑張って作成したと有りますが…。

<爆発のeffect

光や闇はまあいいです。雷とほぼ同じでしょうから。

爆発のEffectを調査します。

f:id:kazuhironagai77:20210801234651p:plain

またRimaye氏の動画が出て来ました。

フランス語なんてマジでParlez-vous français ?しか知らないレベルなのに、どうしろと言うんでしょうか?

f:id:kazuhironagai77:20210801234711p:plain

しかしEffectはマジで凄い。

Cascadeで作成しているTutorialも一個見つけました。

f:id:kazuhironagai77:20210801234725p:plain

ちょろっとだけ見ましたがこれも凄いです。

ただしこのTutorial、一時間もあります。これ勉強したら終わるのに一カ月かかる可能性が…。

<回復のEffect

回復系のEffectも調べます。Healing Effectで調べました。

f:id:kazuhironagai77:20210801234748p:plain

これはCascadeで結構簡単そうです。

3.4 Cascade 応用編を勉強する目的についての確認

Cascadeと言うかParticle Effectの基礎であるSpriteやMesh、Ribbon、そしてBeamなどの仕組みは一応理解しました。その基礎的な技術をどう使って具体的なEffect、例えば炎などを制作するのかを明らかにするのが、Cascade 応用編を勉強する目的です。

例えば煙のEffectを作成するために、Sprite + Sub UVを使用するみたいな事を理解するのが目的です。

3.5 炎のEffectの復習

そういうわけで今回は炎のEffectの復習をします。

TutorialはUnreal 4 Particles Tutorial - Simple Flame, Embers, Smoke. [6]を選びました。

最初に当然ですがParticle Systemを作成します。名前はFrame Touchです。

f:id:kazuhironagai77:20210801234811p:plain

MaterialをM_Fire_SubUVに変更します。

f:id:kazuhironagai77:20210801234824p:plain

ここでもSub UVを使用するのか。Sub UVって滅茶苦茶基本のTechniqueなのね。

Sub UVは以下の設定に変更しました。

f:id:kazuhironagai77:20210801234842p:plain

Interpolation MethodでLiner Blendを選択しました。これはImageが単純に1から2に移るのではなくその間のImageも1と2のImageをBlendするMethodだそうです。

これだけではSub UVのImageはずっと0番しか選択されないのでAnimationになりません。

Sub Image Indexを追加します。

f:id:kazuhironagai77:20210801234924p:plain

Sub Image Indexの値は以下の様に設定します。

f:id:kazuhironagai77:20210801234938p:plain

f:id:kazuhironagai77:20210801234945p:plain

M_Fire_SubUVのImageは36個なので0の時に0、1の時に35をセットします。

f:id:kazuhironagai77:20210801234959p:plain

上のNiagaraのTutorialでは64個imageがある時に

1の時に64をセットしていますが、このTutorialの作者であるGame Dev Society BU氏はきちんと63にセットしていました。

と思ったらこの人も、Tutorialによって1の値が違うけど35であっているはず。と言っていました。

後、もし入力する値が2つ以上ある場合は、Curve Editorを使用して入力した方が分かり易いです。

f:id:kazuhironagai77:20210801235031p:plain

これはGame Dev Society BU氏は述べていませんでした。

以下の様なImageに変化しました。

f:id:kazuhironagai77:20210801235049p:plain

上昇が速過ぎてAnimationがきちんと動いているのか分かりませんね。

根元に注目すると常に同じimageが同じ個所から発生していて不自然に見えます。

f:id:kazuhironagai77:20210801235103p:plain

Rotationを追加する事でこれを直します。

Initial Rotationを追加します。

f:id:kazuhironagai77:20210801235116p:plain

Initial Rotation内のParameterは以下のような設定になっています。

f:id:kazuhironagai77:20210801235128p:plain

ここのMaxの値が1と言うのは360度の事だそうです。ので値自体は弄る必要はないです。

結果、Imageが以下の様になりました。

f:id:kazuhironagai77:20210801235143p:plain

今度は色をつけます。

Particle Systemに元からあるColor Over Life Moduleの値を変更します。

f:id:kazuhironagai77:20210801235156p:plain

以下の値にしました。

f:id:kazuhironagai77:20210801235210p:plain

流石に色の変更はDetail画面でやった方が分かり易いですね。

後、色の値で1以上が入れられるのは、以下に示したようにMaterialでEmissive Colorに繋がっているからだそうです。

f:id:kazuhironagai77:20210801235223p:plain

はい。これは初めて知りました。

結果です。

f:id:kazuhironagai77:20210801235236p:plain

完全な炎になりました。

今度はInitial Size Moduleの値を弄ります。

f:id:kazuhironagai77:20210801235248p:plain

こんな感じに値を変更しました。

f:id:kazuhironagai77:20210801235302p:plain

その結果です。

f:id:kazuhironagai77:20210801235314p:plain

微調整と言う感じです。

今度はParticleの存在している間中のサイズを指定します。

f:id:kazuhironagai77:20210801235326p:plain

Particleの最初のサイズを0.4倍にしました。

f:id:kazuhironagai77:20210801235339p:plain

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

f:id:kazuhironagai77:20210801235353p:plain

この辺の微調整が実際のゲームをPlayするに当たってどれくらいPlayerの満足度に影響するのか知りたいですね。

次に炎の広がりを修正します。

今回作成する炎はまっすぐに伸びる炎なので炎の広がりを直します。

修正するModuleはInitial Velocityです。

f:id:kazuhironagai77:20210801235408p:plain

x、y方向への初速度を0に変更しました。

f:id:kazuhironagai77:20210801235421p:plain

結果です。

f:id:kazuhironagai77:20210801235434p:plain

こんどはLife Timeの調節をします。

f:id:kazuhironagai77:20210801235447p:plain

ちょっとだけMinを小さくしました。

f:id:kazuhironagai77:20210801235527p:plain

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

f:id:kazuhironagai77:20210801235546p:plain

今度はEmberの作成です。Flicking OFFって言っているので燃えカスから飛び出して舞っている燃えカスの粒でも作るのでしょう。

燃えカス用のEmitterを追加しました。

f:id:kazuhironagai77:20210801235559p:plain

それぞれのEmitterの名前が同じなので変更します。

f:id:kazuhironagai77:20210801235612p:plain

EmbersのMaterialにM_Radial_Gradientをセットします。

f:id:kazuhironagai77:20210801235625p:plain

更にInitial Size Moduleから

f:id:kazuhironagai77:20210801235637p:plain

Particleのサイズを以下の様に変更します。

f:id:kazuhironagai77:20210801235649p:plain

以下の様になりました。

f:id:kazuhironagai77:20210801235710p:plain

今度はEmbersに色を追加します。

f:id:kazuhironagai77:20210801235730p:plain

Frameと同じ値を追加します。

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

f:id:kazuhironagai77:20210801235747p:plain

今度はInitial Velocityを変更します。

f:id:kazuhironagai77:20210801235800p:plain

EmberはFrameと違って横に広がります。ので

f:id:kazuhironagai77:20210801235814p:plain

としました。

その結果、

f:id:kazuhironagai77:20210801235827p:plain

と成りました。

Frameと合成して見るとEmberが横に飛び散り過ぎです。

f:id:kazuhironagai77:20210801235842p:plain

EmbersのInitial Velocityの値を以下の様に微調整しました。

f:id:kazuhironagai77:20210801235906p:plain

結果です。

f:id:kazuhironagai77:20210801235919p:plain

少しはマシになりました。

はい。

Tutorialではこんな微調整を丁寧にやっていますが、これがどの程度大切なのか知りたいです。一人でGame作ったらこんな細かい点まで調整している時間も労力もありません。

Emberの数が多いので調節します。

f:id:kazuhironagai77:20210801235933p:plain

Spawn Rateの値を10に変更しました。

f:id:kazuhironagai77:20210801235949p:plain

こんな感じです。

f:id:kazuhironagai77:20210802000003p:plain

EmberはFrameの上にもよく舞っています。それを再現します。

Emberの寿命をFrameより長くします。

f:id:kazuhironagai77:20210802000022p:plain

f:id:kazuhironagai77:20210802000027p:plain

その結果です。

f:id:kazuhironagai77:20210802000041p:plain

Screen Shootでは見にくいですが、Emberが確かにFrameの上を舞っています。

いや、正確に言うと飛んでいます。舞ってはいません。

それではEmberが舞うようにします。

Module、Orbitを追加します。

f:id:kazuhironagai77:20210802000055p:plain

初めて使うModuleです。

公式のDocumentであるOrbit Modules [7]では

f:id:kazuhironagai77:20210802000109p:plain

と解説されています。

Orbit ModuleのOffset Amountの値を以下の様に変更しました。

f:id:kazuhironagai77:20210802000126p:plain

公式のDocumentであるOrbit Modules [7]によるとOffset Amountは以下のような機能を司るそうです。

f:id:kazuhironagai77:20210802000139p:plain

以下の様になりました。

f:id:kazuhironagai77:20210802000153p:plain

値を変更する前を覚えていません。しかしEmberの回転がおとなしくなった気がします。

最後に煙を追加します。

煙用のEmitterを追加します。

f:id:kazuhironagai77:20210802000206p:plain

名前をSmokeに変更します。

f:id:kazuhironagai77:20210802000218p:plain

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

f:id:kazuhironagai77:20210802000231p:plain

いつもの煙用のMaterialですね。

Sub UVの値を以下の様に変更しました。

f:id:kazuhironagai77:20210802000245p:plain

Interpolation MethodがNoneのままですが大丈夫なんでしょうか?

取りあえずはこのままでやって行きます。

煙のAnimationを表示するためにSub Image Indexを追加します。

f:id:kazuhironagai77:20210802000323p:plain

値は以下の様にしました。

f:id:kazuhironagai77:20210802000345p:plain

1には64ではなく63をセットしました。

Curve Editorは以下のようになっています。

f:id:kazuhironagai77:20210802000400p:plain

こんな感じです。

f:id:kazuhironagai77:20210802000414p:plain

正直、煙にAnimationが追加されたかどうか以前に、煙自体が見えません。

今度は煙にFrameと同じような動きにするためにRotation を追加します。

結果です。Viewportからだと煙が全く見えないのでLevel上に配置しました。

f:id:kazuhironagai77:20210802000440p:plain

煙が凄いです。

この炎の煙にはおかしな点が幾つかあります。一つ目は煙が底から発生している点です。

それを直します。

Required ModuleのEmitter OriginのZの値を30に変更します。

f:id:kazuhironagai77:20210802000504p:plain

結果です。

f:id:kazuhironagai77:20210802000519p:plain

大分、本物の炎に見えて来ました。

煙が多すぎるので量を減らします。Spawn Rateを20から5に変更しました。

f:id:kazuhironagai77:20210802000533p:plain

こんな感じです。

f:id:kazuhironagai77:20210802000546p:plain

うーん。どうなんでしょう。煙が少し薄過ぎる気がしますが。

煙のColor Over Life Moduleの値を弄る事で直すみたいです。

f:id:kazuhironagai77:20210802000600p:plain

はい。

f:id:kazuhironagai77:20210802000613p:plain

暗くしました。

結果です。

f:id:kazuhironagai77:20210802000626p:plain

色々位置を変えてScreenshotを取ったのですが、上手く取れませんでした。確かに煙が黒くなって存在感が増しています。

Tutorialの説明によると今度は、煙が突然、無から現れるように見えて不自然なのでそれを直すそうです。

私にはよく分かりません。少なくとも私の煙はそんなに不自然な感じはしません。が一応Tutorialの通りにやっておきます。

Color Over Life Moduleのalpha値を調節します。

f:id:kazuhironagai77:20210802000639p:plain

最初は完全な透明です。そこから段々、不透明になって行きます。半分まで来ると80%位不透明になります。その後また透明になり最後は完全な透明に成ります。

グラフも載せておきます。

f:id:kazuhironagai77:20210802000653p:plain

こんな感じです。

それでは結果を見てみましょう。

f:id:kazuhironagai77:20210802000716p:plain

うーん。確かに本物の炎に見えます。

一応、これで炎のEffectの作成方法を理解しました。

4. 戦闘後のアイテムの入手:今までの復習

先週どこまで終わらしたのか覚えていません。

ので先週まで何をしたのかの復習を最初にします。

4.1 2021-07-25のブログの復習

<石像との会話用のBGI

まず、それぞれの石像に話しかけた時に、表示されるBGIを作成しました。

f:id:kazuhironagai77:20210802000752p:plain

こういうヤツです。

今、見直したら9個、全部描いてありました。結構頑張ったんですね。

閉じるボタンについてコメントが書かれていました。

f:id:kazuhironagai77:20210802000806p:plain

閉じるボタンの実装は以下のようになっているがどんな時もきちんと作動するのか不安と書かれています。

f:id:kazuhironagai77:20210802000821p:plain

これは調べて確認します。

<石像からの報酬用のWidget

その次にしたのは石像との会話の後に表示される報酬を表すWidgetの作成です。

f:id:kazuhironagai77:20210802000838p:plain

思い出してきました。報酬でパスを得た場合は道具以外に表示されますが、これ間違ってますね。パスは道具に追加する予定ですから。

後。パスを道具袋に追加する機能も作成してないはずです。

f:id:kazuhironagai77:20210802000852p:plain

ただしこれはパスをItemに追加すれば解決します。

パスに関する問題はパスを作成してから直していきます。

<石像封印に関するデータ管理>

これはCanTalk変数の値をTrueに変更する関数を作成していません。

f:id:kazuhironagai77:20210802000908p:plain

まだ石像の封印を解く必要はないのでしばらくは、CanTalk変数の値をTrueに変更する関数は作成しませんが、忘れない様にしましょう。

<Stone Statue BPの配置>

以下の様にStone Statue BPを配置しましたが、適切な位置で適切な石像と会話出来ているのか確認していません。

f:id:kazuhironagai77:20210802000930p:plain

出来ていませんね。三体同時に認識されている場所があります。

f:id:kazuhironagai77:20210802000948p:plain

こっちは2体同時です。

f:id:kazuhironagai77:20210802001003p:plain

これらは後で直します。

思ったより忘れていませんでした。先週のBlogを読んだら何をやったのか結構思い出してきました。

4.2 先々週のブログ2021-07-18の復習

先々週の復習もやっておきます。

<20%の確率で元の世界に戻らないようにする仕組み>

以下に示した様に、今は100%の確率でItemが貰えるようになっています。

f:id:kazuhironagai77:20210802001031p:plain

後で、直すのを忘れない様にします。

次はW_StoneStatueTalkウィジェットの閉じるボタンの機能は、

f:id:kazuhironagai77:20210802001044p:plain

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

f:id:kazuhironagai77:20210802001058p:plain

多分大丈夫でしょう。

<「石像との会話」の実装>

Stone Statue BPのExclamation Markの表示は

f:id:kazuhironagai77:20210802001116p:plain

以下の実装で行っています。

f:id:kazuhironagai77:20210802001132p:plain

この仕組み自体は特に問題はないですね。

NPCの会話システムをこちらの方法に統一するかどうかが検討する必要がある所です。

それぞれの石像の向きや大きさはReturn Statue Mesh 関数内で指定しています。

f:id:kazuhironagai77:20210802001148p:plain

以下に実際に表示されている石像の位置と向きを示します。

f:id:kazuhironagai77:20210802001202p:plain

f:id:kazuhironagai77:20210802001209p:plain

f:id:kazuhironagai77:20210802001215p:plain

問題なさそうです。

以上です。

5.戦闘後のアイテムの入手:Landscape 4でテスト

5.1 Stone Statue BPの配置の直し

闘技場のサイズを少しだけ大きくしてそれぞれのTrigger Boxの距離を取る様にしました。

f:id:kazuhironagai77:20210802001246p:plain

調べた範囲では2つの石像と同時に話せる状態にはなりませんでした。

が実際の原因はよく分からないです。

取りあえずはこれでOKとします。

5.2 RPG Game Mode BPのVictory関数のDefault

しかしこのバグを直している間に別なバグが見つかりました。

f:id:kazuhironagai77:20210802001306p:plain

原因を調べたらRPG Game Mode BPのVictory関数のDefault値がVictoryになっているからでした。

f:id:kazuhironagai77:20210802001323p:plain

このDefault値を別な要素に変更すれば解決しますが、それで問題ないのか調べます。

このVictory変数は、Event Report Fight is OverでYou Winの値をセットされています。

f:id:kazuhironagai77:20210802001341p:plain

以下に示した様に、このEventはMonsterかPlayerの操作するキャラのHPが0になった時、もしくは戦闘から逃亡した時に、Boolean 変数であるcombatOverがTureになった時に発動します。

f:id:kazuhironagai77:20210802001357p:plain

f:id:kazuhironagai77:20210802001403p:plain

それ以前の段階でRPG Game Mode BPのVictory関数のDefault値がVictoryである必要はないはずですが、一応調べておきます。

Get Victoryで検索してみます。

f:id:kazuhironagai77:20210802001440p:plain

それぞれの関数が何時使用されているのか調べます。

最初のGet Victoryです。

RPG Game Mode BPのEvent Fight Is Over内で使用されています。

f:id:kazuhironagai77:20210802001452p:plain

Event Fight Is OverはEvent Report Fight is Overの後で呼ばれるので問題ないです。

次にGet Victoryが呼ばれる箇所です。

f:id:kazuhironagai77:20210802001506p:plain

RPG Game Mode BPのEvent Fight Is Over内です。のでこれも問題ないです。

残りの6個はMyThirdPersonAnim_BP内にある同名の変数であるVictoryでした。

f:id:kazuhironagai77:20210802001520p:plain

最後の2つは石像でExclamation Markを表示するかどうかの時、つまり今回の目的に使用している場合でした。

f:id:kazuhironagai77:20210802001533p:plain

はい。この結果から、RPG Game Mode BPのVictory関数のDefault値はVictoryである必要はないです。

しかし、EscapeやGameOverにするのも何かが違う気がします。

f:id:kazuhironagai77:20210802001546p:plain

PHASE_Noneを追加してそれをDefault値にします。

f:id:kazuhironagai77:20210802001602p:plain

はい。BuildしてEditorを再起動します。そしてVictoryにPHASE_NoneをDefault値としてセットします。

f:id:kazuhironagai77:20210802001615p:plain

はい。

テストします。

f:id:kazuhironagai77:20210802001628p:plain

今度は消えています。

戦闘に勝利した後も、問題ないです。石像との会話も出来ます。

f:id:kazuhironagai77:20210802001642p:plain

念のために、戦闘に負けてみます。

f:id:kazuhironagai77:20210802001653p:plain

これも問題なかったです。

逃走も試してみました。

逃走出来るのは確率で決まるので逃走する前に死なないように盾だけ装備した状態でテストしました。

f:id:kazuhironagai77:20210802001707p:plain

これも問題なかったです。

5.3 Landscape 4でテスト

Landscape 4でテストしてみます。

はい。一個目のバグです。

f:id:kazuhironagai77:20210802001726p:plain

Victory Awardウィジェットが表示されている間、playerの操作するCharacterを動かす事が出来ます。

Victory Awardウィジェットの後に、以下のコードを追加しました。

f:id:kazuhironagai77:20210802001747p:plain

これでVictory Awardウィジェットを表示している時は動かなくなるはずです。

テストします。

アホ過ぎる。今度はVictory Awardウィジェットを閉じてもCharacterが動きません。

f:id:kazuhironagai77:20210802001800p:plain

はい。閉じるボタンにコードを追加しました。

f:id:kazuhironagai77:20210802001814p:plain

直りました。

その後、何回か戦闘をしましたが問題はなかったです。

出来てますね。

6. RPGの作成に必要なもの

Warp Passの作成」するつもりだったんですが、ちょっと止めます。

その理由はここまで作成して分かったんですが、もう既にRPGの作成に必要な部品は揃っています。後はどう組み立てるかだけです。

だからいたずらに複雑にする機能を今追加するのではなく、今ある部品を組み立ててRPGとして完成品とする事の方が先だと思いました。

それで、一番今、必要なのか何かと考えたら目的とゴールなんです。

それを今、ここで決めてしまいます。

候補を思うままに書き記します。

  • 隠し財宝を見つける
  • 仇を討つ。
  • オーブを集める。
  • 捕らわれの姫を助ける。
  • 魔王を倒す。

この中で最も簡単なのは「オーブを集める。」です。これにします。

そうだ。

どうせならWarp Passにします。

金のPassを集めるのが目的にします。

ああ。

もっと良い事を思い付きました。

Passじゃなくて切符にします。せっかく主人公の名前をジョバンニにしたんだから、Warpじゃなくて銀河鉄道に乗る為の切符にします。

そうすると2021-07-18のブログで考えたWarp Passの設定が生きて来ます。

f:id:kazuhironagai77:20210802001859p:plain

このWarp Passの設定を銀河鉄道の切符に変更すればいいんです。普通の切符、切符の切れ端、青い切符、赤い切符、黄金の切符、銀の切符、銅の切符です。

そしてこのWarp Gateですが、銀河鉄道の駅に変更します。

f:id:kazuhironagai77:20210802001913p:plain

はい。これで行きます。

ジョバンニは、赤い帽子を被った魔女から、金の切符を探すように依頼される訳です。

そしてジョバンニが金の切符を見つけたらゲームクリアと成る訳です。

7. 銀河鉄道の切符の作成

となるとやっぱり切符の作成をする必要がありますね。

Itemに切符を追加します。

現在、ItemはData Table、Itemsで管理しています。

f:id:kazuhironagai77:20210802001942p:plain

中身は、

f:id:kazuhironagai77:20210802001954p:plain

こんな感じです。

ここに銀河鉄道の切符も追加しましょう。

f:id:kazuhironagai77:20210802002008p:plain

道具屋で買えるか確認します。

f:id:kazuhironagai77:20210802002023p:plain

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

値段は駄目ですね。BGIからはみ出してしまっています。

f:id:kazuhironagai77:20210802002037p:plain

それは兎も角、切符のイラストは絶対必要ですね。

当分、絵は描きたくないです。切符の絵は来週やる事にします。

Warp Gateならぬ銀河鉄道の駅も改良が必要です。

f:id:kazuhironagai77:20210802002055p:plain

銀河鉄道の駅には、普通の切符で別な世界にワープが出来る事。切符の切れ端、10個で普通の切符と交換できる事。切符が買える事などの機能が必要です。

これらの機能も来週作成する事にします。

更に、ワープ、つまり銀河鉄道で移動中の画像も必要です。

次のmapの読み込みに時間が掛かっている場合は、事故が起きて列車が停止しているとかの解説も付け足したいです。

戦闘中にItemとして切符を使用する事も出来ます。

切符の切れ端は体力と魔力を回復します。普通の切符は戦闘からEscape出来ます。相手のMonsterに使用した場合は相手が強制的にEscapeします。などです。

8. 銀河鉄道の切符関連でやる事まとめ

ここで来週、銀河鉄道の切符関連でやる事をもう一度まとめ直します。

  1. 赤い帽子の魔女に金の切符を集める様に依頼されるシーンの作成
  2. 切符のイラストの作成
  3. 駅員との会話システムを作り直す。
    • 切符は道具屋では買えない。駅で駅員から変える様にする。
    • 銀河鉄道に乗る。切符を買う。切符の切れ端10個と普通の切符を交換して貰う。
    • 移動シーンのアニメーションの作成。
    • 駅でセーブも出来るようにする。
  4. 切符が戦闘でもアイテムとして使用出来る様にする。
    • 切符の切れ端―>体力と魔力を回復
    • 普通の切符―>戦闘からEscape

大体こんなものでしょうか?

結構、沢山ありますね。Preparation and Implementationです。それぞれの実装に必要なものを調べていきます。

8.1 赤い帽子の魔女に金の切符を集める様に依頼されるシーンの作成

以下にスタート画面を示します。

f:id:kazuhironagai77:20210802002147p:plain

このMap内に赤い帽子の魔女との会話を追加しましょう。

「新しく始める」ボタンを押すと、Widgetが開いて赤い帽子の魔女が登場します。赤い帽子の魔女は、あなたに別世界に来て金の切符を探す事を依頼します。

8.2 切符のイラストの作成

切符のイラストを作成します。

サイズは200x200です。

8.3 駅員との会話システムを作り直す

これは以下の機能を作成する必要があります。道具屋の機能を参考にすれば良いと思うのでそれも復習します。

<切符は道具屋では買えない。駅で駅員から変える様にする>

今は、切符は通常のItemと同じData Tableで管理されています。

f:id:kazuhironagai77:20210802002226p:plain

Itemsは全ての道具の一覧表とします。

それぞれの村の道具屋はどんな道具をその店で売れるのかを示す新しいData Tableを示します。そこには村名、道具番号がありその番号に当たる道具がその村で買える道具になるようにします。

そして、切符ですが同じようなシステムにします。新しいData Tableを作成しそこには駅名、道具番号があり番号に当たる切符がその駅で買える切符になります。

銀河鉄道に乗る。切符を買う。切符の切れ端10個と普通の切符を交換して貰う>

NPC_ItemShopOwnerBPの中身を復習します。

f:id:kazuhironagai77:20210802002248p:plain

Componentの中身は以下の様になっています。

f:id:kazuhironagai77:20210802002301p:plain

Exclamation Markを表示するためのComponentがありません。

あれ?

Exclamation Markを表示するためのComponentは後で追加します。

Box内にPlayerが操作するキャラが侵入すると以下の事を行います。

f:id:kazuhironagai77:20210802002317p:plain

ます侵入したActorがThirdPersonCharacterにCast出来るかどうかを確認します。

f:id:kazuhironagai77:20210802002329p:plain

Playerが操作するキャラならCast出来き、出来なければ違うActorが侵入した事が判明します。

次に以下の方法でRPG Game Instance BPにアクセスします。

f:id:kazuhironagai77:20210802002344p:plain

これもかなり昔に実装した部分ですので現在の(私独自のですが)BPのGuidelineには反した書き方です。今のGuidelineではGame InstanceとGame ModeはEvent BeginPlayでそれぞれに対応した変数にAssignしてその変数からアクセスするようにしています。

これも後で直します。

RPG Game Instance BPにある変数、Talk Shopの値をtrueに変更します。

f:id:kazuhironagai77:20210802002400p:plain

うーん。この変数、確か道具ボタンを押す時に道具屋内で押したのかPause画面から押したのかを判別するためのBoolean変数だったと思います。だったらRPG Game Mode BPで作成すべきです。後同じボタンを全く別な個所で呼び出すのもDesign Patternとしてどうなんでしょう。

この辺は後で検討が必要ですね。

今はこのままにしておきます。

今度はGame Modeにアクセスしています。

f:id:kazuhironagai77:20210802002414p:plain

こっちは敢えて変数を作成していますね。全然統一性がないです。まあ道具屋の実装はRPG作成においてもかなり最初に作ったので、何を統一すれば良いのかも不明だったのでしょうがないですね。

これも後で直します。

RPG Game Mode BPの変数、My Place For Eventsの値をPE Item Shopに変更しています。

f:id:kazuhironagai77:20210802002427p:plain

これをする事でkeyboardのeを押した時の挙動が、道具屋での会話になる訳ですね。

あらゆるInputに対する挙動は、Third Person Characterとその親クラスであるUE4C++のCh4_3Characterクラスが管理しているので、一見わかりにくい実装方法ですが、理屈には合っています。この実装方法は正しいです。

Third Person Characterの実装も確認しましょう。

Event Do Somethingから見て行きます。

f:id:kazuhironagai77:20210802002439p:plain

DoSomehing()関数は、UE4C++のch4_3Characterクラス内で宣言されています。

f:id:kazuhironagai77:20210802002454p:plain

Function SpecifierでBlueprint Implementable Eventを使用しているので実装をBP内で行えます。

このEventは、以下に示したようにInputの指定により

f:id:kazuhironagai77:20210802002507p:plain

Key BoardのEを押すと発動するように設定されています。

この辺の設定方法、ちょっと理解が曖昧です。後で復習する必要がありますね。

次にRPG Game Mode BPをAssignされた変数であるMy RPG Game Mode Base BPが値を持っているのか確認しています。

f:id:kazuhironagai77:20210802002521p:plain

持っていない場合は改めてMy RPG Game Mode Base BPに値をセットしていますね。

f:id:kazuhironagai77:20210802002534p:plain

これは、Game Mode とGame InstanceはEvent BeginPlayで対応する変数にAssignしとくべきで、それをやっておけば後でこんな確認をする必要は無くなります。

後で直します。

次はRPG game Mode BPの変数、My Place for Eventの値によって別々な実装になります。

f:id:kazuhironagai77:20210802002555p:plain

My Place for Eventの値は、先程、NPC_ItemShopOwnerBP内でPE Item Shopに変更しました。

My Place for Eventの値がPE Item Shopの場合に実行されるコードです。

f:id:kazuhironagai77:20210802002608p:plain

このコード、現在23個ある分岐の一番最初に書かれたコードでした。キャラのいる場所によってEボタンを押した時の対応は千差万別ですがその一番最初の対応が道具屋だったとは。結構感動です。

やっている内容ですが、最初に道具屋のWidgetであるShop_Welcomeウィジェットを開いています。

f:id:kazuhironagai77:20210802002623p:plain

Shop_Welcomeウィジェットは名前から道具屋のWidgetである事が推測出来ない駄目な名前です。後で直します。

次にCursorを表示しています。

f:id:kazuhironagai77:20210802002638p:plain

このゲームを作成し始めた時はゲームのPlayしている間はなるだけCursorを表示させないようにしていました。のでWidgetを開く時に必ずCursorを表示させるような実装をしています。

ゲームのPlayしている間にCursorを表示しないと画面が激しく動き3D酔いするようになるので。今は常にCursorを表示するようにしています。

のでこの部分の実装は要りません。後で外します。

Widgetを開いている間はPlayerはcharacterを動かせません。そのための実装です。

f:id:kazuhironagai77:20210802002659p:plain

なのですが、うーん。Set Game Paused関数は分かるのですが、それに追加してSet Input Mode Game And UI関数も必要なんでしょうか?

この部分はなぜこうやって実装したのかは忘れちゃいました。

思い出せない理由があるかもしれないのでこの部分はノータッチとします。

ここまでは復習みたいなものですがここからが本番です。

Shop_Welcomeウィジェットを見ます。

まずはDesignです。

f:id:kazuhironagai77:20210802002713p:plain

あれ、Itemを売る時のボタンがありません。

ちょっと確認します。

f:id:kazuhironagai77:20210802002727p:plain

うっそ。

道具は売れないようになってました。これは後で直さないと。

それは兎も角、買い物ボタンを押した場合の実装です。

f:id:kazuhironagai77:20210802002741p:plain

Shopウィジェットを開いてみると

f:id:kazuhironagai77:20210802002756p:plain

となっています。

この商品の下のScrollBox_Inventoryに商品名の付いたボタンを追加する実装があるはずです。それを確認します。

Event Constructで始まっていました。

f:id:kazuhironagai77:20210802002809p:plain

Widget にはEvent BeginPlayは無かったんですね。Event Constructでもこの場合は変わらんでしょう。

はいData Table、Itemsのデータを一つ一つFor Each Loopで回しています。

f:id:kazuhironagai77:20210802002822p:plain

この部分も後で変更が必要です。新たなData Tableを作成してそれぞれの村の道具屋で売っている道具の差別化を図ります。しかしそれは駅が完成した後でやります。

はい。そのLoopの中です。

f:id:kazuhironagai77:20210802002836p:plain

Itemsの要素を元にItemウィジェットを作成します。これがアイテムを購入するボタンに成る訳です。そのWidgetを先程のScrollBox_Inventoryに追加します。そしてその後で???

作成したItemウィジェット、つまりボタンの変数、Parent WidgetにこのWidget、つまりShopウィジェットをセットしています。

うーん。これItemウィジェットの変数、Parent Widgetの設定のExpose on Spawnにチェックを入れて

f:id:kazuhironagai77:20210802002848p:plain

Create WidgetでAssignした方がいいですね。これも後で直します。

それではこの節の山場であるアイテム購入を実装しているWidget、Itemを見てみましょう。

デサインは枠いっぱいにボタンが配置されています。

f:id:kazuhironagai77:20210802002902p:plain

f:id:kazuhironagai77:20210802002908p:plain

本当それだけです。Canvas Panelすらありません。

Event Constructの実装です。

f:id:kazuhironagai77:20210802002923p:plain

Game InstanceとGame Instanceの変数であるMy Your Hero、そしてThirdPersonCharacterの変数を作成しています。

これは、後でこのウィジェット内でこれらの値にアクセスするが楽になり非常に便利です。

それではボタンをクリックした場合の実装を見ます。

f:id:kazuhironagai77:20210802002939p:plain

あ、これは随分後で、修正していますね。かなり綺麗に整理されています。結構最近直したのかな?正直覚えていません。

イキナリ、Remove My Tool Image Widget()関数を読んでいます。

f:id:kazuhironagai77:20210802002953p:plain

思い出しました。この関数、以下のイメージを消すための関数でした。

f:id:kazuhironagai77:20210802003006p:plain

この関数がないとずっとこのイメージが表示されているんでした。

次です。

f:id:kazuhironagai77:20210802003020p:plain

ここで道具屋でこのボタンを押したのか、Pause画面でこのボタンを押したのかを判別しています。

あれ?

RPG Game Instance BPにある変数、Talk Shopがこれを担当していると思ったんですが。

ちょっと調べて見ます。

何と。RPG Game Instance BPにある変数、Talk ShopはMap2とMap3で使用されていました。

f:id:kazuhironagai77:20210802003034p:plain

f:id:kazuhironagai77:20210802003050p:plain

うーん。何のために使用されているのか不明ですが、RPG Game Instance BPにある変数、Talk Shopは道具屋でこのボタンを押したのか、Pause画面でこのボタンを押したのかを判別している訳ではなかったんですね。

この変数の意味については後で検討します。必要ないなら消します。

勿論、この実装で今最も知りたいのは、道具屋ないでボタンを押した場合です。

そちらを見て行きます。

まずData Table、Itemsから対応するItemのデータを取り出します。

f:id:kazuhironagai77:20210802003105p:plain

ここで調べてるのはそのItemの値段です。

f:id:kazuhironagai77:20210802003122p:plain

はい。

そのアイテムの値段よりもお金を持っている場合は、次に進めます。持っていない場合はここで実行は終わっています。

f:id:kazuhironagai77:20210802003136p:plain

つまり、アイテムを買うお金を持っていない場合はボタンをクリックしても何も起きない訳です。

十分なお金を持っている場合は、まずお金が引かれます。

f:id:kazuhironagai77:20210802003155p:plain

次に、RPG Game Instance BPの変数でPlayerが操作するキャラの所有するアイテムを管理している変数、Itemsに購入したItemの名前を追加します。

f:id:kazuhironagai77:20210802003209p:plain

次です。

f:id:kazuhironagai77:20210802003222p:plain

この部分一体何をしているだろうと思ったら、簡単な事でした。

以下に示した道具の購入画面で左側の道具袋に勝ったアイテムを表示させる実装が書かれていました。

f:id:kazuhironagai77:20210802003236p:plain

これは報連相の観点から重要ですね。買ったItemが所持品内で表示されなとかなり焦りますから。

ここで作成されるYour Itemウィジェットですが

f:id:kazuhironagai77:20210802003249p:plain

Textだけで構成されているWidgetです。

f:id:kazuhironagai77:20210802003303p:plain

この部分を参考にする事で、切符を買うための実装は作成出来ますね。

切符の切れ端10個と普通の切符ですが、それ専用のボタンを作成します。

「切符の切れ端コレクション」ボタンとして、それをクリックすると現在持っている切符の切れ端の数が表示されます。10枚以上だった場合は、普通の切符と交換しますか?ボタンが表示されます。そのボタンを押すと切符の切れ端10枚と交換で普通の切符が貰えます。

銀河鉄道に乗る。場合です。

これはA_WarpGateKeeper BPの復習をする事で実装方法を確認します。

f:id:kazuhironagai77:20210802003317p:plain

実装方法を見てみます。

うん。これは何をしているでしょうか?

f:id:kazuhironagai77:20210802003331p:plain

あ。NPCと同じ実装をしています。

これはBPのPrivateな変数がそれぞれのInstanceで独立した値が取れる事を知らない時に書いたコードです。

BPの変数は

f:id:kazuhironagai77:20210802003346p:plain

にチェックを入れない限り、所謂Global変数みたいな扱いになると思っていましたので、こんな複雑なコードを敢えて書いていました。

実際はInstance Editableにチェックを入れると以下に示したように

f:id:kazuhironagai77:20210802003358p:plain

Level上に静的に配置したBPのInstance内の変数の値をDetail画面から編集出来ると言う意味でした。

間違っている訳ではないです。ただもっと簡単に実装する方法があるだけです。

そしてその方法は石像との会話で実装しています。

もう頭が働かなくなってきました。

今週はここまでにします。

ワープの実装方法については来週以降考えます。

<移動シーンのアニメーションの作成。>

これはまだ実装はしませんが、理想だけ書いておきます。

銀河鉄道で移動すると言う事は別なMapに移動すると言う事になります。

その場合読み込みに時間がかかる場合があります。ない場合もあります。

読み込みに時間が掛かるときは、電車内の会話で人身事故が起きました。とか線路内に人が立ち入ったので点検しています。しばらくお待ちくださいのようなコメントが流れるようにしたいです。

そして次のMapが開く前に○○駅に到着しました。と表示されるようにします。

だけどUE5で制作した場合は読み込み時間がほぼ0になるみたいですよね。そうなると要らない機能になってしまうんでしょうか?

<駅でセーブも出来るようにする。>

これは良く考えたら神官の仕事を奪ってしまいます。のでこのアイデアは没にします。ただし駅内に神官を配置する事は考えます。

9. Good Skyの検証

とてもやる知力が残っていません。来週以降やります。

10. まとめと感想

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

  • Particle Systemの勉強
  1. Niagara
    • 応用編の最初としてCGHOW氏のUnreal Engine Niagara Tutorials [1]を半分だけ実際に作成した。
  2. Cascade
    • 応用編の最初として炎、雷、氷、水、風、回復などの色々なEffectの資料を集めた。
    • Unreal 4 Particles Tutorial - Simple Flame, Embers, Smoke. [6]を元に炎のEffectを作成した。
  • RPGの作成
    1. 戦闘後のアイテムの入手のバグ探しとその直し
    2. 切符について
      • 切符のアイデアと実装方法についての検証
      • 駅の実装方法についての検証

を行いました。

来週は、

  • RPGの作成
    1. スタート画面の続きで、魔女との会話を実装
    2. 切符の実装方法
    3. 駅における切符の購入の実装
    4. 駅における移動の実装方法の検証
    5. 実際に別なマップに移動してる間に別なアニメーションを表示する方法についての調査
    6. 時間があったらGood Skyの復習

などを行う予定です。

11. 参照(Reference

[1] CGHOW. (n.d.). Unreal Engine Niagara Tutorials. YouTube. Retrieved August 1, 2021, from https://www.youtube.com/playlist?list=PLwMiBtF6WzsqC7_cJmD26ts0YDbtPCCfe

[2] CGHOW. (2019a, March 2). Unreal Engine Niagara Cloud Tutorial | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=hDfKZh1tRmU&list=PLwMiBtF6WzsqC7_cJmD26ts0YDbtPCCfe&index=2

[3] Epic Games. (n.d. -b). Particle Spawn Group. Unreal Engine Documentation. Retrieved August 1, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/ParticleSpawn/

[4] CGHOW. (2019b, August 16). Ice Hit Effect | Unreal Engine Niagara Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=txR-uEwXj64

[5] CGHOW. (2020, July 17). Stylized Water Splash | UE4 Niagara Water Splash | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=Xj5fRywPIlo

[6] Game Dev Society BU. (2019, March 14). Unreal 4 Particles Tutorial - Simple Flame, Embers, Smoke. [Video]. YouTube. https://www.youtube.com/watch?v=u7hRDl2yQmM

[7] Epic Games. (n.d.-a). Orbit Modules. Unreal Engine Documentation. Retrieved August 1, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/ParticleSystems/Reference/Modules/Orbit/

 

 

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 戦闘後のアイテム収得 Part 2

f:id:kazuhironagai77:20210725225509p:plain

<前文>

Minimal Pairのアプリを販売するに当たって一個だけはっきりさせておかない事を書いておきます。

Minimal Pairで練習する事でLとRの音の区別がつくようになるのかは、今の時点では分からないです。こう書くと英語学習の初心者は「RとLの区別は簡単だよ。」と言うかもしれませんが、それは、ゆっくり発音した場合や単語の最初や最後の音がRやLの場合で、アメリカ人が通常の速度で会話した場合でLとRの音を完全に区別出来る日本人(英語がネイティブ以外で)は少なくとも私は会った事がありません。

そのために本当にLとRの音の区別がついているのかどうかのテストもMinimal Pairでみっちりします。そのテストで満点が取れる方のみが「RとLの区別は簡単だよ。」と言う権利があります。

後、LとR以上に日本人にとって難しいと言われれているzとdz、ʒとdʒもみっちりとテストします。

それでですね。

もしかするとある年齢を超えたらLとRの区別はつかないかもしれない可能性もあると思っています。なぜなら絶対音感は子供だけが身に付ける事が出来るように、音素の識別が学べるのはある年齢以下の子供だけかもしれないからです。

その場合はLとRの音素の違いを聞き分ける訓練はやるだけ無駄になります。

ただ100%無駄になるかどうかはやってみないと分かりません。

YouTubeの動画ですが、4年前の動画であるWhy do Japanese mix up "L" and "R"? [1]でJun氏はLとRの区別がつかないとアメリカ人の奥さんから指摘されていますが、最近の動画であるCan Jun finally tell "R" and "L" apart? [2]ではJun氏はLとRのテストを出されてほぼ全問正解しています。

このテストで出された問題の単語の発音は普通の速度で読まれていますし、Jun氏は完全にLとRの区別がつけられるようになったと思われます。と言う事は日本人でも大人になってからもLとRの区別はつけられる可能性はあると思われます。

勿論、Jun氏がどんな訓練をしてLとRの区別がつくようになったのかは分かりません。Minimal Pairの練習ではLとRの区別がつけられるようになるにはならない可能性もあります。

後、もう一つの問題はこの動画で行われたテストは二重盲検法(Double blind experiment)じゃないです。問題を出す側も答えを知っていますし、撮影をしてる奥さんも答えを知っています。だからこの結果だけで日本人でも大人になってからもLとRの区別はつけられるとは言えないかもしれません。

それで言語学の専門家は「日本人は大人になってからでもLとRの区別がつくように成れるのか?」について、どういう見解なのか調べたんですが、これは良く分かりませんでした。

もし出来る様になるのならばMinimal Pairの果たしている役割はどの程度なのかも不明です。と言うか言語学の専門家ってどれだけ信用出来るのかも分かりません。

まあ、そういう訳で問題だらけではありますが、それはVersionをupしながら直していこうと思っています。

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

<本文>

1.今週の予定

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

  • Niagara の勉強
  • Cascadeの勉強
  • 石像との会話と石像からのItemの入手
    • それぞれの石像のBack Ground Imageの作成
    • それぞれの石像からItemを貰うときに開くWidgetの作成
    • それぞれの石像のセリフの作成
    • 戦闘中に石像と会話出来ない仕組みの作成
    • 石像を封印する仕組みの作成
  • Warp Passの作成
  • Good Skyの検証

それでは始めます。

2.Niagara の勉強

今週は、先週出来なかったRecreate the Starter Content Smoke Effect in Niagara [3]をやっていきます。もうSub UVの使用方法も大体理解出来たのでそんなに深くはやらないでぱっぱと終わらせてしまいます。

2.1 Recreate the Starter Content Smoke Effect in Niagara [3]の勉強

<Create System and Emitter

先週作成したFX_Smoke emitterの複製を作成しそれのNiagara systemを作成しました。そのNiagara systemにDark Smokeと名付けLevel上に配置しました。

f:id:kazuhironagai77:20210725225627p:plain

<Edit the Emitter Update Settings

Emitter Update CategoryのEmitter State ModuleにあるLife Cycle Modeの設定をSystemに変えます。

f:id:kazuhironagai77:20210725225648p:plain

Tutorialの説明ではEmitter自身がLife Cycleを管理する必要がないから。とありますが、その辺、もっと詳しい説明が欲しいです。

Selfの時には以下に示したようなParameterを全部自分で指定していました。

f:id:kazuhironagai77:20210725225703p:plain

例えばLoop BehaviorはSystemの時は自動的にInfiniteになるのかそれとも別なFactorによってコントロールされるのか?全く分かりません。

調べましょう。

まずはcursorをLife Cycle Modeに合わせて、表示される解説を読んでみます。

f:id:kazuhironagai77:20210725225719p:plain

うん。成程。Systemの時の方が最適化されるので出来るだけSystemにすべきと書かれています。

つまり効率の観点から出来るだけこのParameterはSystemを選ぶべきで、どうしてもEmitter側でLoopingの設定をしなければならない場合を除いてSystemにしておけという事らしいです。

更に、最初の疑問である「Systemの時は自動的にInfiniteになるのかそれとも別なFactorによってコントロールされるのか?」についてですが、それらの値はSystem側から自動で渡されるそうです。

公式のDocumentであるEmitter Update Group [4] も見ましたが同じ事しか書いてなかったです。

うーん。これだけではまだよく分かりませんね。

Emitter State ModuleのNiagara Module Scriptを開いて見ましょう。

f:id:kazuhironagai77:20210725225736p:plain

何を書いてあるのかまだ分かりません。しかしちょっとは読める部分もあるでしょう。

ノードの塊ごとに整理されていてその塊が何をしているのかのコメントが入っていました。

f:id:kazuhironagai77:20210725225750p:plain

例えば、上記のノードの塊はLoop Durationの初期化を行っているとコメントされています。

これなら少しは理解出来そうです。

先程のInitialize Loop Duration Pre Life Cycleの中身を見るともしFixedならとかもしInfiniteならと書いてあるノードなどがあります。

f:id:kazuhironagai77:20210725225804p:plain

と言う事はこの時点でSelfの内容について実装してるのかもと思い、その前の実装を調べると

f:id:kazuhironagai77:20210725225820p:plain

Initialize Loop Duration Pre Life Cycleの前で分岐してる箇所を発見しました。この分岐した一番下の線を追うと

f:id:kazuhironagai77:20210725225836p:plain

ドンピシャです。Systemで計算する時の実装が書かれている箇所を見つけました。

これのノードらが何をやっているのかが分かれば「Systemの時は自動的にInfiniteになるのかそれとも別なFactorによってコントロールされるのか?」についても分かるはずです。

見てみます。

f:id:kazuhironagai77:20210725225852p:plain

何これ?

f:id:kazuhironagai77:20210725225907p:plain

この青い楕円で囲まれてたSYSTEMというマークがついているやつらがSystemから送られてきた値を保持しているParameterでしょう。でもそれぞれのParameterの名前、AgeとかLooped Ageって初めて見るParameterです。何を担当してるのか全く分かりません。

Niagara SystemのParametersからSystem Attributesを開くとそれらのParametersが表示されています。

f:id:kazuhironagai77:20210725225922p:plain

うん。ひょっとしてSelfの時に手動で決定する以下のParameterって

f:id:kazuhironagai77:20210725225937p:plain

実際には存在しなくて、本当は以下の実際のParameterの値が変化していると言う事なんでしょうか?

f:id:kazuhironagai77:20210725225950p:plain

調べて見ます。

はい。

以下のノードを見つけました。

f:id:kazuhironagai77:20210725230030p:plain

Infinite、Once、そしてMultipleの場合においてそれぞれのParameterの値について指定しています。

つまり、Life Cycle ModeがSelfの時のLoop Behaviorの値を示しています。

f:id:kazuhironagai77:20210725230045p:plain

Infiniteの場合を見ると、以下の様にAge、Looped Ageなどの先程、Life Cycle ModeでSystemを選択した場合に設定したParameterと同じparameterの値を指定していました。

f:id:kazuhironagai77:20210725230101p:plain

と言う事は。やっぱりSelfの時に手動で決定する以下のParameterって実際には存在しなくて、本当はもっと細かい値を指定するParameterが実際の値の管理をしていました。

ただし、先程のInitialize Loop Duration Pre Life Cycleの中身にFixedの場合はLoop Durationの値はこっち、Infiniteの場合はこっちと書かれている箇所がありました。

f:id:kazuhironagai77:20210725230117p:plain

全部のParameterが存在しないと言うわけでもないんですね。

この位で深堀は止めて次に行きます。

Spawn Rate ModuleのParameterであるSpawn Rateの値を25にセットしました。

f:id:kazuhironagai77:20210725230132p:plain

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

f:id:kazuhironagai77:20210725230147p:plain

この辺は、デザイナーが見た目の良さから最適化すべき値で、Programmingとは直接は関係ないので今回は深堀しません。

<Edit the Particle Spawn Settings

Particle Spawn GroupのModuleの設定を変更します。

Initialize Particle ModuleのLife timeの値を変更します。

f:id:kazuhironagai77:20210725230206p:plain

この値もデザイナーが見た目の良さから最適化すべき値で、Programmingとは直接は関係ないので今回はスキップします。

Color ModeのColorの値を変更しました。

f:id:kazuhironagai77:20210725230227p:plain

ちょっと値を弄っただけで煙の印象が全く変わりました。

f:id:kazuhironagai77:20210725230241p:plain

Sprite Size ModeからSpriteのサイズを変更しました。

f:id:kazuhironagai77:20210725230256p:plain

煙のサイズが小さくなりました。

f:id:kazuhironagai77:20210725230403p:plain

正直、前の方が良かった気がします。

Add Velocity Moduleの値を変更しました。

f:id:kazuhironagai77:20210725230418p:plain

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

f:id:kazuhironagai77:20210725230433p:plain

うーん。あんまり変わらないですね。

Particle が発生する箇所をもっと狭めないとへんな感じは無くならない気がしますね。

Sphere Location ModuleのSphere Radiusの値を変更しました。

f:id:kazuhironagai77:20210725230449p:plain

はい。やっぱりParticle が発生する箇所を小さくしましたね。元の値が64でしたので半分の半径になりました。

f:id:kazuhironagai77:20210725230503p:plain

前よりはマシですが、煙の上昇速度が速過ぎる気がします。

<Edit the Particle Update Settings

Acceleration Force ModuleのAcceleration のZ 軸の値を20にしました。

f:id:kazuhironagai77:20210725230521p:plain

Scale Color Moduleのcurveの値を以下のようにしました。

f:id:kazuhironagai77:20210725230537p:plain

結果です。

f:id:kazuhironagai77:20210725230551p:plain

まあま煙には見えます。

Level上に配置した場合です。

f:id:kazuhironagai77:20210725230605p:plain

うん。影はないですがそれ以外はまあまあいいんじゃないでしょうか。

2.2 Smoke Effectのまとめ

Sub UVの使用方法や影の追加方法なども勉強出来たのでSmoke Effectについてはこれで一応終りにします。

UE4でSmokeがどのように作成されているのかは全く想像出来なかったので、Smokeのeffectの作成方法についてかなり深い理解が出来ました。

のでそれをここにまとめておこうと思います。

<その1:Smokeの一つ一つの粒子はSpriteで作成される>

SmokeはSpriteで作成されます。粒子を大量に生成してそれぞれの粒子に常にカメラ側を向いた面を貼り付けるそれです。それぞれの粒子の移動こそが煙が煙らしく見えるための必須条件になります。

<その2:SmokeはSub UVを使用する>

それぞれの粒子が持つ面状でSub UVによってアニメーションが描かれます。それが煙の動きを表します。

f:id:kazuhironagai77:20210725230757g:plain

この二つの働きによってSmoke Effectは作られています。

2.3 Smoke Effectについての考察やまとめ

所で実際の煙の動きはどうなのでしょうか?

このSmoke Effectでやったようにそれぞれの粒子は不完全燃焼をするために煙を発生させ、全体としては沢山の粒子が上方に舞い上がって煙を発生させているんでしょうか?

色んなサイトを見た感じでは、最初から小さい粒子が発生してそれぞれが勝手に舞っているだけの様です。

だから本当の煙を作成する場合はParticleを何十万個と発生させてそれぞれのParticleに煙の粒子を表現させる事になるんでしょうか?

勿論、それでは高コストになってしまうためUE4では上記の方法を採用している訳です。

BlenderのSmokeのSimulationを見るとどうもGridを使用して計算してそうです。流体のSimulationでGridを使う方法と粒子を使う方法があったような気がしますがもう忘れました。

流体力学のSimulation Softはいつかは自分で作成したいとは思っていますが忙しくて勉強する暇がありません。

Real timeで数値解析するんだったらUnreal Engine内で可視化するのもありだと思っているんですがどうなんでしょうか?

UE4や5はゲームだけじゃなくて3D の可視化のツールとしての利用も有効だと思ってはいます。

2.4 Content Exampleの観察

今週は、Niagara Systemで勉強する事が無くなってしまったのでContent ExampleのNiagara systemのサンプルでも見ながら次の勉強に何をするのかを考えます。

<Sprite Facing

Sprite は面が常にカメラに向いていますがそれをコントロールする為の方法が勉強出来るみたいです。

f:id:kazuhironagai77:20210725230847p:plain

地味ですが絶対知っておくべき技術ですね。

<Static BeamとDynamic Beam

Beamは散々勉強しましたがStatic BeamとDynamic Beamの違いが分かりません。

f:id:kazuhironagai77:20210725230905p:plain

<Multiple Rendering

Multiple Renderingそのものについてはそんなに優先順位は高くないですが、この例が素晴らしいです。

f:id:kazuhironagai77:20210725230925p:plain

3次元上での原子核の周りの電子の軌道をこれを利用して表したら面白いなと思いました。

今は小学校の教科書でも量子的な解釈をした電子の雲が原子核の周りを覆っている図しかないんでしょうか。その場合は太陽系の図でも面白いと思います。

<Location Events

これは花火の製作に使えるTechniqueですね。

f:id:kazuhironagai77:20210725230945p:plain

そう言えば花火を作ると言ってすっかり忘れていました。

<Expression

これは何をやっているのか分かりません。

f:id:kazuhironagai77:20210725231003p:plain

HLSLが直接書けると言う事でしょうか?

<Collision

この地面にぶつかって停止しているのは拾えたり出来るんでしょうか?

f:id:kazuhironagai77:20210725231021p:plain

拾えると応用方法が凄く広がりそうです。

<Static Mesh Sampling

これは何やっているのか全く不明ですね。

f:id:kazuhironagai77:20210725231041p:plain

f:id:kazuhironagai77:20210725231048p:plain

Samplingが出来ると言う事はStatic MeshをNiagara systemから自由に動かせると言う事なんでしょうか?それともNiagara system は、Worldに配置されているStatic Meshの持っている情報を自由に得る事が出来ると言う事なんでしょうか?

うーん。

これはこれで面白いですが今はあんまり興味が湧かないです。

CGHOW氏のUnreal Engine Niagara Tutorials [5]の方が面白そうです。

f:id:kazuhironagai77:20210725231104p:plain

これの一番最初のヤツをやって見る方が面白そうです。

決めました来週はこれをやります。

3.Cascadeの勉強

今、言語学についても少しは勉強しなくてはと2冊、英語の発音を勉強する人達が良く薦める教科書を読んでいます。日本語で書かれた本です。それが結構Volumeがあります。軽くは読めないんです。

それで思ったんですが、日本語で書かれたUE4VFXの教科書も結構良いのがあるんじゃないと。

調べたらありました。池田 亘 著「HoudiniとUnreal Engine 4で学ぶリアルタイムVFX」です。今週はCascadeの勉強はお休みしてこの本を読む事にしました。

正し日本語の本の内容を丸々このブログに載せる訳にはいかないので感想を書くに留めます。

3.1 総評

まず全体の感想として、内容が非常に濃く読み応えがあります。しかし平易な言葉で説明しているのでかなり読みやすいです。サラッとですが3時間くらいで一応読み切りました。(ただしHoudiniの箇所は今後も勉強する気はないのでスキップしました。)

私が思うこの本の凄い所は、ノードの計算をGraphを使用する事で可視化している点です。これによって一つ一つのノードが何をやっているのかが正確に分かります。更にその計算の裏側にある理論と目的もはっきり理解出来ます。目から鱗の学習方法でした。

UE4VFXを基礎から勉強したい人や、深い部分までしっかり理解したい人は絶対読むベき本です。後、UE4のMaterialの理解を基礎から一歩進めたい人にもお勧めです。この本のかなりの章でMaterialについても詳しく解説しています。

題にある通り、Houdiniの使用方法の解説や、Houdiniを使用して何かをしたりする箇所が沢山ありますが、Houdiniがないと理解出来ない訳ではないのでUE4 onlyで勉強してる人でも問題なく読み進められます。

私はKindle版を買いましたが、本で買うより断然読みやすいです。PCの画面に200%で表示させて一気に読みました。Kindle版をお勧めします。

勿論、人間が作成したモノに完璧なものはないのでこの本にも良い点と悪い点があります。それについては以下にまとめました。

3.2 私が思うこの本の良い点

私が思うこの本の良い点を以下に述べます。

  • 計算の検討を逐一している。(筆者が完全に理解したり、完全に納得した事のみを書いている。)
  • 付属ファイルにこの本に載っている全てのノードの図が提供されている。(図が小さくて読者が混乱する事はない。)
  • 最新の技術を紹介していると思われる。

細かい点でもっと良いと思う部分はありましたが、最も重要だと思う事を3つ選びました。

<計算の検討を逐一している>

Shader内の計算が特にそうですが、Nodeの計算を全部自分で計算し直しています。

特にこの中で私が凄いと思ったのが計算結果をGraphで表す方法です。

この学習方法が素晴らしいは、計算の意味をしっかり確認するだけでなく、その計算の元になっている理論をしっかり自分のものに出来る事です。

大変分かり易い。

マンガを読んでる位の脳力しか使わないで、複雑な計算方法とその元の理論まで理解出来ます。

一例を挙げるとDot productの計算です。

私はDot Productを反転すると何で円の淵がぼやっと浮き上がるイメージになるのかずっと分からなかったんですが、この本の説明で一発で理解出来ました。

しかもこの本は最初から最後までこの解説方法で一貫しています。非常に沢山の計算方法とその元になる理論が紹介されています。

<付属ファイルにこの本に載っている全てのノードの図が提供されている>

こっちは流石に試している時間はないですが、読者がしっかり自分で試せるように、付属のファイルに全てのノードの図が入っていました。

前に買ったUE4の本で、ノードの図が小さ過ぎて何が書かれているのが分からなくて、実際に自分で試そうとしたら何も出来なかった時がありました。その時、かなり頭にきたので今もってその事を覚えています。

それ以降、UE4関連の本にノードの図がある時は、その図に載っている全てのノードの名前が読めるのかどうかと、全てのノードの繋がりが見えるのかどうかを確認する癖が付きました。

本に載っているノードの図からも一応は全てのノードの名前は読めますが、付属のファイルに入っている同じ図は本の図より5倍位大きくて読みやすいです。

<最新の技術を紹介していると思われる>

すいません。

私はゲーム業界については全く知らないので単なる想像ですが、この本で紹介されているテクニックは実際のプロが現場で今使用しているテクニックそのもののような気かします。最新かつ最高水準のテクニックを教えていると思われます。

3.2 私が思うこの本の不満点

ただ全てか完璧と言うわけでの無く不満点もありました。

以下に私が感じた不満点を記します。

  • どの層が読者なのか?デザイナーが対象なのか、Programmerが対象なのか。はっきりしない。
  • カタカナ語が多すぎ

<どの層が読者なのか?>

Effect Designerに成りたい人向けに書かれているのかと思われます。しかしUE4をちょっと触ってEffect を1個か2個作成しただけの素人にはこの本の内容は高度過ぎます。

元々、programmerでHLSLやGLSLでガンガンコードを書いていた人ならUE4のEffectを学ぶには丁度良い本です。

理論もしっかり説明されていますし、UE4での具体的な操作の仕方も丁寧に説明されています。

でもそうだとすると何で数式や方程式を省くのかな。と思います。更にVisual scriptingの説明でもDesignerでも使えます的な説明をしていますがProgrammer向けならそんな事言う必要ないと思います。

後「2つのイメージを並べて、こっちの方が良くなっています。」と解説されるとかなり焦ります。デザインの勉強をした人には明白な違いなのかもしれませんがProgrammerから見ればどっちも凄く見えます。

デザイナーは元々、絵の上手さでも90点と95点で争っている訳で、85点の絵と95点の絵を二つ並べればすぐに95点の絵が凄いと分かります。しかしProgrammerは絵については素人というか素人の平均を下回っている人がほとんどなので85点の絵と95点の絵を二つ並べられてもどっちも凄いとしか思えません。

2つのイメージを並べて比較する時はデザインの観点からここに注目するポイントがあって、その点から見ると左の方が全然良いよね。と言う感じで説明してほしかったです。

後、デザイナーでUE4のEffectの基本は身に着けた人がこの本の想定している読者なのかなとも思いました。

それなら敢えて数式や方程式までは書く必要ないし、2つのイメージを並べてた時も、こっちの方が良くなっています。で終わりでも良いです。

しかしその場合はVisual Scriptingについて素人同然の人に対してするような説明をする必要はないですよね。

そういう訳で想定している読者がどの層なのか???でした。

対象とする読者を

  1. Programmerで元々HLSLGLSLでバリバリコードを書いていたがUE4VFXの使い方を深いレベルで学びたい人
  2. デザイナーでUE4Niagaraは一応使いこなせるが、更に深く学びたい人
  3. UE4の初心者でVFXを学び始めたばかりの人

と仮定して、この部分は1のタイプの人には常識かもしれませんが、ほとんどの2のタイプの人は初めて聞く内容なので詳しく説明します。ここは3のタイプの人にはまだ理解するには難しいですが、将来的にはこういう事を勉強しないといけいないのでその準備と思って読んでください。完璧に理解する必要はありません。のようなコメントが一言あると読者もここは良く読む必要があるな。とか俺はこの部分はスキッブしていいわ。とか、ああこの部分は3のタイプの人を勇気づけるために敢えて不正確な表現をしているんだな。とか色々分かって読書中に混乱したり不安になったりあるいはちょっとイラッときたりする事が無くなると思います。

カタカナ語が多すぎ>

別にこの本に限った事ではなくProgramming関連の日本語の書籍全般に通じる問題ですが、安易なカタカナ語の作成とその使用は質の高い日本語の崩壊につながると私は思っています。

しかし問題はそれだけじゃありません。

安易な英単語のカタカナ化は実際の発音と全く別の発音を生み出してしまいます。

プロシージャルって何。全く聞いた事ない。と思ったらProceduralの事でした。

Proceduralの発音はprəˈsiʤərəlです。敢えて片仮名で表したらプル(ェ)スィヂュアゥです。どう聞いたらプロシージャルになるんですかね。

英語でシの音とスィの音は全く別な音です。「あんこ下さい」って言うつもりで「ウンコ下さい」って言ってんのと同じ位、間違ってます。しかもその後でʤəの音、つまりヂュの音なのにジャって書いてあって、これまた全く別な音です。「あんこ下さい」って言うつもりで「ウンチ下さい」になっています。

やっぱり私の作成しているMinimal Pairによる音素聞き分け訓練ソフトは必要だと思いました。

4.それぞれの石像のBack Ground Imageの作成

イラストなんですが、ちょっと悩んでいます。

以下にNPCに使用したイラストを示します。

f:id:kazuhironagai77:20210725231257p:plain

f:id:kazuhironagai77:20210725231303p:plain

f:id:kazuhironagai77:20210725231310p:plain

単純ですが、中々可愛いイラストで大変な苦労をして開発しました。私がIllustratorだったら、この画風で勝負を賭ける位の自信作です。

しかし自分の作ったこのRPGをテストしていると、以下に示した回復薬のイラストで描いたイラストの方が上手いです。

f:id:kazuhironagai77:20210725231326p:plain

f:id:kazuhironagai77:20210725231333p:plain

こういう感じの絵はなんの苦労もなく描けます。石像はどっちの絵柄にしようか迷っています。

2番目の絵柄で書いて見ました。

f:id:kazuhironagai77:20210725231347p:plain

こんな感じです。

f:id:kazuhironagai77:20210725231401p:plain

絵の練習を今からする訳にもいかないのでこれで行きます。

残り8体の石像も描いてしまいます。

f:id:kazuhironagai77:20210725231415p:plain

f:id:kazuhironagai77:20210725231423p:plain

f:id:kazuhironagai77:20210725231429p:plain

f:id:kazuhironagai77:20210725231437p:plain

f:id:kazuhironagai77:20210725231445p:plain

f:id:kazuhironagai77:20210725231452p:plain

f:id:kazuhironagai77:20210725231459p:plain

疲れた。本当に疲れました。一緒にゲームを作ってくれるIllustratorの人を早く探さないと。と本気で思いました。

後、このWidgetだと返事用のボタンで石像の3Dのイメージが見えないですね。後で直します。

5.それぞれの石像からItemを貰うときに開くWidgetの作成

これです。

f:id:kazuhironagai77:20210725231522p:plain

今の時点では、以下の画面から「はい」ボタンを押すと

f:id:kazuhironagai77:20210725231535p:plain

どの石像の場合でもGet Item  ウィジェット(つまり最初のイメージ)が開きます。

このWidgetだと一回に一種類のアイテムしか与えられません。色々なパターンのWidgetを作成しようと思います。

沢山のWidgetを作成しようとしたんですが、全部のパターンに対応出来るWidgetを思いつきました。

f:id:kazuhironagai77:20210725231549p:plain

Angle Statue02に会話をした場合です。

f:id:kazuhironagai77:20210725231602p:plain

6.それぞれの石像のセリフの作成

<Betrayal Statue

セリフです。

f:id:kazuhironagai77:20210725231624p:plain

はいといいえの表示は後で直します。

f:id:kazuhironagai77:20210725231636p:plain

f:id:kazuhironagai77:20210725231643p:plain

褒美は以下に示した様に1/6 の確率でしかもらえません。

f:id:kazuhironagai77:20210725231657p:plain

f:id:kazuhironagai77:20210725231704p:plain

外れた時は何も表示されません。

f:id:kazuhironagai77:20210725231718p:plain

Betrayal Statue DialogueのセリフでRewardがなかったのでそれも足しました。

f:id:kazuhironagai77:20210725231731p:plain

Teleport用のPassの仕組みはまだ作成していないのでItemに追加したりする機能は後で作成します。

<Angel Statue>

Angel Statueの場合です。

f:id:kazuhironagai77:20210725231750p:plain

はい。を選びます。

f:id:kazuhironagai77:20210725231804p:plain

褒美を受け取るボタンを押します。

f:id:kazuhironagai77:20210725231823p:plain

イーサーを1個か回復薬を3個もらえます。

残りの石像は何をくれるのかはまだ考え中なのでこれで一端、中止します。

その代りW_StoneStatueTalkウィジェットの回答ボタンの位置を直しました。

f:id:kazuhironagai77:20210725231848p:plain

前より見易くなりました。

7.戦闘中に石像と会話出来ない仕組みの作成

今のStoneStatueBPの実装だと戦闘中でも石像と会話出来てしまいます。それを防ぐ方法を考えます。

考えました。

f:id:kazuhironagai77:20210725232035p:plain

戦闘に勝利した時はRPGGameModeBPの変数であるVictoryの値はPHASE_Victoryになっています。

Victoryの値がPHASE_Victoryの時だけ、石像と会話出来るようにしました。

StoneStatueBPの指定しているTrigger Boxから出る場合も、一応、同じ実装をしておきます。

f:id:kazuhironagai77:20210725232050p:plain

この二つは実際に試してみないときちんと動くか分かりません。

後は実際に配置する時に、Trigger Boxの位置を微妙にずらしてPlayerの操作するキャラがいる位置から外れるようにする事も出来ます。

やっぱり実際にテストをしてみたいのでStoneStatueBPをBattle Field Map上に配置してみます。

8.Stone Statue BPBattle Field Map上に配置する

以下のようにStone Statue BPを配置しました。

f:id:kazuhironagai77:20210725232112p:plain

戦闘が終わりました。

f:id:kazuhironagai77:20210725232126p:plain

石像、AngleStatue02に近づきます。

f:id:kazuhironagai77:20210725232141p:plain

AngleStatue02の頭上にExclamation markが表示されました。あんまりよく見えません。別な方法でこの石像と会話出来る事をPlayerに知らせる必要があるかもしれません。

会話するためにキーボードのEを押します。

いつもの画面が登場しました。

f:id:kazuhironagai77:20210725232156p:plain

「はい」ボタンを押します。

セリフが変わりました。

f:id:kazuhironagai77:20210725232209p:plain

あんまりにも速くセリフが変わったんで、セリフが変わった事に気が付きませんでした。ボタンをクリックするたびに音がするなどの工夫が必要かもしれません。

「褒美を受け取る」ボタンを押します。

Reward画面に切り替わりました。

f:id:kazuhironagai77:20210725232223p:plain

回復薬が1個しかもらえていません。最低の褒美ですね。

戻るボタンを押します。

戦闘前のLevelに戻って来ました。

f:id:kazuhironagai77:20210725232238p:plain

成功ですね。

道具袋を開くと貰った回復薬がしっかり入っていました。

f:id:kazuhironagai77:20210725232252p:plain

そう言えば以下のウィジェット、W_StoneStatueTalkに閉じるボタンがありますがこれの機能を書いた覚えがありません。

f:id:kazuhironagai77:20210725232305p:plain

閉じるを押せばW_StoneStatueTalkが消えて他の石像と会話出来るんでしょうか?

多分出来ないです。が試してみます。

出来ました。

あれ。

実装部を見てみます。

f:id:kazuhironagai77:20210725232319p:plain

うーん。これだけで大丈夫なのでしょうか。何らかのParameterを元の設定にしないといけない気がしますが。

後で調べる事にします。

9.石像を封印する仕組みの作成

これはRPG Game Instance BPにBooleanのarrayを作成して管理します。

管理し易くするために、石像封印専用のStructureをBPで作成しました。

f:id:kazuhironagai77:20210725232338p:plain

このStructureからRPG Game Instance BPにArray、Stone Statue Talkを作成します。

f:id:kazuhironagai77:20210725232351p:plain

このArrayに要素を9個足して、

f:id:kazuhironagai77:20210725232404p:plain

それぞれの石像が封印されているかどうかを管理します。

石像と会話するためのTrigger Box内でkey boardのEを押した時に、Third Person Character内の以下のコードでその石像が封印されているかどうかの確認をします。

f:id:kazuhironagai77:20210725232419p:plain

もしされていたら、新しく作成したWidgetが開き、この石像とは会話出来ない事をPlayerに連絡します。

以下に石像とは会話出来ない事を示すWidgetを示します。名前はNot Allow to talkです。

f:id:kazuhironagai77:20210725232432p:plain

Angel Statue 02を封印してテストしてみます。

f:id:kazuhironagai77:20210725232525p:plain

戦闘終了後に、Angel Statue 02に話しかけてみます。

f:id:kazuhironagai77:20210725232547p:plain

封印されて話せませんでした。

「別の石像に話しかける」ボタンを押すと元の画面に戻りました。

f:id:kazuhironagai77:20210725232602p:plain

出来ています。

10.全部の石像をStone Statue BPと入れ替える

やはりこの状態でテストしないときちんと動くのか不明です。

出来ました。

f:id:kazuhironagai77:20210725232634p:plain

テストします。

戦闘が終了しました。

それぞれの石像をチェックします。

f:id:kazuhironagai77:20210725232650p:plain

因みに、会話出来る石像は以下の3つだけです。

f:id:kazuhironagai77:20210725232705p:plain

AngleStatue02 に話しかけました。

f:id:kazuhironagai77:20210725232719p:plain

会話出来ます。

いいえを選択して隣の石像に話しかけました。

f:id:kazuhironagai77:20210725232732p:plain

Betrayal Statueとも会話できます。

次のStatue01 に話しかけると

f:id:kazuhironagai77:20210725232746p:plain

となりました。

残りの石像も同じ回答でした。

最後のAngle Statueは普通に会話出来ました。

f:id:kazuhironagai77:20210725232759p:plain

出来ているようです。

残念ながら時間がなくなってしまったので今週はここまでとします。残りは来週やります。

11.Warp Passの作成

来週やります。

12.Good Skyの検証

来週やります。

13.まとめと感想

今週は、

  • Niagaraの勉強
  • UE4Effectについての本「HoudiniUnreal Engine 4で学ぶリアルタイムVFX」を読む
  • 戦闘後のアイテムの入手の作成の続き

を行いました。

来週は、

  • Niagaraの勉強としてCGHOW氏のUnreal Engine Niagara Tutorials [5]のどれかを勉強する。
  • Cascadeの勉強の続き、もしくは英語で書かれたUE4Effectについての本を読む
  • 戦闘後のアイテムの入手の作成の続き
  • Warp Passの作成
  • Good Skyの検証

を行います。

今週は、久しぶりに日本語の本を読んだり、絵を沢山描いたのでいつもより疲れました。

<参照(Reference)

[1] Rachel and Jun. (2017, February 17). Why do Japanese mix up “L” and “R”? [Video]. YouTube. https://www.youtube.com/watch?v=F4MsJHn-lRA

[2] Rachel and Jun’s Adventures! (2021, June 30). Can Jun finally tell “R” and “L” apart? [Video]. YouTube. https://www.youtube.com/watch?v=zufKIv4-Q0U

[3] Epic Games. (n.d.). Recreate the Starter Content Smoke Effect in Niagara. Unreal Engine Documentation. Retrieved July 25, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/HowTo/RecreateSmoke/

[4] Epic Games. (n.d.-a). Emitter Update Group. Unreal Engine Documentation. Retrieved July 25, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/EmitterUpdate/

[5] CGHOW. (n.d.). Unreal Engine Niagara Tutorials. YouTube. Retrieved July 25, 2021, from https://www.youtube.com/playlist?list=PLwMiBtF6WzsqC7_cJmD26ts0YDbtPCCfe

 

「Unreal Engine 4.xを使用してRPGを作成する」の足りない部分を作成する 戦闘後のアイテム収得

f:id:kazuhironagai77:20210718215134p:plain

<前文>

Minimal Pairのアプリ開発についてですが、段々腹が座って来ました。有料で公開する事にします。

まず私はアメリカに10年程暮らしていましたが全く言語学を勉強した事がない素人ですので、本来ならば口出しする分野ではありません。しかしMinimal Pairを使用して音素の区別のトレーニングをやってみると、現状存在しているアプリやサイトではあんまり実用的ではありません。

以下にその理由を述べます。

  1. YouTubeにあるMinimal Pairではいつも答えが同じなため、答えを覚えてしまいます。音の区別がついたのかそれとも答えを覚えてしまったのか分からないです。
  2. 練習のためには最低でも5人くらいのNative Speakerに発音してもらう必要があります。一人ではその人の癖を先に覚えてしまいます。
  3. イギリス英語とアメリカ英語の区別がない。特にʌの音。
  4. 聞き取りのテストに使用するのか、音素が区別出来るように訓練するために使用しているのかが曖昧。

それで自分でソフトを作成する事にしました。

Minimal Pairは効果のあるトレーニングです。しかし自分で作成したソフトで遊んでみると意外と完璧でない事も分かって来ました。例えばLとRの音です。しかしこれは練習していくうちにLの音がdark LやLight L以外にもあるような気もしていてそのせいかもしれません。現状は良く分かっていません。

ただしほとんどの音に対してはかなりの効果があります。SとThについては練習すればすぐ区別がつきます。

ので公開して世間一般の評価を仰ごうと思いました。

ただし一般に公開するとなると、録音した発音に著作権が発生する可能性があります。日本における著作権の定義は、作者の思想や感情が表現された文芸・学術・美術・音楽などの表現方法に対する権利ですので、作者の思想や感情が表現するのが不可能な単なる単語の発音に著作権が存在するのかは正直疑問です。しかしアメリカでは単なる単語を書いた文字には著作権は発生しないという判決がある一方で、コンサートで録音した僅か1秒間のクラクションの音を他のMusician が無断で使用したら著作権違反で訴えられたりしています。

そういう訳で念のためにこのソフトのMinimal Pairに使用する音を、私自身でお金を払ってNative Speakerに発音してもらう必要があります。それにはお金がかかります。

最低でも5人くらいのNative Speakerに発音してもらう必要があります。ので有料にならざる得ません。

それで妥協案を考えました。Minimal Pairによる音素の区別がついているかの聞き取りのテストが出来るアプリも同時に開発してそちらは無料で公開する事にします。

例えば、

Fun、Fan

と二つの単語が表示されて音声が一回だけ流れます。その音を聞いてどちらの発音かを判断します。偶然でも50%の確率で当たるため、同じ音で5回程度連続でテストします。

Bug、Bag

Cup、Cap

Hut、Hat

Mud、Mad

のようにです。これで偶然で正解する確率は3%になります。

これで行く事にします。

レーニング用のMinimal Pairですが、現状は

ʌとæのMinimal Pair

???

Fun、Fan

となっていで、???を押すとFunかFanのどちらかの音が出ます。Funを押すとFunの発音が聞けます。Fanを押すとFanの音が聞けます。何度でもです。何度も音を聞いて???の音がどちらか分かったら答えを押します。正解なら次に進みます。不正解の場合は、もう一度練習しますか?と聞かれYesなら同じ問題が、Noなら先へ進みます。

3問ぐらいやります。例えば

Bug、Bag

Cup、Cap

です。読む人は必ず別人にします。

3問終わったら今度はテストです。

Fun、Fanのどちらが読まれます。そして正解だと思う単語を選びます。

Bug、Bagのどちらが読まれます。そして正解だと思う単語を選びます。

Cup、Capのどちらが読まれます。そして正解だと思う単語を選びます。

最後にテストの結果が表示されます。

これを一組として色々な音素のMinimal Pairを何組も作成していきます。

現状はこんな風に考えていますが、Minimal Pairを使用したもっと効果的なトレーニング方法があるならVer2.0ではそちらを採用します。この継続して作成するためにも有料にするのは必要だと判断しました。

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

<本文>

1.今週の予定

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

  • Niagaraの勉強
    • Smokeの実装
  • Cascadeの勉強
    • Sub UVの勉強
  • RPG、戦闘後のアイテム入手
    • 「20%の確率で元の世界に戻らないようにする仕組み」の実装
    • 「石像との会話」の実装
    • Warp Passの検証
    • Good Sky をLandscapeに追加するための検証
  • Dreamscape Nature : Meadows - Stylized Open World Environmentを見る

最後のDreamscape Nature : Meadows - Stylized Open World Environmentは今月、無料で配布されたアセットです。私の作成しているRPGの雰囲気に合いそうなので急遽、検証する事にしました。

2.Niagaraの勉強-Smokeの実装

公式documentのNiagara Visual Effects [1]に以下に示したようなGuideがあります。

f:id:kazuhironagai77:20210718215409p:plain

今週はこの中のRecreate the Starter Content Smoke Effect in Niagara [2]をやっていきます。

2.1 Recreate the Starter Content Smoke Effect in Niagara [2]の勉強

まず勘違いしていたんですが、このDocumentはStarter ContentにあるCascadeのSmoke EffectのサンプルをNiagaraに作り変えるTutorialでした。

それはそれでかなり重要です。というかもっと面白さが増してきました。

更にM_smoke_subUV Materialと

f:id:kazuhironagai77:20210718215432p:plain

Create a Sprite Particle Effect in Niagara [3]で作成したFX_Smoke Emitterを使用するそうです。

Create a Sprite Particle Effect in Niagara [3]って既に勉強している?

調べたら、2021-05-10のブログで

f:id:kazuhironagai77:20210718215521p:plain

と簡単に説明しただけでした。後、2021-05-24のブログで

f:id:kazuhironagai77:20210718215539p:plain

ちょっとだけ引用していました。Spriteの仕組みとはParticleにカメラに対して常に正面を向く面を貼り付けたものである。との仮説を立てていた時にそのままの内容が書かれていた文がCreate a Sprite Particle Effect in Niagara [2]にあったのでそれを引用したんでした。

それだけでした。

何で勉強しなかったんでしょう?

その理由も2021-05-10のブログで説明してありました。

f:id:kazuhironagai77:20210718215616p:plain

要するにCreate a Sprite Particle Effect in Niagara [3]に書かれている事は既に全部知っているから勉強しません。と言う事でした。

でもSub UVの使用方法は知りませんよね。やっぱりCreate a Sprite Particle Effect in Niagara [3]は勉強する必要があります。

2.2 Create a Sprite Particle Effect in Niagara [3]を先に勉強する

こっちを先に勉強します。

Create Sprite Particle Effect in NiagaraはGuideの三番目にあるもっとも基本的なTutorialです。

f:id:kazuhironagai77:20210718215639p:plain

それを今更勉強しなくちゃいけないのか?と思うとがっくりですが、Sub UVの使用方法を勉強出来るのはこのDocumentだけと思うとやる気が爆発してきます。

<Prerequisite Steps

ここでもM_smoke_subUV Materialを使用します。

f:id:kazuhironagai77:20210718215658p:plain

こいつです。

念のため、中身も見ておきます。

まずResult ノードですが先週勉強したM_cloud_lit Materialと同じでBlend ModeがTranslucentにセットされています。

f:id:kazuhironagai77:20210718215714p:plain

f:id:kazuhironagai77:20210718215721p:plain

まずBase Colorのノードから見てみます。

f:id:kazuhironagai77:20210718215741p:plain

成程、Texture Sampleで使用しているTexture、T_Smoke_Tiled_Dは以下に示したように非常に精密な雲のTextureです。

f:id:kazuhironagai77:20210718215757p:plain

一方でTexture Sampleと合成するParticle SubUVに使用されているTexture、T_Smoke_SubUVは以下に示したように8x8の雲のアニメーションを64個の絵で表したものです。

f:id:kazuhironagai77:20210718215812p:plain

T_Smoke_SubUVはアニメーションを表すために一個一個の絵自体は雑にならざる得ません。それを補うために、非常に精密な一枚絵の雲のTextureであるT_Smoke_Tiled_Dと合成しているんです。

正しT_Smoke_Tiled_Dは大きな一枚絵ですので単に合成してもT_Smoke_SubUVに描かれている64個の雲の絵とは一致しません。それを補うのがTexCoord[0] ノードです。

TexCoord[0] ノードのDetailを見るとUTilingとVTilingがそれぞれ8にセットされています。

f:id:kazuhironagai77:20210718215826p:plain

それをTexture SampleのUVsにつなげる事でTexture Sampleに使用されているTexture、T_Smoke_Tiled_Dは8x8の計64個の絵になります。

f:id:kazuhironagai77:20210718215843p:plain

これと先程のT_Smoke_SubUVと合成する事で、T_Smoke_SubUVの一個、一個の絵がT_Smoke_Tiled_Dのような精密な雲の絵に変化する訳です。

f:id:kazuhironagai77:20210718215900p:plain

簡単な例を作成しました。

T_Smoke_SubUV中の一個の絵を以下の絵とします。

f:id:kazuhironagai77:20210718215914p:plain

T_Smoke_Tiled_Dの精密な雲の絵を以下とします。

f:id:kazuhironagai77:20210718215928p:plain

この二つを単純に加算します。

f:id:kazuhironagai77:20210718215950p:plain

アニメーションのための形を維持したまま、雲が細部まで綺麗に表現されています。うん。綺麗な雲になっています。

最後の実装部分は雲に色を追加する為の物ですね。

f:id:kazuhironagai77:20210718220004p:plain

ただ実際の計算値がどうなっているのかは分かりませんね。

白い部分のRGBが1と仮定するとそれに例えばRGBが1,0,1である赤い色を掛けると白い部分が赤くなります。実際は黒い部分が赤くなるはずです。

次はOpacityの実装です。

f:id:kazuhironagai77:20210718220021p:plain

T_Smoke_SubUVのαってどんなイメージが入っているんでしょうか?

f:id:kazuhironagai77:20210718220036p:plain

背景が黒くなっているだけ。

???

分かりました。背景は黒だから値は0です。αの値が0と言う事は透明と言う事になります。

先程のBase Colorで「Particle colorを掛けたら、背景の方が雲より濃い色がついてしまうじゃないか?」の疑問が解けました。Base Colorの時点では背景に更に濃い色が付いているんです。しかしOpacityでその部分は透明にセットされます。

Clampして敢えて0と1の間の値にするのは何故なんでしょう?別に1以上なら完全に不透明になるだけじゃないでしょうか?

最後のノードがDepth Fadeです。

f:id:kazuhironagai77:20210718220053p:plain

このノード、先週の勉強で雲に影をつけるなら外さないといけないノードとして紹介されていたやつです。

公式のdocumentであるDepth Expressions [4] によると

f:id:kazuhironagai77:20210718220126p:plain

と、このノードの機能が説明されていました。

醜い線ってどんな線?と思ったらしっかり図でも説明されていました。

f:id:kazuhironagai77:20210718220142p:plain

この赤い不透明の球と緑の透明な球の境目に出来ている線が醜い線だそうです。

これがDepth Fadeを使用すると

f:id:kazuhironagai77:20210718220155p:plain

こうなるそうです。

うーん。このノードがないと困る時も出て来そうです。

実際、先週、勉強したParticle Shadow Castingに不透明なActorが重なったらどうなるんでしょうか?確認する必要がありますね。後でやります。

これでM_smoke_subUV Materialの実装方法については大体は理解しました。

<Project Setup

ここはNiagara専用のFolderの作成方法やMaterialをcopyしてNiagara用のFolderに移す方法などが説明されていました。本当の初心者以外はスキップして良い部分です。当然スキップします。

<Create the System and Emitter

Simple Sprite Burst Emitterを追加したNiagara systemを作成しています。何でこんなに丁寧に説明しているのかと思ったんですが、良く考えたらこのTutorial、Niagara systemのTutorialの一番最初のヤツでした。そりゃ丁寧に説明しますよね。

f:id:kazuhironagai77:20210718220227p:plain

Documentの説明通りに作成しました。

ここも今の私が学ぶ事はありませんね。

<Change Renderer Settings

ここで初めてSubUVをmaterialに使用した場合のSprite Rendererの設定方法が学べます。

f:id:kazuhironagai77:20210718220257p:plain

まずM_smoke_subUVをmaterialにセットします。

すると以下の様なイメージがPreviewに表示されます。

f:id:kazuhironagai77:20210718220316p:plain

これをSubUV用のRenderingに変換する為にSub Image Sizeのxとyにそれぞれ8をセットします。

f:id:kazuhironagai77:20210718220330p:plain

そしてSubUV Blending Enabledにチェックを入れます。

するとReviewのイメージが以下のように変化します。

f:id:kazuhironagai77:20210718220344p:plain

所でSubUV Blending Enabledは何を管理するParameterなんでしょうか?

公式DocumentのNiagara Renderers [5]によると

f:id:kazuhironagai77:20210718220359p:plain

と書かれています。

同じ様な形の雲をBlendしても違いは分かりません。後でもっと分かり易いMaterialを作成して試してみます。

そしてSmoke SystemをLevel上に配置します。

f:id:kazuhironagai77:20210718220413p:plain

あれ?何も表示されません。

念のためにWireFrameに変えて見ましたがSpriteが生成されていませんね。

f:id:kazuhironagai77:20210718220428p:plain

なんでReviewとイメージが違うんでしょうか?

取りあえずこの問題は無視して先に進みます。

<Edit the Emitter Update Group Settings

ここではEmitter Update Groupの設定をします。

ここでする事はSpawn Burst Instantaneous Moduleを外してSpawn Rate Moduleを追加します。

f:id:kazuhironagai77:20210718220447p:plain

そしてSpawn Rate ModuleのSpawn Rateを50にセットします。

f:id:kazuhironagai77:20210718220500p:plain

こんなに雲の色が濃くなりました。

f:id:kazuhironagai77:20210718220515p:plain

一秒間に50個のSpriteを生成してその雲の寿命が2秒とすると少なくとも1秒間は50枚の雲が重なっている計算になります。雲の色が上記の様に濃くなるのは当然でしょう。

Level上に配置したSmoke Systemには何も表示されません。

f:id:kazuhironagai77:20210718220605p:plain

この理由は直ぐ分かりました。ReviewのようにLoopしないので、一回しか雲を生成していなかったんです。その時を逃したら上記のような何もないイメージしか見れません。

次にEmitter State Moduleの設定を以下の様に変更しました。

f:id:kazuhironagai77:20210718220619p:plain

雲が消えなくなりました。

f:id:kazuhironagai77:20210718220632p:plain

このParameterの中でLoop Durationだけ意味が分かりません。

と言うのは、

Loop DurationはParticleをSpawnする時間を指定しているはずです。

Loop BehaviorをOnceにセットしてテストすると4秒後に雲が消えます。これは2秒間雲がSpawnされてそれぞれの雲の寿命が2秒であるため、最後に生成された雲の寿命が尽きるのは4秒後だからです。

次にLoop Behaviorをinfiniteにセットします。

これって結局Loop Durationがinfiniteになったと言う事だと思うんですが。

そうなるとLoop Durationの値をセットする意味ないですよね。

公式DocumentのEmitter Update Group [6]にはLoop BehaviorとLoop Durationの機能は以下の様に説明されています。

f:id:kazuhironagai77:20210718220648p:plain

f:id:kazuhironagai77:20210718220655p:plain

うん。やっぱりこの説明でもLoop Behaviorをinfiniteにセットした場合は、Loop Durationがinfiniteになったと解釈出来ます。

CursorをLoop Behaviorに重ねた時に表示される説明文が公式DocumentのEmitter Update Group [6]と違っていたのでそちらも読んでみます。

f:id:kazuhironagai77:20210718220738p:plain

Infiniteの場合は、Loop Durationで指定した時間が過ぎたらすぐに次のLoopを開始するとあります。つまりLoop Durationで指定した時間が2秒でも1秒でもその時間が過ぎたらすぐに最初の状態からやり直す訳です。

成程、ある非常に特殊な条件ならばLoop Durationで指定した時間によって何らかの差が出る可能性もありますね。この説明なら。

この辺で納得しておきます。

因みにCursorをLoop Durationに重ねた時に表示される説明文は以下のものでした。

f:id:kazuhironagai77:20210718220759p:plain

0の指定は出来ないというのは豆知識として覚えておきます。

<Particle Spawn Group Settings

この節では主に3つの事を行っています。

  • Initialize Particle ModuleLife Timeの値の調節
  • Initialize Particle ModuleSpriteの位置、角度、そしてサイズの調節
  • SubUVのイメージを全部使用するためのSubUV moduleの追加と設定

最後の「SubUVのイメージを全部使用するためのSubUV moduleの追加と設定」こそが私が知りたい事でこれを最初にやってみます。と言うのはこのDocument通りにやるとSubUV moduleを追加した時には既にspriteがいろんな箇所から発生して実際にSubUVの影響がどうなっているのか良く分からなくなってしまうからです。

以下の様なやり方が説明されていました。

まずSub UV Animation Moduleを追加します。

f:id:kazuhironagai77:20210718220838p:plain

設定は以下の様にします。

f:id:kazuhironagai77:20210718220851p:plain

Documentでは赤で囲った部分の値を変更して上記の値にしてくださいと書かれていましたが、私のはSub UV Animation Moduleを追加した段階で既にそうなっていました。

はい。

結果です。

f:id:kazuhironagai77:20210718221311p:plain

f:id:kazuhironagai77:20210718221319p:plain

雲のイメージは全く変化していません。

うーん。分からん。

ひょっとするとLife Timeの値が影響しているのかもしれません。それを変更してみます。

f:id:kazuhironagai77:20210718221335p:plain

Document通りの設定にしました。

何も変化しません。

もうDocument通りにやってみます。

今度はSpriteのサイズを変更します。

f:id:kazuhironagai77:20210718221351p:plain

しました。

次は回転を追加します。

f:id:kazuhironagai77:20210718221407p:plain

もう雲のイメージが回転し始めてSubUVが効いているのか分からなくなりました。

f:id:kazuhironagai77:20210718221655g:plain

後、ここでDocumentの方で2つの違う値が載っています。多分レアレスミスでしょうね。

f:id:kazuhironagai77:20210718221733p:plain

雲を移動させるために初速度を追加します。

Add Velocity Moduleを追加して

f:id:kazuhironagai77:20210718221752p:plain

以下の設定にします。

f:id:kazuhironagai77:20210718221806p:plain

この辺は基本なのでサラッといきます。

今度はSpriteが発生する場所を変更します。

Sphere Moduleを追加します。

f:id:kazuhironagai77:20210718221822p:plain

このModuleは球を指定してその球の中でSpriteをSpawnするそうです。

f:id:kazuhironagai77:20210718221837p:plain

今回は64にしました。

このModule自体も調べたら結構面白そうですが、なんせSub UV Animation Moduleの使用方法も不明な状態では調べる気が起きません。

<Particle Update Group Settings

最後ですがForceを追加しているだけです。

f:id:kazuhironagai77:20210718221922p:plain

f:id:kazuhironagai77:20210718221929p:plain

もう一つありました。このNiagara systemをAssetとしてSaveしていました。

これでassetにしておいてRecreate the Starter Content Smoke Effect in Niagara [2]で使用する訳ですね。

f:id:kazuhironagai77:20210718221946p:plain

うーん。SubUVについて少しは勉強になりましたが使用方法が判明する所まではいかなかったです。

2.3 SubUVの考察など

SubUVのそれぞれのイメージにアクセスするにはどうしたら良いのかが知りたいですがそれが分かりません。

そしたらどうもSubImage Index Moduleがそれを担当しているらしいです(公式のDocumentのSubImage Index [8]から)。ところがNiagara systemではSubImage Index Moduleはどうもないらしく、代わりにParameterとして存在しているみたいです。

実際に調べて見ると

f:id:kazuhironagai77:20210718222007p:plain

f:id:kazuhironagai77:20210718222016p:plain

そのようです。

それでgameDev Outpost氏のUE4 - Niagara Flipbook - Part 2 – Smoke [7]にSub Image Indexの使用方法が載っていたのでそれを勉強します。

ところで今回使用したSub UV Animation Moduleは何をしているんでしょうか?

公式DocumentのParticle Spawn Group [9]には以下の説明がされていました。

f:id:kazuhironagai77:20210718222046p:plain

うーん。と言う事はSub UV Animation ModuleでもSub UVのそれぞれのイメージを表示はしていたんでしょうか?

ひょっとしてSpawn Rateを50にセットしそれぞれのSpriteの寿命が2秒だったから100個の別々なイメージを保持しているSpriteが重なり合っていたので結果として同じイメージになっていたんでしょうか?

確認します。

Create a Sprite Particle Effect in Niagara [3]でやったのと同じ方法で、Simple Sprite Burst Emitterを含むNiagara systemを作成します。

Sprite RendererのMaterialをM_smoke_subUVに変更します。

更にSprite RendererのSub Image sizeを8,8にします。

次にParticle Update にSub UV Animation moduleを追加します。

f:id:kazuhironagai77:20210718222148g:plain

アニメーションになっていましたね。

Sub UV Animation moduleのNode Graphicsを見たら以下の様にSub Image Indexが沢山使用されていました。

f:id:kazuhironagai77:20210718222215p:plain

かなり回り道をしながらですが少しはSub UVの使用方法が分かって来ました。

2.4 UE4 - Niagara Flipbook - Part 2 – Smoke [7] の勉強

気が付いたらNiagaraだけでかなり時間を使ってしまったので今週は、Sub Image Indexの使い方だけ勉強します。

まずSubUVの最初のImageがSpriteに表示されるようにします。

Particle Spawn GroupにSet new or existing parameter directly Moduleを追加します。

f:id:kazuhironagai77:20210718222243p:plain

こんな感じです。

f:id:kazuhironagai77:20210718222319p:plain

Set Parametersの右端の+ボタンを押してSub Image Indexを追加します。

f:id:kazuhironagai77:20210718222332p:plain

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

f:id:kazuhironagai77:20210718222346p:plain

そしてこの数字を弄ると

f:id:kazuhironagai77:20210718222403g:plain

SubUVのイメージが変わります。

うん。変わるんだけとT_Smoke_Tiled_Dのイメージは全く動いていないのも分かってしまいましたね。

残りは来週やる事にします。

3.Cascadeの勉強-Sub UVの勉強

3.1 CascadeにおけるSub UVの使用方法

今週はCascadeにおけるSub UVの使用方法を勉強します。

で、Niagaraで一応Sub UVの設定方法を理解したので適当にやってみます。

f:id:kazuhironagai77:20210718222459g:plain

出来ました。

作り方を説明します。

Particle systemから新しいParticle systemを作成します。

f:id:kazuhironagai77:20210718222526p:plain

Spriteが移動していると見にくいので、Initial Velocity Moduleを外します。

f:id:kazuhironagai77:20210718222540p:plain

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

Initial Size Moduleを弄ってSpriteのサイズを大きくします。

f:id:kazuhironagai77:20210718222601p:plain

f:id:kazuhironagai77:20210718222607p:plain

Required ModuleのMaterialにセットされているMaterialをSub UV用のMaterialに変更します。(見えにくいのでBack Ground Colorを白に変更しました。)

f:id:kazuhironagai77:20210718222623p:plain

Material はNiagaraで使用したM_smoke_subUVを使用しました。

一個のイメージだけを写すためにSub UVの値を8、8にセットします。

f:id:kazuhironagai77:20210718222641p:plain

Sub UVはRequired Module内にありました。

f:id:kazuhironagai77:20210718222655p:plain

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

これをAnimationにする為にSub Image Index Moduleを追加します。

f:id:kazuhironagai77:20210718222709p:plain

全てのイメージを表示するためにSub Image Index Moduleの1のOut Valに63をセットします。

f:id:kazuhironagai77:20210718222723p:plain

f:id:kazuhironagai77:20210718222732p:plain

はい。

f:id:kazuhironagai77:20210718222753p:plain

あれ?

先程やった時は出来たんですが今回はイメージが全く変化しません。

先程やった奴と比べたら、先程のはRequired ModuleのInterpolation Methodの値がLinearになっていました。

f:id:kazuhironagai77:20210718222807p:plain

直しました。

それでもAnimationになりません。

f:id:kazuhironagai77:20210718222822p:plain

むむむ。

あ、Spawn ModuleのSpawn Rateが初期値のままでした。

f:id:kazuhironagai77:20210718222841p:plain

一秒間に20回も同じ位置でSpriteを生成していたら全部が重なり合って一つのイメージに収束してしまいます。

Spawn ModuleのSpawn Rateの値は0にしてBurstの値を5に変更しました。

f:id:kazuhironagai77:20210718222857p:plain

これで5個のSpriteが同時に同じ場所で生成されるはずです。

f:id:kazuhironagai77:20210718222932g:plain

SubUVのアニメーションが出来ました。

微調整をします。

次のLoopが始まるまでに少し間がほしいのでLoop Delayの値を変更します。

Loop DelayではなくてEmitter Delayでした。場所はRequired Module内にありました。

f:id:kazuhironagai77:20210718223001p:plain

2秒に変更しました。

Smokeの動きも少し速い気がします。Life timeを長くしてみます。

Life Time ModuleのLife timeの値を2秒にしました。

f:id:kazuhironagai77:20210718223021p:plain

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

f:id:kazuhironagai77:20210718223034g:plain

こんだけ出来れば十分です。

3.2  先週作成したParticle Shadow CastingのDepth Fade Nodeについて

先週のブログ

f:id:kazuhironagai77:20210718223113p:plain

Depth Fade Nodeを使用すると影が出来ないので外す事を習いました。

先程、「2.2 Create a Sprite Particle Effect in Niagara [3]を先に勉強する」で勉強しましたが、公式のdocumentであるDepth Expressions [4]で

f:id:kazuhironagai77:20210718223128p:plain

Depth Fade Nodeが無いと見た目が結構やばくなる事を勉強しました。

この問題は先週作成したParticle Shadow Castingは回避しているんでしょうか?

それを確認します。

Third Person Characterをそのまま突っ込ませてみました。

f:id:kazuhironagai77:20210718223153p:plain

別に普通です。

うーん。もう少し深く知りたいですが今の知識でDepth Fade Nodeの中の実装方法を理解するのは無理です。今回はこの問題についてはこの辺で諦めるしかなさそうです。

4.Ch4_3の確認

そういえば先週、Ch4_3 がオカシクなって途中で止めたんでした。すっかり忘れていました。

久しぶりにVisual Studio を開いてそのままにしてBlogを書いていたらVisual Studioの挙動がおかしくなって途中で中止したんでした。

Buildしてみました。

f:id:kazuhironagai77:20210718223218p:plain

大丈夫そうですね。

一応ゲームもPlayして確認します。

普通に出来ました。

ただし一個バグを見つけてしまいました。

f:id:kazuhironagai77:20210718223234p:plain

BlockからPlayerの操作するキャラが出ているのにMonsterが消滅しません。後でこのバグを検証します。

5.RPG、戦闘後のアイテム入手-「20%の確率で元の世界に戻らないようにする仕組み」の実装

はい。これはほとんど先週の検証で出来ています。

先週、検証したRPGGameModeBPのBranchを追加したところに更にBranchを追加します。

f:id:kazuhironagai77:20210718223258p:plain

これで5回に1回は戻らなくなるはずです。

f:id:kazuhironagai77:20210718223315p:plain

戦闘を何回かすると元のLevelに戻らなくなりました。

骸骨が回っていると3D 酔いが凄いです。消します。

Level内に配置されているActorに何かをする時はRPG Game Mode BPにEvent Dispatcherを作成してそれにやらせると簡単です。

RPG Game Mode BP内にEvent Dispatcherを作成します。

f:id:kazuhironagai77:20210718223342p:plain

Delete Skull BPと名付けました。

Battle Field のLevel BP内で以下に示した様にBindさせます。

f:id:kazuhironagai77:20210718223356p:plain

これで空中に浮遊している骸骨は消えるはずです。

戦闘後にアイテムがもらえる時はこのDispatcherを呼び出します。

f:id:kazuhironagai77:20210718223413p:plain

テストします。

f:id:kazuhironagai77:20210718223427p:plain

骸骨が消えました。

先週作成したWidgetを追加します。

f:id:kazuhironagai77:20210718223444p:plain

RPG Game Mode BPから追加しました。

f:id:kazuhironagai77:20210718223503p:plain

Battle Field のLevel BPから追加するのとどっちが整合性があるんでしょうか?分かりません。

以下の様になりました。

f:id:kazuhironagai77:20210718223518p:plain

Widgetを消すボタンが必要ですね。作成します。

f:id:kazuhironagai77:20210718223536p:plain

f:id:kazuhironagai77:20210718223547p:plain

しました。

テストしたら普通にこのWidgetが消えました。

最後にですが、イラストの紋章が気に入りません。

f:id:kazuhironagai77:20210718223602p:plain

f:id:kazuhironagai77:20210718223607p:plain

直します。

f:id:kazuhironagai77:20210718223622p:plain

直しました。

6.RPG、戦闘後のアイテム入手-「石像との会話」の実装

6.1 「石像との会話」の実装方法について

こんな感じで考えています。まずNPC_Person BPに似たStone‗Statue BPを作成します。

NPCとの大きな違いはTrigger boxは外付けでStone‗Statue BPの変数の一つがTrigger Boxになります。残りの仕組みは同じにします。

  9体の石像全て作成せずにenumで対応します。

Exclamation markの実装ですが

f:id:kazuhironagai77:20210718223649p:plain

f:id:kazuhironagai77:20210718223657p:plain

こんな複雑な事をしなくてもBoxに侵入したら反応するでOKだと思います。

NPCの製作でスパゲティコードになってしまった原因は、RPG Game Mode BP内のMy Place For Event変数の値にNPCはまとめて一つにしなかった事です。

ので以下のようにそれぞれのNPCに対して全部別の対応を作成する必要が出来てしまいました。

f:id:kazuhironagai77:20210718223713p:plain

石像との会話では開くWidgetも全部同じにします。

f:id:kazuhironagai77:20210718223727p:plain

そしてそのWidgetの中でセリフやイメージを変えるようにします。

ただし、この方法を採用した場合はどの石像と話しをしたのかを記憶する変数が必要になります。それはRPG Game Mode BP内に作成する事にします。

取りあえずここまで制作します。

6.1 Stone Statue BPの作成

Stone Statue BPはActor クラスから作成しました。

Static Mesh、TextRender、そしてPoint Lightを追加します。

f:id:kazuhironagai77:20210718223749p:plain

TextRenderはExclamation markを表しPoint Lightがそれを照らします。

f:id:kazuhironagai77:20210718223806p:plain

ただしそれはその石像と会話出来る時だけです。

更に変数としてTrigger BoxをInstance Editableにして追加します。

f:id:kazuhironagai77:20210718223819p:plain

Trigger Boxの名前はStone Statue Talkにしました。

実際のTrigger Boxは別にLevel 内に静的に配置します。それをStone Statue TalkにAssignします。

Trigger Boxに侵入したらExclamation markが光ります。

f:id:kazuhironagai77:20210718223835p:plain

これでテストします。

2体のStone Statue BPを配置しました。

f:id:kazuhironagai77:20210718223848p:plain

それぞれのStone Statue Talkは別のTrigger BoxにAssignされています。

f:id:kazuhironagai77:20210718223903p:plain

f:id:kazuhironagai77:20210718223910p:plain

Boxに侵入する前です。Exclamation markは見えません。

f:id:kazuhironagai77:20210718223933p:plain

右のBoxに侵入しました。

右の石像のExclamation markが発現しました。

f:id:kazuhironagai77:20210718223950p:plain

予測した通り、左の石像のExclamation markは反応していません。

6.2 石像の種類を示すEnumを作成する。

はい。出来ました。名前はE_StoneStatueとしました。

f:id:kazuhironagai77:20210718224010p:plain

名前ですがそれぞれの石像のStatic meshの名前をそのまま入れました。

後で訳わからなくなるのを防ぐためです。

f:id:kazuhironagai77:20210718224025p:plain

6.3 Stone Statue BPの表示する石像を選択出来る様にする

Stone Statue BP内に先程作成したE_StoneStatueから作成した変数Stone Statue Nameを追加します。

f:id:kazuhironagai77:20210718224047p:plain

そのまま実装するとまたスパゲティコードになってしまうので関数を作成します。名前はReturn Statue Meshとします。

f:id:kazuhironagai77:20210718224105p:plain

E_StoneStatueの要素から石像のStatic meshを選択して返す関数です。

その関数を使用して石像の種類を変更出来るようにしました。

f:id:kazuhironagai77:20210718224227p:plain

テストします。

左の石像はBetrayal Statueになるように設定しました。

f:id:kazuhironagai77:20210718224242p:plain

なっていますがサイズが全く違います。サイズの設定も必要です。

f:id:kazuhironagai77:20210718224257p:plain

それぞれの石像のサイズも追加します。

Return Statue Mesh()関数の返し値にそれぞれの石像のscaleの値も返すようにします。

f:id:kazuhironagai77:20210718224311p:plain

それぞれの石像のScale値はBattle Field mapに配置されているそれぞれの石像のScale値をそのまま使用します。

f:id:kazuhironagai77:20210718224325p:plain

例えばBetrayal Statueならば

f:id:kazuhironagai77:20210718224342p:plain

X=3、y=3、そしてz = 3 です。

f:id:kazuhironagai77:20210718224358p:plain

テストします。

f:id:kazuhironagai77:20210718224413p:plain

良い感じです。ほかの石像も試してみます。

Statue 01 です。

f:id:kazuhironagai77:20210718224427p:plain

げ。向きが逆です。Rotationの値も設定しないといけないようです。

f:id:kazuhironagai77:20210718224459p:plain

直しました。

f:id:kazuhironagai77:20210718224529p:plain

他の石像も調べます。

f:id:kazuhironagai77:20210718224546p:plain

5番目の石像であるSM_Skeleton Headです。

f:id:kazuhironagai77:20210718224603p:plain

今度は高さの変更が必要です。

f:id:kazuhironagai77:20210718224632p:plain

はい。追加しました。

こうなりました。

f:id:kazuhironagai77:20210718224648p:plain

この骸骨、SM_Skeleton Headは20倍のScaleなんでちょっと雑な作りに見えますね。

f:id:kazuhironagai77:20210718224705p:plain

f:id:kazuhironagai77:20210718224713p:plain

f:id:kazuhironagai77:20210718224724p:plain

f:id:kazuhironagai77:20210718224737p:plain

やっと出来ました。

6.4 石像との会話用のWidgetを作成する。

先にWidgetを作成します。このWidgetは9体全ての石像に対応しています。

Oldman Welcome ウィジェットをコピーして改良して作成する事にします。

f:id:kazuhironagai77:20210718224815p:plain

流石に今から9体の石像の絵を描いている時間もアイデアもありません。以下のデザインで行きます。

f:id:kazuhironagai77:20210718224830p:plain

勿論後で差し替えます。

それぞれの石像のBGIは以下の関数で変更します。

f:id:kazuhironagai77:20210718224844p:plain

WidgetのImageにTextureを動的に指定する場合、Make Slate Brushノードを使用する必要がありました。

f:id:kazuhironagai77:20210718224858p:plain

すっかり忘れていました。

これでそれぞれの石像で別なBGIを表示するwidgetは出来たはずです。

テストします。

6.7 石像との会話用のWidgetを表示するための実装をする

これが結構面倒くさいはずです。

丁寧にやっていきます。

まずEnumのEPlaceForEventsに石像との会話用の要素を追加します。

f:id:kazuhironagai77:20210718224919p:plain

PE_TalkStoneStatueとします。

Buildします。

f:id:kazuhironagai77:20210718224933p:plain

当たり前ですが成功しました。

思い出したんですがRPGGameModeのEnumを書き変えた時は、その新しい要素がBPまで反映されるには一端UE4Editorを閉じる必要がありました。多分、.24以降ならそんな問題はなかったはずですが。

UE4Editorを開きなおしたらPE_TalkStoneStatueがBPからも使用出来るようになっていました。

f:id:kazuhironagai77:20210718224948p:plain

StoneStatueBPでTrigger Boxに侵入した時にRPGameModeBP内の変数、My Place For Eventsの値がPE_TalkStoneStatueになるようにセットしました。

勿論、Trigger Boxから退散した時はMy Place For Eventsの値がPE_Noneになるようにセットします。

f:id:kazuhironagai77:20210718225002p:plain

今回の石像との会話はもう一個変数が必要です。

RPGameModeBP内にそれを作成します。EnumのE_Stone Statue タイプの変数です。

f:id:kazuhironagai77:20210718225016p:plain

名前はStone Statue Talkingとしました。

この変数もStoneStatueBPでTrigger Boxに侵入した時に値が変わります。

f:id:kazuhironagai77:20210718225030p:plain

これで準備は出来ました。

ThirdPersonCharacterのBPからStoneStatueBPに侵入した時に開くwidgetをセットします。

RPGameModeBP内の変数、My Place For Eventsの値がPE_TalkStoneStatueだった時、

f:id:kazuhironagai77:20210718225043p:plain

W_StoneStatueTalkウィジェットを開くようにします。

f:id:kazuhironagai77:20210718225056p:plain

これで出来たはずです。

テストしてみましょう。

一番目の天使の石像に話しかけました。

f:id:kazuhironagai77:20210718225135p:plain

一番目のBGIが表示されています。

文章はまだ作成していないのでNPC_Oldmanのままです。これは次に直します。

今度はとなりの石像に話してみます。

f:id:kazuhironagai77:20210718225150p:plain

この石像は9番目の石像でした。

BGIは正確に表示されています。

6.8 石像との会話を作成する。

それぞれの石像の会話を作成します。と言ってもセリフ中身は後で考えます。今週は取りあえず動く事だけ確認します。

先週の検討では、石像との会話は簡単でNPCのような複雑な仕組みは要らないと結論づけました。しかしNPCで作成した会話のシステムは大変優れているのでそれをそのまま使用する事にしました。

以上の事を踏まえて以下のセリフを作成しました。

f:id:kazuhironagai77:20210718225213p:plain

1のセリフの石像の名前の部分だけ変えて9種類作成しました。

これをWidgetから呼び出します。

9柱の石像でそれぞれセリフが違うので関数を作成して呼び出します。

f:id:kazuhironagai77:20210718225226p:plain

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

f:id:kazuhironagai77:20210718225241p:plain

後はAnswer ButtonもW_StoneStatueTalkウィジェット様に作り直しました。

f:id:kazuhironagai77:20210718225254p:plain

Answer Buttonは以下の実装部でParent Widgetを呼ぶ時にそのWidgetが正確に親Widgetである必要があります。

f:id:kazuhironagai77:20210718225309p:plain

ので親のWidgetのタイプだけAnswer Button ウィジェットが必要になります。

テストします。

f:id:kazuhironagai77:20210718225322p:plain

はい。指定したセリフが表示されています。はいといいえの文字の配置がおかしいですね。これは後で直します。

「はい」ボタンを押すと

f:id:kazuhironagai77:20210718225334p:plain

となりました。

「いいえ」ボタンでは

f:id:kazuhironagai77:20210718225350p:plain

こちらも正確に表示されました。

6.9 Itemの受け取り方法について

Item受け取り用のWidgetは別に作成します。のでそのWidgetをどうやって開けるかが問題になります。

「汝に褒美を与える。」と言った後に、そのWidgetが開けるようになると良いのですが、このセリフはData Tableで管理しているためBPで干渉する事が出来ません。

f:id:kazuhironagai77:20210718225416p:plain

そこで以下の様にしました。

「汝に褒美を与える。」と石像が答えた後に、「褒美を受け取る」ボタンを表示させます。

f:id:kazuhironagai77:20210718225430p:plain

このボタンをクリックするとRewardと書かれたコメントを表示するように指示が出ます。

f:id:kazuhironagai77:20210718225443p:plain

しかし実際には、このコメントがData tableから返されるや否や、以下に示したように、BranchのTrueに送られます。(W_StoneStatueTalkウィジェットのConversation Start Event内の実装です。)

f:id:kazuhironagai77:20210718225457p:plain

この後でItemを得るWidgetを開けば良いはずです。

6.10 Item受け取りのためのWidgetの作成

Itemを受け取るWidgetは最終的には複雑になるかもしれませんが今回は非常に簡単にします。

名前はGet Items ウィジェットにしました。

f:id:kazuhironagai77:20210718225517p:plain

まず、上のコメントですが、褒美の種類と数が変えられるようにします。

どの石像に話しかけたのかを確認します。

f:id:kazuhironagai77:20210718225530p:plain

Angle Statue 02の場合は、Data TableのReward Enumから褒美の種類と数を決定します。

f:id:kazuhironagai77:20210718225545p:plain

Data TableであるReward Enumは以下の様な作りになっています。

f:id:kazuhironagai77:20210718225557p:plain

Reward がItemの種類、NumberがそのItemの個数を表しています。

その中からRandomに一個選びます。

f:id:kazuhironagai77:20210718225611p:plain

選ばれた値をGet Items ウィジェットの変数であるReward とNumberに保存します。

f:id:kazuhironagai77:20210718225624p:plain

これらの値は後で、戻るボタンを押した時に使用するからです。

RewardとNumberの値をAppendノードで合成して文章にします。それを別の変数であるCommentに保存します。

f:id:kazuhironagai77:20210718225638p:plain

そのComment変数に保持されているTextを先程のコメント欄に表示します。

f:id:kazuhironagai77:20210718225651p:plain

こんな感じです。

f:id:kazuhironagai77:20210718225706p:plain

次にボタンの機能を追加します。

f:id:kazuhironagai77:20210718225719p:plain

ボタンが持つ機能は二つあります。一つ目は貰ったアイテムを道具袋に追加する事です。そして2つ目は元のLevelに戻る事です。

貰ったアイテムを道具袋に追加する方から実装します。

最初のノードはReward変数に保持されているアイテムの名前が本当にData Tableのアイテムにあるのか確かめます。

f:id:kazuhironagai77:20210718225732p:plain

これはItemはData Tableで管理しているので常にスペルミスをする可能性があるからです。最終的にはenumに変更するのかどうか、今の時点では不明ですが、Data Tableで管理しているため、微妙なゲームバランスの調整は出来るようになっています。

次のノードでNumber変数に保持されている値だけLoopします。勿論Loopの中でReward変数内に保持されているItemをRPG Game Instance のArrayであるItemsに要素として追加します。

f:id:kazuhironagai77:20210718225746p:plain

これで道具袋にもらったアイテムが追加されたはずです。

次に元のLevelに戻る実装を作成します。

f:id:kazuhironagai77:20210718225800p:plain

元のLevel名はRPG Game Instance BP内の変数、Map Name Before Battleに保持されています。それを利用して元のLevelに戻ります。

だたし、今テスト用にMap1に配置されているStone Statue BPは元々、元のLevelにいます。

f:id:kazuhironagai77:20210718225815p:plain

のでTestのために元のLevelに戻る実装は外して、同じLevel内でWidget画面から普通のPlay画面に戻る別の実装をおこないます。

まずこのWidgetを消します。

f:id:kazuhironagai77:20210718225837p:plain

これ最初にやったらこの後に続くノードは実行されないんじゃないの?と疑問に思うんですが何故か実行はされています。まあテスト用ですし、あまり深くは考えません。

その後で、Player の操作するキャラを固定していた機能を解除したり、Play画面でカーソルが消える事が無いようにします。

f:id:kazuhironagai77:20210718225853p:plain

これでテストします。

褒美は回復薬が5個です。

f:id:kazuhironagai77:20210718225909p:plain

「戻る」ボタンを押すとPlay画面に戻りました。

f:id:kazuhironagai77:20210718225924p:plain

道具袋を開けると回復薬が5個入っています。

f:id:kazuhironagai77:20210718225938p:plain

成功ですね。

回復薬の数もランダムになっている様です。

f:id:kazuhironagai77:20210718225954p:plain

f:id:kazuhironagai77:20210718230003p:plain

今週はここまでで、一端中止して検証します。

自分で発見しておいてあれですが、Preparation and Implementation Programmingの効果は凄いです。本当に先週、調査した箇所まで実装出来るとは。信じられない効率です。

6.10 石像との会話とアイテムの入手 -機能の追加と改良点-

石像との会話ではWidgetに表示する石像のイラストは全部描き直す必要があります。

f:id:kazuhironagai77:20210718230028p:plain

石像との会話では、実装部分はこれで良いと思います。特に何処かを改良する必要はないと考えています。

唯一直す必要がある箇所は、返事のボタンに表示されるTextです。

f:id:kazuhironagai77:20210718230044p:plain

何で2行に渡って書かれているんでしょうか?謎です。これは後で直します。

石像からのアイテムの入手手順ですが、

Get Item ウィジェットが開き、

f:id:kazuhironagai77:20210718230058p:plain

その中でどの石像からItemをもらうのかによって対応を変化しています。

f:id:kazuhironagai77:20210718230112p:plain

これは今思ったんですが、どの石像からItemをもらうのかによって開くWidgetを変えた方が色々なItemや武器を貰う事が出来るようになります。

のでそのように改良します。これは来週やります。

後、戦闘中に石像と会話が出来ないような実装を作るのを忘れていました。これも来週追加します。

もう1つコードを書いている間に思い付いた事を書いておきます。

9柱の石像全てと最初から会話出来るのではなく、ほとんどの石像が最初は封印されているようにします。物語が進むにつれて段々、石像と会話が出来るようになるようにします。

7.RPGWarp Passの検証

Warp passはWarpをするのに必要なItemとします。

Warp Passには種類があります。

Warp Passの欠片:10個でWarp Passが作れる。ただし魔法合成屋に行く必要がある。

Warp Pass:普通のWarp Pass

青いWarp Pass:ある特別なWarp Spotは移動するのに青いWarp Passが必要。

赤いWarp Pass:普通のWarp Spotに赤いWarp Passを使用すると別な場所に行ける。

黄金のWarp Pass:効果は不明。世界に一個だけある金で出来たWarp Spotで使えるらしい。

銀のWarp Pass:死者の国に行けるらしい。2枚あれば死者を生き返らせる事も出来る?

銅のWarp Pass:天使の国、や悪魔の国、そして竜の国など人間が通常は行く事が許されない場所にいけるらしい。

こんなんでどうでしょうか?

8.Good Sky Landscape 4に追加するための検証

Good SkyをLandscape4 に追加出来るのは来週以降になるのは確実なので今調べても無駄になってしまいます。ので今週はパスします。

9.Dreamscape Nature : Meadows - Stylized Open World Environmentを見る

Epic Games社の今月のFree AssetであるDreamscape Nature : Meadows - Stylized Open World Environmentが今制作中のRPGの世界観に合いそうなのでサラッとですが見てみます。

f:id:kazuhironagai77:20210718230201p:plain

Demoから開いて見ます。

8.1 Demoの見学

f:id:kazuhironagai77:20210718230222p:plain

f:id:kazuhironagai77:20210718230232p:plain

かなりToon調で良いですね。

f:id:kazuhironagai77:20210718230248p:plain

木の作りが良いです。Toon調ですが葉の付き方が本物の木の様なもっさり感があります。

f:id:kazuhironagai77:20210718230304p:plain

水もToon調ですね。Water simulationを使用しているんでしょうか?

f:id:kazuhironagai77:20210718230319p:plain

滝の部分ですがToon調にかなり改良している感じです。

f:id:kazuhironagai77:20210718230334p:plain

滝の周りには霧も立ち込めています。

f:id:kazuhironagai77:20210718230349p:plain

岩はかなり単純な作りのようです。

所々に以下に示した様な透明な板があります。

f:id:kazuhironagai77:20210718230425p:plain

FX_fog_Cardと書かれています。何をしているのかは不明です。

Landscapeですが丸いです。

f:id:kazuhironagai77:20210718230439p:plain

こんな作り方も出来るんですね。

黄土色の部分を選択したら以下の様にBPと表示されました。

f:id:kazuhironagai77:20210718230624p:plain

ひょっとするとLandscapeは使用していないのかもしれません。

f:id:kazuhironagai77:20210718230640p:plain

うーん。このTextureの繰り返し感はLandscapeを使用してそうですが。

f:id:kazuhironagai77:20210718230655p:plain

この白い板は何をしているんでしょうか?

f:id:kazuhironagai77:20210718230721p:plain

となっていますね。

World Outlinerから使用されているActorを調べると以下の様に大量のEffectがありました。

f:id:kazuhironagai77:20210718230739p:plain

Niagaraで作成されたのかと思ったのですが全部Cascadeでした。

MapのFolder内にLandscapeがありました。

f:id:kazuhironagai77:20210718230755p:plain

あれ。と思ってチェックしたら

f:id:kazuhironagai77:20210718230831p:plain

滅茶苦茶小っちゃい領域をカバーしていました。元からある分を残しておいた感じです。

Post Process Volumeもありました。

f:id:kazuhironagai77:20210718230848p:plain

これはまだ勉強していないので見ても良く分かりません。

Toon調にするためにPost Process Volume内で何かしているんでしょうか?

たき火がありました。

f:id:kazuhironagai77:20210718230905p:plain

流石に火はToon調ではなかったです。

Rainbowなんてのがありました。

f:id:kazuhironagai77:20210718230920p:plain

ほとんど見えませんが綺麗です。

BenchなどのAssetがありました。

f:id:kazuhironagai77:20210718230935p:plain

見た目はToon調ですが影がしっかり載っています。

使用しているMaterialのNormalを調べたらしっかりNormal ノードからデータが渡されていました。

f:id:kazuhironagai77:20210718230949p:plain

やっぱり影はMaterialのNormalで指定されるみたいですね。

草ですが生え方が複雑で作り物感がないです。

f:id:kazuhironagai77:20210718231004p:plain

SM_Bushes_Newと言う名前でした。

花ですが全部静的に配置されています。

f:id:kazuhironagai77:20210718231020p:plain

Landscape4を制作した時に使用したGrass Toolを使用して一気に追加出来るのか試したいです。

パッと見で面白そうなのはこの位です。

あっ。もう一つ忘れていました。

空です。BP_Sky_Sphere_Stylizedと言う名前になっています。

f:id:kazuhironagai77:20210718231036p:plain

これはどうやって作成したんでしょうか?

Toon調でありながら非常にきれいです。

8.2 Showcaseの見学

全体像です。

f:id:kazuhironagai77:20210718231054p:plain

思っているよりActorの数は少ないです。

f:id:kazuhironagai77:20210718231109p:plain

細かいActorはこれだけです。これ位だったらBlenderを勉強し直したら自分で作成できそうです。

山のActorです。

f:id:kazuhironagai77:20210718231123p:plain

これは駄目でしょう。Textureの繰り返しが丸見えです。

2,3カ月前まで私も同じような岩肌を作成していたくせに偉そうです。

8.3 その他の部分の見学

BPです。

f:id:kazuhironagai77:20210718231208p:plain

HUDクラスが何をしているのかが分かりません。それ以外は中身をみて勉強すれば大体理解出来そうです。

今週は見学だけなので中身は見ませんが。

Effectです。

f:id:kazuhironagai77:20210718231223p:plain

全部、Cascadeで作成されています。やっぱり今もCascadeの方が実用的なんでしょうか?

Foliageです。

f:id:kazuhironagai77:20210718231239p:plain

うーん。Bushは非常にきれいです。ぜひRPGの何処かで使用したいです。

Propです。

f:id:kazuhironagai77:20210718231253p:plain

うーん。今使用しているAssetと比べて特別凄い気はしませんね。影が出るのでその辺が長所かな。

Treeです。

f:id:kazuhironagai77:20210718231306p:plain

木はどれも綺麗です。今更ですがLandscape4の木と交換するか迷います。

Waterです。

f:id:kazuhironagai77:20210718231320p:plain

これも使用するか迷いますね。

Toon調の滝の作成方法の勉強には結構良い気がしています。

8.4 見学した感想

実用面から言うと、木や茂みは非常に綺麗で何処かで使用したいです。小物系は影があるので影のないのと交換する形なら使用してもいいかなと言う感じです。岩や山は要らないです。

Toon調の勉強面から言うと、滝や空、そして虹のBPはどうやって作成したのか結構勉強になると思います。後でBPを見てみます。

FXは一応全部見てみます。勉強になる事はいっぱいあると思います。

10.まとめと感想

今週の勉強した内容です。

  • NiagaraCascade共にSub UVの使用方法がとうとう分かりました。
  • RPGでは石像との会話と石像からのItemの入手を実装しました。
  • Warp Passの検証を行いました。
  • 今月のFree AssetであるDreamscape Nature : Meadows - Stylized Open World Environmentをざっと見ました。

来週の予定ですが、

  • Niagara Cascadeの勉強
  • 石像との会話と石像からのItemの入手
    • それぞれの石像のBack Ground Imageの作成
    • それぞれの石像からItemを貰うときに開くWidgetの作成
    • それぞれの石像のセリフの作成
    • 戦闘中に石像と会話出来ない仕組みの作成
    • 石像を封印する仕組みの作成
  • Warp Passの作成
  • Good Skyの検証

をやる予定です。

流石に今週は疲れました。

11.参照(Reference

[1] Epic Games. (n.d.-e). Niagara Visual Effects. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/

[2] Epic Games. (n.d.-g). Recreate the Starter Content Smoke Effect in Niagara. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/HowTo/RecreateSmoke/

[3] Epic Games. (n.d.-a). Create a Sprite Particle Effect in Niagara. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/HowTo/SpriteEffect/

[4] Epic Games. (n.d.-b). Depth Expressions. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Materials/ExpressionReference/Depth/#depthfade

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

[6] Epic Games. (n.d.-c). Emitter Update Group. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/EmitterUpdate/

[7] gameDev Outpost. (2020, September 23). UE4 - Niagara Flipbook - Part 2 - Smoke [Video]. YouTube. https://www.youtube.com/watch?v=okrHUHunPIQ

[8] Epic Games. (n.d.-h). SubUV Modules. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/ParticleSystems/Reference/Modules/SubUV/

[9] Epic Games. (n.d.-f). Particle Spawn Group. Unreal Engine Documentation. Retrieved July 18, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/ParticleSpawn/

 

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

f:id:kazuhironagai77:20210711205519p:plain

<前文>

2021-06-27のブログの前文でɑの音がアーに聞こえる単語とオーに聞こえる単語があると話しました。

私にはどうしてもこの音が同じ音には聞こえません。しかし同じ事を言っている人は一人も見つかりません。これはノイローゼになってしまったのかなとも思いましたが、確認する方法を思い付ました。

それは唇の形を見る事です。

アメリカ英語のɑの音は以下のVowel Chart [1]によると

f:id:kazuhironagai77:20210711205553p:plain

右下の唇を丸めない音です。ɑの音は唇を丸めて発音する事でɒの音(いわゆるオーの音)に変化します。

Vowel Chart [1]には一般的なアメリカ英語のVowel Chartも載っていてそれによると

f:id:kazuhironagai77:20210711205613p:plain

唇を丸めて発音するɑの音、つまりɒの音はありません。

更にCot–caught mergerが起こるとこのɑの音とɔの音がɑの音になってɔの音も無くなります。つまりオの音が無くなる訳です。上の図だと元から消えていますね。ただし二重母音(diphthong)のoʊは有りますのでオウの音はあります。上の図のOはoʊを表しているのかそれとも単独でoの音があるとしているのかちょっと分かりません。

で、思い付いたんですが、この「アメリカ英語にはɒの音がない」と言うのが怪しいのではないのかと。

だったらɑの音の単語を発音している時の唇を見れば区別がつくんじゃないのか。と閃きました。

そこでyouglish [2]の出番ですよ。

October (ɑkˈtoʊbər)で調べて見ました。

このɑの音、私にはオにしか聞こえません。

f:id:kazuhironagai77:20210711205639p:plain

0.5倍速にしてOの発音が聞こえた時に一時停止して唇の形が見えるものを切り抜きました。

はい。唇が完全に丸くなっています。

やっぱり、と思ったんですが、ˈtoʊの発音の口の形をしている可能性もあります。一時停止するのが遅すぎたらˈtoʊの口になってしまうからです。

後、10人くらいのOctoberの発音を聞いたのですが、その内の2人はアクト―バーとはっきりとアと発音している人がいました。残りの人は少なくとも私にはオクト―バーと聞こえました。

Octoberはɑの音の直ぐ後にtoʊの発音が続くのでもっと調べやすい単語に変更します。

Sorry (ˈsɑri)にしました。これならスの音が聞こえた瞬間に一時停止すれば唇の形をはっきり見る事が出来ます。

f:id:kazuhironagai77:20210711205715p:plain

うーん。Octoberほどはっきりしていませんが、やや丸くなっている気はします。

Fatherのɑの音は少なくとも私にはアにしか聞こえませんので比較対象としてFather(ˈfɑðər)の唇の形を見てみました。

f:id:kazuhironagai77:20210711205753p:plain

まったく唇を丸めていませんね。

この結果だけ見ると、やっぱりアメリカ英語のɑの音は単語によってはかなりɒの音に近づいていると考えられます。と言うかやっぱりアメリカ英語にもɒの音はあるんじゃないでしょうか。

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

<本文>

1.今週の予定

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

  • Niagaraの勉強の続き
  • Cascadeの勉強の続き
  • RPGの直し
    • Monsterがアイテムを落とすようにします
    • Warp Passの作成
    • Landscape4にgood skyを追加

全部は無理かもしれませんがやれるだけやっていきます

2. Niagaraの勉強の続き

公式のDocumentであるNiagara Visual Effects

Niagara Visual Effects | Unreal Engine Documentation [3]を見ると

f:id:kazuhironagai77:20210711205907p:plain

GuideにCreate a Beam Effect in NiagaraRibbonとは別にありました。

今週はこれを勉強します。もしこのDocumentが短くて何も新しく勉強する所がない場合、Smokeのdocumentでもやる事にします。

2.1 Create a Beam Effect in Niagara [4]を勉強する

注目すべき点としては

  • CascadeBeamにおけるSheetInterpolation Pointのパラメーターがどうやって実装されているか。
  • Niagara SystemBeamRibbon Renderingを使用します。しかし実際のBeam Renderingはどのように行われているのでしょうか?CascadeBeamと同じなのでしょうか?それともRibbon と同じなのでしょうか?
  • CascadeBeamは起点となる最初の面は常にカメラ側を向いています。Niagara Beamはどうなんでしょうか?
  • CascadeBeamは起点が常に画面から見て前になるようにRenderingされます。これってバグだと思っています。NiagaraBeamはどうなんでしょうか?

などがあります。これらの点に注意して勉強していきます。

このdocumentではStatic BeamをTemplateに使用していますね。

f:id:kazuhironagai77:20210711210119p:plain

この時点でもう50%くらい完成していますよね。

<Change Renderer Settings

Ribbon Renderer Moduleのparameterを弄っていきます。

f:id:kazuhironagai77:20210711210141p:plain

Curve Tensionは何を管理するParameterなんでしょうか?

f:id:kazuhironagai77:20210711210207p:plain

と書かれています。

0の時です。

f:id:kazuhironagai77:20210711210223p:plain

1の時です。

f:id:kazuhironagai77:20210711210238p:plain

Beamが細くなっていると言えばなっていますね。でも良く分かりませんね。

f:id:kazuhironagai77:20210711210253p:plain

Beam Width Moduleがあります。

f:id:kazuhironagai77:20210711210307p:plain

これのScale Curveの値を50に変更して

f:id:kazuhironagai77:20210711210324p:plain

同じ事を試してみます。

0の時です。

f:id:kazuhironagai77:20210711210340p:plain

1の時です。

f:id:kazuhironagai77:20210711210354p:plain

変わっていない?

もしかするとCurve TensionはCascadeにおけるTangentのような役割をするのかもしれませんね。Interpolation PointやSheetのようなParameterの値を後で弄るとこのBeamがCurve Tension の値に沿ってCurveを描くのかもしれません。

<Edit the Emitter Update Group Settings

次はEmitter Update GroupのEmitter State ModuleのParameter、Loop Duration についてです。

f:id:kazuhironagai77:20210711210414p:plain

Loop DurationにRandom Range Floatをセットして

f:id:kazuhironagai77:20210711210542p:plain

0.1と0.2をそれぞれの値にセットします。

f:id:kazuhironagai77:20210711210559p:plain

Beamが点滅しなくなりました。

Loop Durationは次のLoopが始まるまでの期限を指定しているはずです。一応確認します。

Loop Durationを5秒にセットしました。

f:id:kazuhironagai77:20210711210616p:plain

すると0秒と5秒の時にBeamが現れます。

f:id:kazuhironagai77:20210711210656p:plain

Beamは3秒間表示され消えます。

今度はLoop Durationを4秒にセットしました。

f:id:kazuhironagai77:20210711210711p:plain

今度は0、4、8秒の時にBeamが現れるようになりました。

はい。合ってますね。

Documentの設定だと0.1~0.2の間にDurationがセットされるので

f:id:kazuhironagai77:20210711210728p:plain

Beamの寿命が3秒にセットされている今の状態だとずっとBeamが表示される訳です。

次にEmitter Update GroupのBeam Emitter Setup ModuleのParameter、

f:id:kazuhironagai77:20210711210747p:plain

Absolute Beam Endにチェックを入れます。

f:id:kazuhironagai77:20210711210806p:plain

このParameterの機能があんまりはっきりと説明されていません。

Documentには以下の様に説明してありました。

f:id:kazuhironagai77:20210711210855p:plain

Beam RenderingでBeamの起点と終点を指定するのは重要です。それを担当するのがこのBeam Emitter Setup Moduleみたいです。

それぞれのParameterを見ると以下の物があります。

f:id:kazuhironagai77:20210711210951p:plain

Beam StartはBeamの起点を指定しています。Simulation Positionがセットされています。Simulation Positionは

f:id:kazuhironagai77:20210711211011p:plain

と書かれていますが、簡単に言えばLevel上に配置されたNiagara systemの位置から開始すると言う事でしょう。

そしてDocumentの説明では、

f:id:kazuhironagai77:20210711211028p:plain

とありますが、要するにLocal Coordinateを使用するかWorld Coordinateを使用するかの設定をしていると思います。Beam StartはSimulation PositionがLevel 上に配置されたNiagara SystemのWorld Coordinateを返します。のでAbsolute Beam Startにチェックを入れるとそのNiagara Systemが配置された箇所からBeamが始まります。

次にBeam EndですがそのBeamの起点から200cm、x軸側に移動した箇所にセットしています。のでこっちはLocal Coordinateを使用しないといけません。のでAbsolute Beam Endはチェックしてはいけないはずです。

あれ?

Documentではチェックしていますね。

確認してみます。

Level上に配置したBeamです。

Absolute Beam Startはチェック、Absolute Beam EndはCheckしていません。

f:id:kazuhironagai77:20210711211057p:plain

想像通りのEffectが作成されています。

Absolute Beam EndにCheckします。

f:id:kazuhironagai77:20210711211114p:plain

やっぱりWorld Coordinateにおける200、0,0を指しています。

Documentの設定はオカシイですね。

次にBeamにcurveを追加します。

まずBeam Emitter Setup ModuleのUse Beam Tangentsにcheckを入れます。

f:id:kazuhironagai77:20210711211136p:plain

すると以下のParameterが現れます。

f:id:kazuhironagai77:20210711211153p:plain

Beam Start Tangentの設定をMultiply Vector by Floatにします。

f:id:kazuhironagai77:20210711211208p:plain

すると以下の様な表示に変わりました。

f:id:kazuhironagai77:20210711211241p:plain

これはもうCascadeのTangentの設定と全く同じですね。

Document通りの値を追加します。

f:id:kazuhironagai77:20210711211326p:plain

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

f:id:kazuhironagai77:20210711211342p:plain

うん。中々きれいなCurveだなと思って一応Level上でも確認したら

f:id:kazuhironagai77:20210711211357p:plain

Level上ではとんでもないCurveになっていました。

Scaleを0.5と1から0.1に変更しました。

f:id:kazuhironagai77:20210711211414p:plain

まあまあ、オカシクないCurveになりました。

まあ、この辺の値はCascadeと同じでしょうから後で自分で調節します。

後、この節の一番最初で述べたParameterであるCurve Tension

f:id:kazuhironagai77:20210711211430p:plain

の機能はTangentを指定する事じゃなかったですね。このParameterの機能も後で調べます。

最後にSpawn Burst Instantaneous moduleのSpawn Countを35にセットします。

f:id:kazuhironagai77:20210711211448p:plain

このParameterについては前に良く調べました。2021-06-20のブログにまとめてあります。

簡単に説明するとSpawn Countの数が少ないとBeamが部分的にしかRenderingされません。

<Edit the Particle Spawn Group Settings

まず最初にInitialize Particle Moduleの

f:id:kazuhironagai77:20210711211509p:plain

Life Timeを0.2に変更します。

f:id:kazuhironagai77:20210711211526p:plain

Life Time、こんな所にいたのか。これでBeamが点滅するはずです。

f:id:kazuhironagai77:20210711211549p:plain

Screenshotなので点滅しているのか、これからは分かりませんが実際は点滅しています。

その後で、Documentでは以下に示した様にSpawn Beam Moduleについての説明があります。

f:id:kazuhironagai77:20210711211612p:plain

これの事ですね。

f:id:kazuhironagai77:20210711211627p:plain

Parameterも一個しかなくて良く分からないModuleです。

f:id:kazuhironagai77:20210711211643p:plain

Documentの説明を信じればBeamを作成したい時は、このModuleを追加する必要があります。しかし単に追加すれば良いので何もParameterを弄る必要はないそうです。

CursorをSpawn Beamに重ねたら以下の説明が表示されました。

f:id:kazuhironagai77:20210711211659p:plain

結構重要な内容が書かれています。

  • Particleを起点と終点の間の線状に配置します。
  • 古典的なBeamRibbon Rendererで作成するために使用されます。
  • これで作成されたBeam は起点と終点をフレーム毎に計算する必要はありません。

マジですか。BeamってParticleを起点と終点の間に線上に配置していたんですね。それでSpawn Burst Instantaneous moduleのSpawn Countの数が少ないと変なImageになったんですね。

今度は、Beam Width Moduleです。

Curveの0.5の位置が1の値になるように調節します。

f:id:kazuhironagai77:20210711211722p:plain

0と1の傾きも調節しました。

更にScale Curveは5に変更しました。

このModuleはBeamの太さを管理しているModuleです。

<Edit the Particle Update Group Settings

はい。最後のGroupに来ました。

f:id:kazuhironagai77:20210711211742p:plain

まず、Color ModuleのColorを変更してBeamの色を変えます。

f:id:kazuhironagai77:20210711211758p:plain

やっぱり光らせるために1以上の値をセットしましたね。

f:id:kazuhironagai77:20210711211814p:plain

実際光っています。

今度はBeamをジグザグにするためにJitter Position Moduleを追加します。

f:id:kazuhironagai77:20210711211829p:plain

追加しただけで以下の様な感じになりました。

f:id:kazuhironagai77:20210711211852p:plain

実際のLevel上では以下に示した様になっています。

f:id:kazuhironagai77:20210711211914p:plain

うん。このModuleは何をしているんでしょうか?

取りあえず先をやってから考えます。

次はUpdate Beam ModuleをJitter Position Moduleの前に追加します。

f:id:kazuhironagai77:20210711211929p:plain

またJitter Position Moduleに戻ってJitter AmountとJitter Delayに以下の値をセットします。

f:id:kazuhironagai77:20210711211945p:plain

これで終です。

以下の様になりました。

f:id:kazuhironagai77:20210711212001p:plain

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

f:id:kazuhironagai77:20210711212101g:plain

この節の最初で以下の疑問を書きましたがこれらの答えはまだ分かりません。

f:id:kazuhironagai77:20210711212136p:plain

更にこのDocumentをやっている中で、新たな疑問も出て来ました。

  • Ribbon Renderer ModuleのCurve Tensionはどんな機能なのか?
  • Jitter Position Moduleは実際は何をしているの?
  • 何でUpdate Beam ModuleをJitter Position Moduleの前にセットしないといけないのか?

などです。これらの疑問は次の節で検討します。

2.2 Niagara SystemにおけるBeam Renderingの疑問と検証

CascadeBeamにおけるSheetInterpolation Pointのパラメーターがどうやって実装されているか。>

まずそのものズバリSheetやInterpolation PointというParameterが無いか調べました。

f:id:kazuhironagai77:20210711212209p:plain

f:id:kazuhironagai77:20210711212216p:plain

なかったです。

それで考えて見ましたがSheetは兎も角Interpolation PointがParameterとしてあるならBeamの起点と終点のTangent を指定した時点でCurveになる訳はないです。その後でInterpolation Pointを指定して初めてCurveになります。と言う事は少なくともInterpolation PointというParameterはNiagara SystemのBeamには無いのかもしれません。

SheetはどっかのModuleにはありそうな気がしています。が見つかりませんでした。

Niagara SystemのBeamRibbon Renderingを使用します。しかし実際のBeam Renderingはどのように行われているのでしょうか?CascadeのBeamと同じなのでしょうか?それともRibbon と同じなのでしょうか?>

これはSmile ちゃんを使用して確認してみましょう。

f:id:kazuhironagai77:20210711212320p:plain

f:id:kazuhironagai77:20210711212329p:plain

f:id:kazuhironagai77:20210711212338p:plain

f:id:kazuhironagai77:20210711212345p:plain

起点と終点にある面が常にカメラ側を向いています。この点は起点だけカメラを向いているCascadeとは違いますね。

後Sheetが一枚だけ作成されています。Sheetの数は増やせそうですね。

更にWire Frameを見ると以下のようになっています。

f:id:kazuhironagai77:20210711212402p:plain

Cascadeの場合を以下に示します。

f:id:kazuhironagai77:20210711212417p:plain

f:id:kazuhironagai77:20210711212425p:plain

一見違うように見えますが、終点を含む面が常にカメラ側を向くとなると同じになると思います。

後、Spawn Burst InstantaneousのSpawn Countの値によってRenderingがどう変わるのかを調べます。

f:id:kazuhironagai77:20210711212441p:plain

0、1の時です。

f:id:kazuhironagai77:20210711212456p:plain

何も現れません。

2の時です。長方形のイメージが現れました。

f:id:kazuhironagai77:20210711212511p:plain

Wire Frameを見ると以下のようになっています。

f:id:kazuhironagai77:20210711212529p:plain

成程、辺が2個ある長方形になっています。

3の時です。

f:id:kazuhironagai77:20210711212551p:plain

f:id:kazuhironagai77:20210711212601p:plain

うん。これはCascadeのBeamにおけるInterpolation Pointと同じですね。もっと試してみましょう。

4の時です。

f:id:kazuhironagai77:20210711212618p:plain

これは?何で3つのSmileが出来ているんでしょうか?

f:id:kazuhironagai77:20210711212634p:plain

Wire Frameの方は想像通りですね。

今度は5つです。

f:id:kazuhironagai77:20210711212652p:plain

また変なMaterialの貼り方をしています。

辺の数は5個でSpawn Burst InstantaneousのSpawn Countの値はBeamの辺の数を表しているのは間違いないですね。

後は、この変なMaterialの貼り方について調べるだけですね。

6~10にしました。

f:id:kazuhironagai77:20210711212723p:plain

f:id:kazuhironagai77:20210711212730p:plain

f:id:kazuhironagai77:20210711212738p:plain

f:id:kazuhironagai77:20210711212745p:plain

f:id:kazuhironagai77:20210711212753p:plain

25です。Smileがやっと一個になりました。

f:id:kazuhironagai77:20210711212808p:plain

Wire Frameを見ても綺麗な扇型になりました。

f:id:kazuhironagai77:20210711212823p:plain

はい。

結論をまとめます。

  • NiagaraBeamRenderingは基本的にはCascadeBeamRenderingと同じです。ただしCascadeBeamは起点の面だけが常にカメラに向かっているのに対してNiagaraBeamは起点の面と終点の面の両方が常にカメラ側を向いています。
  • NiagaraBeam ではSpawn Burst InstantaneousSpawn Countの値はBeamの辺の数を表しています。CascadeにおけるInterpolation Pointの機能と同じです。
  • NiagaraBeamではMaterial3つ貼られます。Spawn Burst InstantaneousSpawn Countの値が増える毎に真ん中のMaterialのサイズが大きくなって最終的には一個のMaterialBeam全体をカバーするようになります。

以上です。

CascadeのBeamは起点となる最初の面は常にカメラ側を向いています。Niagara のBeamはどうなんでしょうか?>

この質問は既に調べてしまいましたね。NiagaraのBeamは起点の面と終点の面の両方が常にカメラ側を向いています。

CascadeのBeamは起点が常に画面から見て前になるようにRenderingされます。これってバグだと思っています。NiagaraのBeamはどうなんでしょうか?>

自分で質問を作成しておいてこの質問の内容すっかり忘れていました。

良い質問過ぎます。質問の内容を読んでいて、こんな質問考えるヤツは天才だと思いました。それで良く考えたらこの質問考えたのは私でした。

冗談はさておき調べて見ましょう。

起点が手前で、終点が奥になります。

f:id:kazuhironagai77:20210711212901p:plain

この場合は手前の起点が前にRenderingされています。

終点が手前で起点が奥になります。

f:id:kazuhironagai77:20210711212917p:plain

はい。CascadeのBeamとは違い、手前の終点の方が奥の起点より前でRenderingされています。

この結果から考えるとCascadeのBeamのRenderingの常に手前が前にRenderingされるのはバグですね。

Ribbon Renderer ModuleのCurve Tensionはどんな機能なのか?>

f:id:kazuhironagai77:20210711212946p:plain

と書かれていますが、数値を幾ら弄っても実際のBeamのCurveの形状に変化は見られません。

現時点では影響のないParameterなのではないかと思っています。

<Jitter Position Moduleは実際は何をしているの?>

Jitter Position Moduleがoffの時です。

f:id:kazuhironagai77:20210711213007p:plain

起点を含む面がカメラを向いているのが分かります。

Jitter Position ModuleがOnの時です。

f:id:kazuhironagai77:20210711213023p:plain

起点を含む面がカメラを向いていません。

Jitter Position ModuleのJitter Amountの値を変えてみます。

f:id:kazuhironagai77:20210711213124p:plain

0の場合です。

f:id:kazuhironagai77:20210711213138p:plain

Jitter Position Moduleをoffにした場合と同じです。

1の場合です。

f:id:kazuhironagai77:20210711213152p:plain

起点を含む辺が僅かに歪んでいます。

3の場合です。

f:id:kazuhironagai77:20210711213208p:plain

起点を含む辺がかなり歪んでいます。

Wire Frameで見るともっと良く分かります。

f:id:kazuhironagai77:20210711213223g:plain

これがJitter Position Moduleがしている事のようです。

<何でUpdate Beam ModuleをJitter Position Moduleの前にセットしないといけないのか?>

Update Beam ModuleをOffにしてみました。

f:id:kazuhironagai77:20210711213256p:plain

起点を含む面が元の位置に戻らず、どんどん最初の位置がずれて行っています。つまりUpdate Beam Moduleは起点の面をNiagara Systemが配置された点に戻す役割を果たしていたんでした。

Update Beam ModuleのNiagara Module Scriptを開くと以下の様なノードがOutput Moduleに繋がっています。

f:id:kazuhironagai77:20210711213314p:plain

PositionだけでなくBeam Spline Tangent、Beam Spline Normal、Beam Spline Binormalの値も初期化されているみたいですね。

流石にまだNiagara Module Scriptは読めませんがぼちぼちこれも勉強しようと思います。

今週のNiagaraの勉強はここまでとします。

3. Cascadeの勉強の続き

2021-05-24のブログに書いてある様にDistribution Float Particle Paramの具体的な使用方法は今もって分かりません。先週(2021-07-04のブログ)で述べたようにUE4C++のTutorialにその具体的な使用方法が載っているとIntro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [5]ないで説明がありました。

f:id:kazuhironagai77:20210711213350p:plain

UE4C++のTutorialとはC++ 3rd Person Battery Collector Power Up Game |v4.9| Unreal Engine [6]のTutorialの事です。

f:id:kazuhironagai77:20210711213407p:plain

このTutorialは昔、何回もやった事があるのでDistribution Float Particle Paramの具体的な使用方法を解説している箇所を見つけたらそこだけ勉強するだけでDistribution Float Particle Paramの具体的な使用方法が理解出来ると思います。

まずDistribution Float Particle Paramの具体的な使用方法を説明している箇所を探します。そしてそれを勉強します。最後に自分で試してみます。

3.1 C++ 3rd Person Battery Collector Power Up Game |v4.9| Unreal Engine [6] の調査

C++ 3rd Person Battery Collector Power Up Game |v4.9| Unreal Engine [6] からDistribution Float Particle Paramの具体的な使用方法を説明している箇所を探します。

f:id:kazuhironagai77:20210711213441p:plain

多分これでしょう。C++ Battery Collector: Adding Particles to the Pickup | 15 | v4.9 Tutorial Series | Unreal Engine [7]を見てみます。

見ました。

結論から言うとDistribution Float Particle Paramは使用していませんでした。

公式のDocumentのDistributions [8]によるとDistribution Float Particle Paramは以下の様に説明されています。

f:id:kazuhironagai77:20210711213501p:plain

のでBPでBeam EmitterのTargetを指定しているC++ 3rd Person Battery Collector Power Up Game |v4.9| Unreal Engine [6]にはDistribution Float Particle Paramの具体的な使用方法が載っていると勝手に思っていましたが、実際はDistribution Float Particle Paramを使用しなくてもEffectとBPはTargetの位置のやり取りが出来ていました。

一応C++ 3rd Person Battery Collector Power Up Game |v4.9| Unreal Engine [6]のやり方を以下にまとめておきます。

Beam EmitterのTarget ModuleのParameter, Target MethodをUser Setに変更します。

f:id:kazuhironagai77:20210711213518p:plain

f:id:kazuhironagai77:20210711213524p:plain

そしてBP内からそのParticle SystemをSpawn Emitter Attached ノードを使用して呼び出します。

f:id:kazuhironagai77:20210711213540p:plain

Set Beam Target Point ノードをSpawn Emitter Attached ノードのReturn Value から呼び出してNew Target PointにTargetの位置にしたい場所のCoordinateを指定します。

以上です。

3.2 予定変更

今週のCascadeの勉強はDistribution Float Particle Paramの具体的な使用方法を勉強する事と決めていたので予定が狂ってしまいました。

正直、Beam RenderingやRibbon Renderingもちょっとだけ飽きて来ました。

Blogを読み直してみるとRibbon Renderingを勉強する前はContent Exampleにあるsampleを見てどれを勉強するか決めていました。のでContent ExampleのCascadeのサンプルを見てみます。

この雲みたいやつにしますか。

f:id:kazuhironagai77:20210711213601p:plain

というのはNiagaraで次に勉強する予定に入れているのが公式のDocumentのRecreate the Starter Content Smoke Effect in Niagara [9] だからです。

f:id:kazuhironagai77:20210711213616p:plain

比較対照するためにCascadeでも似たようなEffectを勉強しておいた方が得な気がしています。

3.3 Particle Shadow Castingの勉強

Particleの影の投影について?

あれ。Smokeみたいなやつの作成じゃなかったのか?ちょっとParticle Systemを開いてみます。

f:id:kazuhironagai77:20210711213639p:plain

Emitterも一個しかなくて思ったより簡単かもしれません。

実際に配置してみました。

f:id:kazuhironagai77:20210711213654p:plain

あれ?Content Exampleではあった影が無くなっています。この雲みたいなのを作成するのが目的なので影の事は後で考えます。

Wireframeで見ると一目瞭然ですね。

f:id:kazuhironagai77:20210711213710p:plain

Particleを大量に発生させてそれに常にカメラに向いている面を貼り付けています。その面に指定したMaterialを貼り付けています。

普通のSpriteです。

Emitterで確認しても特別なData Typeは使用してません。

f:id:kazuhironagai77:20210711213726p:plain

Moduleを見ると見た事ないのは一個だけあります。

f:id:kazuhironagai77:20210711213742p:plain

SubImage Index Moduleだそうです。

公式のDocumentのSubUV Modules [10] によると、

f:id:kazuhironagai77:20210711213800p:plain

あ、MaterialのTextureに良く以下ののようなImageを沢山並べたヤツを使用しているのがあります。

f:id:kazuhironagai77:20210711213814p:plain

それをEffectで使用するためのModuleのようですね。そう言えばこのImageがいっぱいあるTextureから作成したMaterialの使用の仕方が全然知りませんでした。この辺も勉強する必要がありますね。

3.4 M_cloud_litの勉強

SubUVを使用したMaterialの使用の仕方を勉強する前にParticle Shadow Castingで使用されているmaterialであるM_cloud_litについて調べて見ます。

f:id:kazuhironagai77:20210711213834p:plain

まずMaterialのResultノードから見てみます。

f:id:kazuhironagai77:20210711213849p:plain

この出力の種類はBlend ModeをTranslucentにセットしていますね。

f:id:kazuhironagai77:20210711213906p:plain

Base Colorがあって、Emissive Colorも出力していますね。

それぞれの値がどのように計算されているのかを見てみます。

Base Colorです。

f:id:kazuhironagai77:20210711213921p:plain

8*8のImageのまま出力しているんですね。ひょっとしてすべてそうなんでしょうか?

f:id:kazuhironagai77:20210711213937p:plain

f:id:kazuhironagai77:20210711213945p:plain

f:id:kazuhironagai77:20210711213954p:plain

そうでした。

するとこのタイプのMaterialを使用する特別な方法がCascade側にあると言う事ですね。

それだけ分かれば十分です。Particle Shadow Castingの勉強に戻ります。

3.4 Particle Shadow Castingの勉強 Part 2

色々調べたんですがSubUVのTutorialはNiagaraが主流になってしまってCascadeはほとんど見つかりませんでした。

のでそれぞれのModuleにあるSubUV関連のParameterを見ていきます。

まずRequired ModuleにあるSubUV関連のParameterです。

f:id:kazuhironagai77:20210711214013p:plain

良く分かりませんね。

何となく分かるのはSub Image HorizontalとSub Image Verticalが8にセットされている事が、MaterialのImageが8x8だった事に一致している事だけです。

うーん。

公式のDocumentであるDefault Required and Spawn Modules [11]を見てみますか。

Required ModuleのSub UVの所です。

f:id:kazuhironagai77:20210711214032p:plain

アニメーション?

Sub UVってAnimationを作るためにあるんですか?

うーん。

これは雲のEffectを理解する前にSub UVを使用したAnimation のEffectの作成方法を勉強しないとParticle Shadow Castingが何をやっているのか理解出来ないかもしれませんね。

Particles Casting Shadows [11]

Sub UVを使用したAnimation のEffectの作成方法についてのTutorialを探していたら偶然、Smoke Effectの影を付けるTutorialを見つけました。のでこれを先に勉強する事にします。

何せ、Particle Shadow Castingと言う名前なのにそのParticleをLevel上に配置したらその影が出来ないんです。

f:id:kazuhironagai77:20210711214049p:plain

まずLightの設定を変える必要があるそうです。以下に示したCast Translucent Shadowsにチェックを入れます。

f:id:kazuhironagai77:20210711214111p:plain

そう言えばContent ExampleでもなぜかParticle Shadow CastingだけLightが右上から照射されていました。

f:id:kazuhironagai77:20210711214129p:plain

はい。チェックされていました。

f:id:kazuhironagai77:20210711214147p:plain

因みにこのSpot Lightに重なる様にS_EV_SimpleLightBeam_03と言うStatic MeshがSpot lightに重なる様に配置されていて最初、これをSpot Lightと勘違いしていました。

f:id:kazuhironagai77:20210711214209p:plain

それでずっとCast Translucent ShadowsなんてParameterはないと思っていました。

後、試しにSpot LightのCast Translucent Shadowsのチェックを外したら雲の影も消えました。

f:id:kazuhironagai77:20210711214227p:plain

次です。

今度はLevel上に配置したParticle SystemのParameterを変更します。

LightingのCast Shadowにチェックを入れます。

f:id:kazuhironagai77:20210711214245p:plain

入れる前です。

f:id:kazuhironagai77:20210711214259p:plain

入れました。

f:id:kazuhironagai77:20210711214315p:plain

影が突然現れました。

でも何か影が濃すぎる気がします。

最後の変更だそうです。MaterialのOpacityの計算にDepth Fadeノードを使用していると影が出なくなるそうです。

f:id:kazuhironagai77:20210711214330p:plain

これを外します。

Particle Shadow Castingに使用されているMaterialであるM_cloud_litではOpacityの計算にDepth Fadeノードは使用されていませんでした。

f:id:kazuhironagai77:20210711214345p:plain

今度は雲の影をもっとスムーズにしていきます。

M_cloud_litのTranslucency Self ShadowingのShadow Density Scaleの値を変化させます。

f:id:kazuhironagai77:20210711214523p:plain

0.1にして見ました。

f:id:kazuhironagai77:20210711214536p:plain

影が薄くなってますね。

1にして見ました。

f:id:kazuhironagai77:20210711214551p:plain

濃くなりました。

Tutorialでは0.5位が見た目が良い。と言っていましたので0.5にしてみます。

f:id:kazuhironagai77:20210711214603p:plain

うーん。正直、雲の形が変わっているので影か薄くなっているのかどうか分かりません。

次は影のResolutionを変えるそうです。

今度はParticle Systemから変えます。

Boundsをクリックして境界線を表示させます。

f:id:kazuhironagai77:20210711214622p:plain

f:id:kazuhironagai77:20210711214629p:plain

次にBoundsのSet Fixed Boundsを選択します。

f:id:kazuhironagai77:20210711214644p:plain

Emitterの選択を外してBoundsを表示させます。

f:id:kazuhironagai77:20210711214700p:plain

この中のMinとMaxの値を弄る事で雲のサイズが変化するそうです。

後で直すのが大変そうなのでこの値は弄るのは止めてTutorialだけ見る事にします。

Tutorialでは以下のような影になりました。

f:id:kazuhironagai77:20210711214715p:plain

影が細部まで綺麗に写っている気がします。

以上でした。

<今週のCascadeの勉強はここまでにします。>

Sub UVを使用したAnimation のEffectの作成方法を解説したTutorialを探したんですが見つかりません。ひょっとするとNiagaraのSmokeのTutorialで解説されているかもしれませんし、今週のCascadeの勉強はここまでにします。

4. Monsterがアイテムを落とすようにする。-Play Animation ノードを使用しないで勝利のポーズを行う

今週は勝利のポーズをPlay Animation ノードからではなくMyThirdPerson_AnimBPから行うようにします。

やり方は

  • MyThirdPerson_AnimBPにBoolean変数を追加してその変数がTrueの時に勝利のポーズを取るようにする。
  • RPGGameModeBP内からMyThirdPerson_AnimBPにアクセスしてそのBoolean変数を戦闘後の勝利のポーズを取るときに変更する。

勝利のポーズを取っている間、RPGGameModeBPは次のノードの実行を待ってくれるのかどうか?などまだ不明な点はありますが作成しながら検討していきます。

4.1 MyThirdPerson_AnimBPのコードの改良

まずBoolean変数を作成します。

f:id:kazuhironagai77:20210711214810p:plain

勝利のポーズを取る時にTrueになる変数です。

武器を装備していない場合です。

f:id:kazuhironagai77:20210711214824p:plain

弓と矢を装備している時の場合です。

f:id:kazuhironagai77:20210711214900p:plain

それ以外の武器を装備している時です。

f:id:kazuhironagai77:20210711214917p:plain

4.2 RPG Game Mode BPのコードの改良

以下の部分を直していきます。

f:id:kazuhironagai77:20210711214939p:plain

以下の様になりました。

f:id:kazuhironagai77:20210711214954p:plain

実際に外した部分です。

f:id:kazuhironagai77:20210711215008p:plain

最後にMy ThirdPerson Anim BPのVictory変数をfalseにします。

f:id:kazuhironagai77:20210711215025p:plain

勿論、Set Anim Instance Classは要らないので外します。

これで完成した。と思ったら思い出しました。

前のこれと同じ物を作成した事をです。

たしか変なアニメーションになったんで仕方なくPlay Animation ノードに変更したんでした。

取りあえず結果を見てみます。

4.3 テスト

テストします。

武器なしの時です。

f:id:kazuhironagai77:20210711215044p:plain

普通に勝利のポーズを取っています。どこもおかしくないです。

武器を装備した時です。

f:id:kazuhironagai77:20210711215102p:plain

これもおかしくないですね。

弓を装備した時です。

f:id:kazuhironagai77:20210711215119p:plain

弓と手が離れていますが、それは元からなので今回は無視しておきます。

勝利のAnimationには何の問題もありません。

あまりに簡単に終わってしまったので拍子抜けですが出来ました。

後、多分ですが前回Play animation ノードを外した時に変なアニメーションになった理由はMy ThirdPerson Anim BPのAnim Graphの以下の部分

f:id:kazuhironagai77:20210711215149p:plain

でLoop Animationにチェックしたままにしていたせいだと思います。

f:id:kazuhironagai77:20210711215212p:plain

兎に角出来ました。

Preparation and Implementation Programmingはやっぱりすごい効果があります。全然疲れないし、時間も前の何分の1かで済んでしまいます。今までの越えなければならないハードルの高さが10位だとすると2か3位になっています。

来週は2倍の量がこなせそうですので、先週の2倍分、調査、検討する事にします。

5.戦闘後にアイテムが手に入る場合

5.1 色々な検討

戦闘後にアイテムが手に入る場合と入らない場合はどのような割合になるのでしょうか?

また、手に入るアイテムの種類はどの様に配分すべきなのでしょうか?

戦闘後にアイテムが手に入る確率は20%ぐらいが丁度良いと思います。それは最初の10回の戦闘はPlayerの操作するキャラのレベルが戦闘後、毎回上がるからです。その間に2回程度アイテムが手に入る事が分かればPlayerもどのくらいの確率でアイテムが手に入るのかが推測出来き、それ以降の戦闘に対しての準備や対策が建てられるからです。

アイテムの種類については2021-06-13のblogで検討した内容で良いと思います。

f:id:kazuhironagai77:20210711215247p:plain

ただし流石にこの期に及んで50%の確率でしかアイテムが貰えないのは厳しすぎます。一個は必ず貰えるようにしましょう。

となるとまず作成する必要があるのは、20%の確率で元の世界に戻らないようにする仕組みです。

そして石像と会話した後で元の世界に戻れるようにします。

段々、何を制作しないといけないのか見えて来ました。

まとめます。

  1. 20%の確率で元の世界に戻らないようにする仕組み
  2. 石像との会話
  3. 会話の後に元の世界に戻る仕組み

です。

5.2 「20%の確率で元の世界に戻らないようにする仕組み」の検討

まず戦闘に勝利した後、RPG Game Mode BP内でどんなノードが実行されるのかを確認します。

前節のMy Third Person Anim BP内のVictory変数がFalseにセットされた後から見て行きます。

f:id:kazuhironagai77:20210711215321p:plain

カメラの位置を元に戻しています。

f:id:kazuhironagai77:20210711215335p:plain

Down Victory Music変数をTureに変更しました。

f:id:kazuhironagai77:20210711215349p:plain

Down Victory Music変数はEvent Tickで使用されていました。

f:id:kazuhironagai77:20210711215404p:plain

TrueになるとBGMの大きさが0になるまで少しずつ下げていきます。

次のノードはHad Read Fight is Overノードです。

f:id:kazuhironagai77:20210711215418p:plain

戦闘に勝利した後だけでなく戦闘から逃げ出した時もこのノードに繋がっています。

戦闘から逃げ出した後で褒美が貰えたらオカシイです。このノードの後に石像と話す実装をする場合は戦闘に勝利した場合と戦闘から逃げた場合の別々な実装を作る必要がありますね。

Had Read Fight Is Over関数についてです。

f:id:kazuhironagai77:20210711215434p:plain

UE4C++の方の関数でした。FightISOverIsRead変数にTureをセットしています。

FightISOverIsRead変数がTureになるとTick()関数の以下の部分が実行されるようになります。

f:id:kazuhironagai77:20210711215450p:plain

Pointerなどの後処理を行っているだけですね。特にBP側に指令を発したりはしていませんね。

次は「読みました」ボタンにBindしたEventを全て外しています。

f:id:kazuhironagai77:20210711215505p:plain

この「読みました」ボタンの仕組みについては散々勉強したので今回はパスします。

その次のノードは倒したモンスターをRPGGameInstanceBP内のデータから消去しています。

f:id:kazuhironagai77:20210711215628p:plain

ここでMonsterの消滅を実行していたんですね。

一秒待っています。

f:id:kazuhironagai77:20210711215646p:plain

理由は忘れました。

何か重大な理由があったはずです。ここで待たないと何か不都合な事が起きたのは覚えています。

はい。最後に元のLevelにワープしています。

f:id:kazuhironagai77:20210711215702p:plain

このOpen Levelノードのすぐ前で「20%の確率で元の世界に戻らないようにする仕組み」を作成出来ると一番簡単です。

しかし戦闘に勝利した場合と戦闘から逃げ出した場合の違いをどうやって区別しましょうか?

良い変数を見つけました。

f:id:kazuhironagai77:20210711215731p:plain

この変数Victory、Combat Over State のEnumでPHASE Victory, PHASE Game Over, PHASE Escapeの種類があります。そして今の時点ではVictoryにセットされたままのはずです。この変数を使えば戦闘に勝利した場合と戦闘から逃げ出した場合を分けれるはずです。

ちょっとだけ試してみます。

f:id:kazuhironagai77:20210711215747p:plain

自由に歩けるようになりました。

f:id:kazuhironagai77:20210711215801p:plain

骸骨は消した方が良いです。回っている骸骨が3D酔いを引き起こします。

5.3「20%の確率で元の世界に戻らないようにする仕組み」の手順

20%の確率で当たる実装はどうとでも作成できるので来週考えます。その20%の確率に当たった場合、まずWidgetで特別な褒美が石像からもらえる事を連絡します。

そのWidgetでは

  • 褒美としてItemが貰える事
  • Itemをもらうためには石像に話しかける必要がある事
  • 話しかける石像によってもらえるItemが違う事

を説明します。

Widgetは今、作成してしまいましょう。

イラストはこんな感じです。

f:id:kazuhironagai77:20210711215832p:plain

Widgetのデザインはこんな感じです。

f:id:kazuhironagai77:20210711215849p:plain

「話しかける石像によってもらえるItemが違う事」に関しては、実際に石像に話しかけて見れば良いと思い消しました。

次に「回っている骸骨」を消します。

「回っている骸骨」はBackgroundSkullBPと言う名前のBPクラスから生成されたInstanceでLevel、Battle Fieldに静的に配置されています。

f:id:kazuhironagai77:20210711215909p:plain

このVisualを消すためにはLevel、Battle FieldとRPG Game Mode BPとのやり取りが必要になります。RPG Game Mode BP内に専用のDispatcherを作成して、そのDispatcherをBattle Field内でBind、RPG Game Mode BP内でCallするようにするのか良いと思います。

5.5「石像との会話」の作成方法について

注意しなければならない点が一つあります。戦闘中は石像との会話が発動しないようにしなければなりません。これはBoolean変数をつければ解決します。

石像との会話はNPCとの会話と一緒で良いと思います。

のでNPC_Personを見て確認しましょう。

f:id:kazuhironagai77:20210711215931p:plain

Viewportはこんな感じでした。

f:id:kazuhironagai77:20210711215945p:plain

Boxの位置は変える必要がありますね。あるいはMeshを完全に外してしますのも手かもしれません。

Exclamation markを光らせる部分の実装です。

f:id:kazuhironagai77:20210711220028p:plain

f:id:kazuhironagai77:20210711220041p:plain

正直、何でこんな複雑にしたのか覚えていません。Boxに侵入したら光るだけでは駄目なんでしょうか?

思い出しました。

確か全部のNPCのExclamation Markが光ってしまうので上記のようなコードにしたんでした。

これは実装する時にもう一回検討しましょう。Begin Overlap関数に実装するだけで上記の問題は解決しそうです。

Begin Overlap関数を見て行きます。

f:id:kazuhironagai77:20210711220101p:plain

cast to Third Person Characterノードに繋がっています。

f:id:kazuhironagai77:20210711220117p:plain

これは侵入したActorがPlayer が操作するキャラであるかどうかの確認をここで行っているでした。

次のノードに行きます。

NPC_Person BP クラスの変数であるVillage Nameの値をThird Person Characterクラスの変数であるVillage Nameにセットしています。

f:id:kazuhironagai77:20210711220133p:plain

NPC_Person BP クラスのVillage NameはEnumで村の名前を保持しています。Instance Editableなのでlevel内に静的に配置したそれぞれのInstanceに別の値をセットする事が出来ます。

f:id:kazuhironagai77:20210711220418p:plain

村人との会話の区別に使用しているはずです。

次はRPGGameModeBPを呼び出して変数化していました。

f:id:kazuhironagai77:20210711220435p:plain

これはEvent Begin Playでやって置く事でしょう。と思ったらこのBP、Event Begin Playノードがありません。

Event Begin Playノードが無いからここでRPG Game Mode BPを呼び出して変数化しているんですね。Event Begin Playで呼び出すのとどっちが良い方法でしょうか?これも来週考えます。

最後にNPC_Person BP クラスのOccupationをRPG Game Mode BPクラスの変数、My Place For Eventsにセットします。

f:id:kazuhironagai77:20210711220451p:plain

因みにOccupationとMy Place For EventsはEnumで以下の要素で構成されています。

f:id:kazuhironagai77:20210711220506p:plain

以上でした。

これだけでは何をやっているのか不明です。のでこのExclamation markが見える時にEボタンを押した場合についての検討を次に行います。

まずThird Person Character BPクラスを見てみます。

Third Person Character BPクラスにはEvent Do Somethingがあります。

f:id:kazuhironagai77:20210711220522p:plain

このEventはEボタンを押すと発動します。

f:id:kazuhironagai77:20210711220537p:plain

キャラクターを操作するためのキーボードやマウスの操作についての管理は一括してThird Person Characterが担当すると決めています。

Playerが操作するキャラがNPCに話しかける場合もThird Person Character BP内で管理しています。

このやり方は以下のノードのようなスパゲッティコードを生み出していますが「キャラクターを操作するためのキーボードやマウスの操作についての管理は一括してThird Person Characterが担当する」と言う原則は守っているので一長一短がある実装方法です。

f:id:kazuhironagai77:20210711220554p:plain

NPCの場合はどんな実装がされているのかを見てみます。

NPCは沢山の種類があるのでその代表としてMy Place For Events がPE_TalkingNPC_Oldmanの場合を見てみます。

f:id:kazuhironagai77:20210711220609p:plain

Widget、Oldman Welcomeを開きます。

こんな絵が出て来ました。

f:id:kazuhironagai77:20210711220625p:plain

思い出しました。NPCの作成方法は結構大掛かりで大変でした。

このwidgetの特徴はNPCのセリフをそのセリフを管理しているData Tableから呼び出した表示する事です。更にそのセリフを管理しているData TableはそのNPCのセリフに対するPlayerの回答も用意されていて結構複雑な作りになっています。

NPCとの対話用のData Tableは以下の様な作りになっています。

f:id:kazuhironagai77:20210711220707p:plain

流石にこの辺の作りは覚えています。アドベンチャーゲーム方式でセリフを管理しています。

f:id:kazuhironagai77:20210711220728p:plain

ConversationにNPCのセリフが書かれています。

Answer Choice(何故かData TableにはAnser Choiceになっていますね。)にはNPCのセリフに対してのPlayerの回答が書かれています。その回答を選択した場合はJump To Commentに書かれた番号のCommentに飛びます。

このData Tableを正しく読めるような実装をOldman Welcomeウィジェット内で実装しているはずです。

まずCustom EventであるConversation Startが呼ばれています。

f:id:kazuhironagai77:20210711220742p:plain

Village Nameによって分岐しています。

f:id:kazuhironagai77:20210711220756p:plain

これはそれぞれの村でNPCのData Tableは別なので当然です。

最初の村の場合を見てみます。

Get Data Table Row Names関数が使用されていました。この関数は最初の村の老人用のセリフを管理したData Table、FistVillage_Oldmanを読み込んでそのData TableのRow Nameを返します。

f:id:kazuhironagai77:20210711220810p:plain

FistVillage_OldmanのRow Nameは以下のものです。

f:id:kazuhironagai77:20210711220824p:plain

次のノードです。Get Data Table Row()関数が使用されています。

f:id:kazuhironagai77:20210711220837p:plain

Get Data Table Row()関数ではComment Numberで指定された値のFistVillage_OldmanのRow NameがGet Data Table Row()関数にパスされそのRow Nameの担当する列がまるまる返されてきます。

Comment Numberで指定された値は、0なので

f:id:kazuhironagai77:20210711220851p:plain

が返されます。そしてRow Nameが担当している列のデータ(以下の物)が返されます。

f:id:kazuhironagai77:20210711220905p:plain

Conversationにある値はComment変数にセットされます。

f:id:kazuhironagai77:20210711220919p:plain

Comment変数の値は以下のTextBlockにバインドした

f:id:kazuhironagai77:20210711220933p:plain

Get Text Block Oldman Dialog Text 0 関数によって直ぐにComment欄に表示されます。

f:id:kazuhironagai77:20210711220948p:plain

その次のノードであるAnswer CommentにAnswer Choiceにある全ての要素が記録されます。

f:id:kazuhironagai77:20210711221003p:plain

そしてその配列は次のFor Each Loopに渡されます。

f:id:kazuhironagai77:20210711221016p:plain

ここで、それぞれの要素毎にAnswer Button ウィジェットが作成されます。

f:id:kazuhironagai77:20210711221038p:plain

Answer Button ウィジェットはただのボタンのWidget

f:id:kazuhironagai77:20210711221053p:plain

ボタン内のTextには先程、Answer Choice からAnswer Commentにパスされた要素の内のPlayerの回答部分が表示されます。

そのための実装部分を以下に示します。

f:id:kazuhironagai77:20210711221108p:plain

更にこのボタンがクリックされた場合は、以下の実装部分によりOldman Welcome ウィジェットのComment Numberが指定されている番号に変更します。

f:id:kazuhironagai77:20210711221122p:plain

その後、Clear Children関数で

f:id:kazuhironagai77:20210711221136p:plain

以下の赤丸で囲った部分に表示されているボタンを全て消去し、

f:id:kazuhironagai77:20210711221150p:plain

Oldman Welcome ウィジェットのCustom EventであるConversation Startを呼び出します。

f:id:kazuhironagai77:20210711221205p:plain

この後は、上記のOldman Welcome ウィジェットのCustom EventであるConversation Startに戻って同じ事を繰り返していきます。

f:id:kazuhironagai77:20210711221219p:plain

大変でしたが一通り復習出来ました。

5.6「石像との会話」の作成方法について Part 2

「石像との会話」では前節で復習したNPCとの会話のような複雑な対話システムは必要ありません。しかしItemを修得する必要があります。

ので先週作成したPick Up Itemクラスでどのように収得したItemを道具袋に追加しているのかを確認します。

ただし流石に先週作成したものの全てのノードを見て行くのは無駄なので実際にItemを追加する箇所だけ復習します。

それはPick Up Item ウィジェット内の以下の実装部です。

f:id:kazuhironagai77:20210711221240p:plain

最初のノードでそのItemが本当に存在しているItemかどうかを確認しています。

次のADDノードでRPG Game Instanceクラスの変数ItemsにそのItemを追加しています。これで修得したItemが道具袋に収納された状態になりました。

何かPCの調子がオカシイので、突然ですが今週の作業はここまでとします。

6.まとめと感想

今週は以下の事についてやりました。

  • Niagara Systemの勉強
    • Create a Beam Effect in Niagara [4]を勉強する。
    • Niagara SystemBeamCascadeBeamの比較と検証
  • Cascade Systemの勉強
    • BPBeam EmitterTargetを指定する方法について
    • Content ExampleにあるParticle Shadow Castingの勉強
  • ターン制RPGの作成
    • Play Animation ノードを使用しないで勝利のポーズを行う
    • 戦闘後にアイテムが貰える場合の検証
      • 20%の確率で元の世界に戻らないようにする仕組み」の検証
      • 「石像との会話」の検証

来週は、ターン制RPGの作成では今週の検証した内容についての実装を行います。NiagaraではSmokeのdocumentを勉強します。Cascadeは今週の続き、特にsub UVを使用したAnimationの作成方法についての勉強をします。

もしPCの調子が直らなかったり、Ch4_3 のProjectそのものが破損してしまった場合は、また一から作り直す事になってしまいますが、それもまた勉強でしょう。

以上です。

<参照 (Reference)

[1] Vowel diagram. (2021, March 21). In Wikipedia. https://en.wikipedia.org/wiki/Vowel_diagram

[2] Improve Your English Pronunciation. (n.d.). YouGlish. Retrieved July 11, 2021, from https://youglish.com/

[3] Epic Games. (n.d.-d). Niagara Visual Effects. Unreal Engine Documentation. Retrieved July 11, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/

[4] Epic Games. (n.d.-a). Create a Beam Effect in Niagara. Unreal Engine Documentation. Retrieved July 11, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/HowTo/BeamEffect/

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

[6] Epic Games [Unreal Engine]. (2017, February 14). C++ 3rd Person Battery Collector Power Up Game | v4.9 | Unreal Engine [Video]. YouTube. https://www.youtube.com/playlist?list=PLZlv_N0_O1gYup-gvJtMsgJqnEB_dGiM4

[7] Epic Games [Unreal Engine]. (2015, October 7). C++ Battery Collector: Adding Particles to the Pickup | 15 | v4.9 Tutorial Series | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=1-eT_hnjdfg&list=PLZlv_N0_O1gYup-gvJtMsgJqnEB_dGiM4&index=15

[8] Epic Games. (n.d.-c). Distributions. Unreal Engine Documentation. Retrieved July 11, 2021, from https://docs.unrealengine.com/4.26/en-US/Basics/Distributions/

[9] Epic Games. (n.d.-e). Recreate the Starter Content Smoke Effect in Niagara. Unreal Engine Documentation. Retrieved July 11, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/HowTo/RecreateSmoke/

[10] Epic Games. (n.d.-f). SubUV Modules. Unreal Engine Documentation. Retrieved July 11, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/ParticleSystems/Reference/Modules/SubUV/

[11] Epic Games. (n.d.-b). Default Required and Spawn Modules. Unreal Engine Documentation. Retrieved July 11, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/ParticleSystems/Reference/Modules/Required/

[12] W3 studios. (2017, August 14). Particles Casting Shadows [Video]. YouTube. https://www.youtube.com/watch?v=Z6F2sqo37bw

 

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

f:id:kazuhironagai77:20210704212517p:plain

<前文>

中学生の時から本があると読まずにいられない性分だった私は立花隆氏の本をほとんど全部読んでいました。

残念だったのは立花隆氏を知ったのは渡辺昇一氏よりずっと後で、逆だったら田中角栄の裁判について10倍くらい面白く読めたと思う事です。

渡辺昇一氏の著作は一貫して白黒はっきりつける結論至上主義に対して、立花隆氏の著作は科学的な手順や思考にこそ真実があると言うスタンスで、その結果、結論が常識外れだとしてもそれはそれで受け入れるみたいな手順至上主義みたいな所がありました。

この二人が田中角栄の裁判を巡って大喧嘩したと聞いた時は「それは絶対面白いだろう。ぜひその時の事を知りたい。」と思いましたが実際に読んだらあんまり面白くなかったです。渡辺昇一氏の田中角栄の裁判に関する本はその時は既に読んでいて、立花隆氏の田中角栄氏に関する本を後から読んだんですが、正直、立花隆氏の臨死体験の面白さを10としたら1か2ぐらいしか面白くなかった記憶があります。

今は全く本を読まなくなりました。本当の理由は分かりませんが、多分ネットの発達で知識人に価値が無くなったからだと思います。

これはネットの影響を示す一例ですが、Tax havenをtax heavenと勘違いした知識人の方が居ました。直ぐにその間違いはネットに広まってしまい、その話を聞いた私はその人の話を一切信じなくなりました。一瞬でその人の知識人としてのブランドが崩壊してしまったんです。

その代りにネットの中に今まで知識人達が担当していた部分、日本人の知識欲を満たしたり、日本の針路についての助言を行う別な人達が現れました。

中田敦彦氏、DAIGO氏、ひろゆき氏のような人達です。

あいつ等は軽い!と読書好きな人からは怒られるかもしれませんが、その軽さこそがこのネット社会で生き残る秘訣だと私は思います。今のネット社会で間違いを指摘されない事は不可能です。間違いを指摘されてしどろもどろにうろたえる事が駄目であって、直せば良いんです。直したら更に良くなるだけです。彼らは自分の間違いを直す事を全く恐れません。また最初からある程度間違える事も計算していて間違えたらすぐに修正出来る様に準備しています。

そんな中で私が今一番注目しているのが元プロレスラーの前田日明氏です。彼の主張する下剋上の思想「大義があれば下剋上は正しかったし今も正しい。」はこれからの日本の未来を決める思想になる可能性があります。

彼の主張する下剋上の思想を簡単に言えば、我々はみんな日本丸に載ってる乗員ですが、船長が余りにもアホな行動をしたら船が沈んでみんな死んでします。だからそんな船長はみんなで監禁してもっとまともな人に船長になってもらう。と言う言われてみれば当たり前の考え方です。しかしこの考え方、とても悪い事のように今の我々は教わっています。これが間違っているっと前田日明氏は主張してるわけです。

戦国時代の様に明日侵略されて死ぬかもしれない時代ではアホな領主の下に付いたらすぐに死んでしまいます。そんな時代は下剋上は必要悪として当たり前だった。しかしそれは戦国時代のような特殊な時代のみに通じる常識なのか?実は下剋上はいつの時代でも通じる当たり前の事で、今の我々がそれが悪い事であると洗脳されているだけなのかもしれない。

この思想はネットで叩かれて直ぐに死んでしまうかもしれません。しかしもし5年も生き延びる事が出来れば日本の未来への活路を開くための日本人の意識転換の一歩になるかもしれない気がしています。

と言うのは「上がサボっているから俺もサボる。」と言う考えに捕らわれるとみんながサボりだし、結果的に仕事の質が指数的に落ちていくからです。製品の段階ではもう競争にならない位の低品質になってしまいます。

そして日本の大部分が今このスパイラルに陥っているように見えます。

ここで下剋上の思想が一般化すれば「上がサボっているなら俺が取って代わる。」となるから仕事の手を抜く事はありません。むしろチャンスが到来したともっと仕事を熱心に行うようになります。更に自分が仕事の手を抜くとこんどは部下に取って代わられるため今のように上がサボっているから俺もサボろうとはならないからです。

つまりその結果「上がサボっているから俺もサボる。」と言う負のスパイラルから抜け出せるようになる訳です。

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

<本文>

1.今週の予定

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

  • Niagaraの勉強の続き
  • Cascadeの勉強の続き
  • RPGの直し
    • PickUpItemクラスにItemを追加
    • Monsterがアイテムを落とすようにします
    • Warp Passの作成
    • Landscape4にgood skyを追加

全部は無理かもしれませんがやれるだけやっていきます。

2.Niagaraの勉強

今週もRibbon Renderingについて勉強します。

2.1 Ribbon Renderingの仮説

先週、Ribbon Renderingは以下の様にRenderingしているのではないのかと説明しました。

ただしこのやり方でRibbon Renderingを説明しているTutorialはひとつもありません。世界で私だけです。ので論理的な破たんがない事をしっかり確認しておきたいです。

まずLife timeとSpawn Rateの関係で一個のRibbonしか生成されない場合です。

f:id:kazuhironagai77:20210704212628p:plain

Ribbonは必ず長方形になります。

横軸の長さはLife TimeとRibbon Systemの先頭が移動するスピードで決定されます。

次にLife timeとSpawn Rateの値を大きくして一個以上のRibbonが生成される場合です。

f:id:kazuhironagai77:20210704212643p:plain

この場合は存在しているRibbon全体に対して一枚のMaterialが貼られます。

以下のScreenshotの様にです。

f:id:kazuhironagai77:20210704212703p:plain

のでLife timeとSpawn Rateの値を大きくして沢山のRibbonが生成されるようにすると以下の図の様に円周上に沿ったイメージを作成する事も出来ます。

f:id:kazuhironagai77:20210704212724p:plain

しかしある程度の時間が経つと最初のRibbonのLife timeが尽き消滅します。しかしそれと同時に新しいRibbonも生成されます。

f:id:kazuhironagai77:20210704212742p:plain

するとRibbon全体の長さは一定になります。

f:id:kazuhironagai77:20210704212800g:plain

2.2 Ribbon Renderingの仮説の検証

Life timeとSpawn Rateの関係で一個のRibbon しか生成されない場合、本当に長方形のRibbonしか生成されないのか確認します。

以下の条件で試してみます。

f:id:kazuhironagai77:20210704212901p:plain

f:id:kazuhironagai77:20210704212908p:plain

Life Timeが0.5秒ですので一個のRibbonの寿命は0.5秒になります。

そしてSpawn Rateは1.0にセットしたので、1秒間に1個のRibbonが生成されます。

これなら一個のリボンしか生成されません。本当に長方形になるのか試してみます。

テストします。

f:id:kazuhironagai77:20210704212932p:plain

???

出来ません。Ribbonが一個も生成されないです。

あれ?

色々試しましたがRibbonの寿命が次のRibbonが生成される前に尽きる場合は絶対に生成されません。

しかし以下の条件のように最初のRibbonの寿命が尽きる前に新しいRibbonが生成される場合はRibbonを見る事が出来ます。

f:id:kazuhironagai77:20210704212950p:plain

f:id:kazuhironagai77:20210704212956p:plain

上記の条件だとRibbonの寿命は1秒で、Ribbonは0.5秒毎に生成されます。

f:id:kazuhironagai77:20210704213017g:plain

上記の条件だと常に2個のRibbonが生成されます。この場合だと長方形になります。

うーん。

閃きました。以下に説明します。

2.3 Ribbon Renderingの仮説の改良

Initialize Ribbon Moduleで生成されるのは幅の情報を保持するParticleだけなんです。

f:id:kazuhironagai77:20210704213057p:plain

以下のようなイメージのParticleです。

f:id:kazuhironagai77:20210704213116p:plain

これが一個しか生成されない時はRibbonは作れません。ので何も表示されません。

もしこれが2個以上生成される場合はそれぞれのParticleを繋いでRibbonを生成する事が出来るのでRibbonが生成されます。

f:id:kazuhironagai77:20210704213134p:plain

以下に示した赤い部分がRibbonになります。

f:id:kazuhironagai77:20210704213150p:plain

この考え方でもRibbonが最初はどんどん長くなるのに、ある程度の時間が過ぎるとRibbonの長さが変わらなくなるのも説明出来ます。

まずこのParticleが2個以上ある場合です。

以下の様に沢山あると仮定します。

f:id:kazuhironagai77:20210704213208p:plain

この場合以下の様なRibbonが生成されるはずです。

f:id:kazuhironagai77:20210704213241p:plain

一番右端のParticleのLife Timeが尽き消滅します。

しかし左端に新しいParticleが誕生します。

f:id:kazuhironagai77:20210704213259p:plain

のでTotalの長さは同じになります。

つまりInitialize Ribbon Moduleで生成されるのは面ではなく辺だったんです。

2.4 Ribbon Renderingの新たな仮説の検証

今度の仮説は合っていると思いますが少し検証してみましょう。

Particleが3つ作られる条件でRibbonを作成してみます。

f:id:kazuhironagai77:20210704213328p:plain

f:id:kazuhironagai77:20210704213335p:plain

はい。

<テスト1

最初のテストは横に引っ張っります。

f:id:kazuhironagai77:20210704213359g:plain

まず観察します。

①最初に現れたRibbonです。

f:id:kazuhironagai77:20210704213434p:plain

②直ぐにその上を覆うように横に拡張したRibbonが現れます。

f:id:kazuhironagai77:20210704213453p:plain

③次に現れるRibbonはサイズは前のRibbonと同じですが位置が左にずれています。

f:id:kazuhironagai77:20210704213512p:plain

これを何回も繰り返して、④左端につくと横のサイズが小さいRibbonが発生します。

f:id:kazuhironagai77:20210704213536p:plain

⑤そして更に横幅の小さいRibbonが発生します。そしてRibbonは消滅します。

f:id:kazuhironagai77:20210704213555p:plain

改良した仮説によると①の状態は以下の様になっていると考えられます。

f:id:kazuhironagai77:20210704213612p:plain

2個目のParticleが生成され最初のRibbonが生成された状態です。

②の時は更にもう一個のParticleが生成されます。のでNiagara Systemが一定の速度で左に移動しているならばRibbonの横幅は大きくなります。

f:id:kazuhironagai77:20210704213630p:plain

③の時は最初に生成されたParticleが消滅します。しかしそれと同時に新しいParticleが生成されます。

f:id:kazuhironagai77:20210704213648p:plain

ので長さが一定で左に移動するRibbonが生成されます。

④の状態です。

左端のParticleはNiagara systemが停止したために隣のParticleに非常に近い場所で生成されています。

f:id:kazuhironagai77:20210704213706p:plain

ので3つのParticleがある状態ですが、Ribbonは前より短くなります。

最後の⑤の状態です。

Niagara systemが停止したため新しいParticleが作成される事はありません(あるのかもしれませんが前と同じ位置で作成されるためされないのと同じ事になります)。

f:id:kazuhironagai77:20210704213723p:plain

これによって前の④より更に短いRibbonが生成されます。勿論この後でRibbonは消滅します。

横に伸びた状態は完璧に説明出来ていますね。

<テスト2

今度はNiagara Systemを回転させてみました。

f:id:kazuhironagai77:20210704213816g:plain

①やはり最初に作成されるRibbonは長方形でした。

f:id:kazuhironagai77:20210704213904p:plain

これは実は中々見つからなかったです。最初のRibbonから丸くなっていたらオカシイと思って徹底的にコマ送りにして探しました。そうしてやっと見つけました。

②次のRibbonが生成された時です。

f:id:kazuhironagai77:20210704213927p:plain

かなりいびつな形をしています。

③その次のRibbonが形成された時です。

f:id:kazuhironagai77:20210704213948p:plain

完全な扇形になっています。

f:id:kazuhironagai77:20210704214006p:plain

④ほぼ同じ大きさの扇形で移動しつづけています。

Niagara Systemの移動が終了すると扇が小さくなります。

f:id:kazuhironagai77:20210704214023p:plain

⑥最後に長方形になって消滅します。

f:id:kazuhironagai77:20210704214048p:plain

はい。それでは検証していきます。

先ず①の状態です。

今度は円を描くようにNiagara Systemを移動させましたのでParticleが円周上に生成されているはずです。

以下に示したのはそのポンチ絵です。

f:id:kazuhironagai77:20210704214106p:plain

もし上図のような状態で二つのParticleがRibbonを作成すると2点でも扇型、もしくは台形型になるはずです。

f:id:kazuhironagai77:20210704214123p:plain

f:id:kazuhironagai77:20210704214130p:plain

しかし実際はParticleが2点の時は長方形が作成されています。

f:id:kazuhironagai77:20210704214147p:plain

それはこのParticleはRotationの情報は持っておらず、単に2点間を結んだ線をRibbon Widthで広げたと考えると辻褄が合います。

f:id:kazuhironagai77:20210704214213p:plain

ただし実際の計算でどんなAlgorithmが使用されているのかが分からないと実際の所は分かりませんね。その近似式を使うと2点の時は長方形、3点以上の時は扇形になるのかもしれませんし。

その近似曲線の計算方法が分からないのでこれ以上ここで追及するのは無駄な気がします。ので一端ここで中止します。

私が想像していたのは3点のParticleが生成された場合は以下のようなRibbonが生成され、

f:id:kazuhironagai77:20210704214239p:plain

生成されるParticleが増えると以下に示した様なもっとスムーズなRibbonが生成される

f:id:kazuhironagai77:20210704214257p:plain

と思っていましたが実際は、3点のParticleが生成された時点で

f:id:kazuhironagai77:20210704214315p:plain

きれいな曲線を描いています。

これはRibbon を作成する段階でCatmull–Clark subdivision surfaceのようななんらかの近似曲線を使用していると言う事です。

2.5 Ribbon Renderingで作成してみる。

まあ完璧とは言えませんがかなりRibbon Renderingについて理解は深まりました。

この知識を元にオリジナルのRibbon Renderingを作成してみようと思います。

以下のイメージを使用してみます。

f:id:kazuhironagai77:20210704214340p:plain

Materialは以下の様に組みました。

f:id:kazuhironagai77:20210704214359p:plain

Niagara Systemの設定は

f:id:kazuhironagai77:20210704214417p:plain

f:id:kazuhironagai77:20210704214424p:plain

にしてみます。

f:id:kazuhironagai77:20210704214502g:plain

うーん。文字を使用するのはどうでしょうか?

f:id:kazuhironagai77:20210704214655p:plain

これで試してみます。

f:id:kazuhironagai77:20210704214731g:plain

字ははっきりと読めますね。良いんじゃないでしょうか。

白色を追加した方が黒や赤がはっきり見えると思ったんですがあまり関係ないというか透明にした方が見やすそうですね。

昔の漫画の効果線の様な感じを出してみました。

f:id:kazuhironagai77:20210704214846p:plain

f:id:kazuhironagai77:20210704214912g:plain

横に伸ばされるので丸いほうが線が滑らかかもしれません。

f:id:kazuhironagai77:20210704215031p:plain

これで試してみます。

f:id:kazuhironagai77:20210704215103g:plain

今週はここまでにしますが色々なイメージを試すだけでも結構勉強になります。

3.Cascadeの勉強の続き

Intro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [1]の続きをやっていきます。

3.1 InterpolationとSheetについて

先週、Interpolation とSheet を使用してBeamを曲げました。でもこれらのParameterの機能は調べませんでしたのでそこから始めます。

Interpolationについては直ぐに理解出来ました。

0です。

f:id:kazuhironagai77:20210704215232p:plain

1です。

f:id:kazuhironagai77:20210704215247p:plain

2です。

f:id:kazuhironagai77:20210704215302p:plain

3です。

f:id:kazuhironagai77:20210704215318p:plain

4です。

f:id:kazuhironagai77:20210704215333p:plain

5です。

f:id:kazuhironagai77:20210704215349p:plain

つまりTargetとSourceの2点間の間を直線で繋ぐのに何個の頂点を追加するかを示してます。

公式のDocumentであるBeam Type Data [2]によると

f:id:kazuhironagai77:20210704215406p:plain

と書かれています。

成程、SourceやTargetで示したTangent、つまり傾きを満たす最大限の角度を

f:id:kazuhironagai77:20210704215424p:plain

正確に表すためには

f:id:kazuhironagai77:20210704215440p:plain

の数が多ければ多い程良い訳ですね。

ただしDistributionのConstantのZの値が具体的に何を表しているのかは分かりませんね。

角度を表しているなら45度を代入したら円になるはずですよね。

f:id:kazuhironagai77:20210704215458p:plain

しかし実際は明らかに楕円形をしています。

Sheetについてですが、公式のBeam Type Data [2]によると

f:id:kazuhironagai77:20210704215515p:plain

と書かれています。

まずSheetが具体的に何を指しているんでしょうか?

恐らくですがMaterialを貼り付ける面の事をSheetと呼んでいるんでしょう。

例えばNiagaraRibbonの場合なら以下に示した図なら赤い部分がSheetに当たり、

f:id:kazuhironagai77:20210704215533p:plain

SpriteならParticleに貼りつけるMaterialを表示するための面がSheetになると思われます。

f:id:kazuhironagai77:20210704215601p:plain

Beamの場合はSheetをTargetとSourceの間に作成してその上にBeamのMaterialを貼っていると仮定すると上の公式の説明がなんとなく理解出来ます。

Beamを上から眺めてSheetの数によってBeamの見た目が変化するかを見てみます。

0の時です。

f:id:kazuhironagai77:20210704215619p:plain

0なら何も表示されないのではと思いまいしたがBeamが表示されています。なんででしょう?

1です。

f:id:kazuhironagai77:20210704215634p:plain

0と変わってないですね。

良く見ると真ん中で捻じれていますね。そのせいで途中から裏側が映し出されています。裏側にはなにも表示されていないので透明になっているんですね。

2です。

f:id:kazuhironagai77:20210704215652p:plain

真ん中に5本の筋がみえるようになりました。Sheetが一枚足されたのでしょう。ただしこの角度からは新しく足されたSheetに貼られたBeamの絵を見る事は出来ませんね。

3です。

f:id:kazuhironagai77:20210704215709p:plain

両端にひし形のイメージが追加され更に真ん中の線が左右対称の複雑な形状に変化しました。

ただしこの視点からみてBeamのイメージで消えている部分が見えるように成る事はありませんでした。

順調にSheetの数は増えていると考えられます。

4です。

f:id:kazuhironagai77:20210704215727p:plain

少しだけRibbonの消えている部分に絵が描かれるようになりました。

5です。

f:id:kazuhironagai77:20210704215744p:plain

あんまり変わっていないですね。

6です。

f:id:kazuhironagai77:20210704215802p:plain

イメージの見えていなかった部分のBeamがかなりはっきり見える様になりました。

10です。

f:id:kazuhironagai77:20210704215820p:plain

ほぼ左右対称になりました。

まあ、全部が理解出来た訳ではありませんが、Sheetの枚数はBeamがどの角度から見ても消える箇所がないようにするまで増やす。と考えるべきでしょうね。

BeamをLevel上に配置したら色々な角度から観察してもしBeamの一部が消えているならばSheetの数が足りないと言う事です。

3.2 BeamのRenderingについての考察

具体的にどうやってBeamをRenderingしているのかがまだ良く分かっていません。ずっと分からないままかもしれません。

BeamのRenderingでよく分からないのが、以下のイメージです。

f:id:kazuhironagai77:20210704215846p:plain

このRibbonを中心として180度カメラを回します。今、手前に来ているリボンの付け根の部分に注目して下さい。

180度、このRibbonを中心にしてカメラを回しました。

f:id:kazuhironagai77:20210704215906p:plain

本来なら前のRibbonに隠れて見えないはずの部分が見えています。遠近感が滅茶苦茶です。

もしParticleを飛ばし、その上に板を貼ってその板を繋げたモノをSheetと名付けて、そのSheetの上に絵を描いているだけならこんな破たんは起きないと思われます。どうやって実際のRenderingが行われているのは現状では全く不明です。

はい。Smileちゃんの出番です。

f:id:kazuhironagai77:20210704215923p:plain

Sheetは1にセットしています。

f:id:kazuhironagai77:20210704215940p:plain

これを見ると一枚の大きなSheetがSourceとTargetを両端として作成されているようにです。

今度は真横から見てみます。

f:id:kazuhironagai77:20210704220015p:plain

例え真横から見ても前半分はカメラ側を向いて後ろ半分はカメラの反対側を向いています。

逆向きになっても同じです。

f:id:kazuhironagai77:20210704220054p:plain

所が上から見ると、今度は逆になっています。奥半分のSheetがカメラ側を向いて手前の半分のSheetはカメラの反対側を向いています。

f:id:kazuhironagai77:20210704220121p:plain

かなり強引な構図ですが真下から見てみました。

f:id:kazuhironagai77:20210704220151p:plain

真下から見た時は、前半分はカメラ側を向いて後ろ半分はカメラの反対側を向いています。普通です。

以下にカメラをBeamの上に移動した時のSheetの変化を示します。

f:id:kazuhironagai77:20210704220236g:plain

分かりました。

根元の部分に注目して下さい。Sourceから一番最初のInterpolateまでの面は常にカメラに向かって正面を向いています。それ以外のSheetはその面の捻じれにつられて面がカメラに向いたり、カメラの逆側を向いたりしています。

では、Sheetが2枚になったらどうでしょうか?

f:id:kazuhironagai77:20210704220331p:plain

Sheetがお互いに90度に交わるように重なっています。勿論、Sheetの数は2枚になっています。

ああ、分かった。

Beam Type Data [2]で言っていた事の意味が分かりました。

f:id:kazuhironagai77:20210704220349p:plain

Sheetが一枚の時は以下の様に単に一枚のSheetが作成されます。

f:id:kazuhironagai77:20210704220408p:plain

Sheetが2枚の時は以下のようにお互いに垂直に交わるように作成されます。

f:id:kazuhironagai77:20210704220425p:plain

ここからは想像ですが、Sheetの数が3になったらお互いが60度の角度を保つように生成されるはずです。

試してみます。

f:id:kazuhironagai77:20210704220455p:plain

大体60度っぽい角度で3つのSheetが交差しています。

f:id:kazuhironagai77:20210704220516p:plain

別な角度で見てみました。どう見ても60度でしょう。

はい。Sheetについても完璧に理解出来ました。

それでですね。

奥にある部分が手前にRenderingされてしまう理由ですが、

f:id:kazuhironagai77:20210704220535p:plain

分かりません。

どっかのParameterを弄ったら直るのかもしれませんし、もしかしたらバグかもしれませんね。

でもこれだけ分かれば十分です。

3.3 Intro to Cascade: Creating a Beam Emitter | 07 | v4.2 Tutorial Series | Unreal Engine [1]の続きをやる

ここまで理解出来ればBeamに関しては十分ですが、せっかくですのでこのTutorialは終わらせる事にします。

Beam categoryのNoise Moduleを追加します。

f:id:kazuhironagai77:20210704220802p:plain

f:id:kazuhironagai77:20210704220809p:plain

Noise ModuleのLow Freq Enabledにチェックを入れ、Frequencyを10にセットします。

f:id:kazuhironagai77:20210704220828p:plain

このModuleは何を管理しているんでしょうか?

PreviewのBeamのイメージが以下の様になりました。

f:id:kazuhironagai77:20210704220846p:plain

Noise RangeのDistributionの設定を以下のように変えると

f:id:kazuhironagai77:20210704220909p:plain

以下に示した様にBeamの形状が微妙に変化し始めました。

f:id:kazuhironagai77:20210704220931g:plain

Beam Data ModuleのMax Beam Countの値を3にセットします。

f:id:kazuhironagai77:20210704221006p:plain

Beamの数が3本に見える様になりました。しかし実際に撮影すると1本しか見えません。

f:id:kazuhironagai77:20210704221021p:plain

後は一個を除いて特に重要なポイントはなかったです。

のでBeam Data ModuleのMax Beam Countを少しだけ調べる事にしました。

Beam Type Data [2]には

f:id:kazuhironagai77:20210704221039p:plain

と書かれています。

でもBeamだってSpawn RateとLife Timeで生成される数は決まるはずです。

その辺の関係を見てみます。

うーん。色々数字を弄って見たんですが良く分からないです。

最後の重要なポイントに行きます。

3.4 Distribution Float Particle Paramの具体的な使用方法について

このTutorialの最後にTargetの位置をBPやUEC++から指定出来ると言っていました。

f:id:kazuhironagai77:20210704221105p:plain

そしてその具体的なやり方は前のUE4C++のTutorialで実際に紹介してあると言いました。

これって2021-05-24のブログで勉強した中で唯一、具体的な方法が分からなかったDistribution Float Particle Paramの使用方法についての説明の事じゃないでしょうか?

流石に今週はこれ以上Cascadeの勉強をする時間はないので来週調べる事にします。

4.PickUpItemクラスにItemを追加

4.1 Dropped Item Baseクラスにitemを追加する

最初にDropped Item BaseクラスがItemを表示出来るようにします。

f:id:kazuhironagai77:20210704221135p:plain

その為には以下の関数にItem名とそのItemのMeshを追加する必要があります。

f:id:kazuhironagai77:20210704221150p:plain

追加するItemはData Table、Itemsで管理されている以下の3つです。

f:id:kazuhironagai77:20210704221205p:plain

以下の部分を追加しました。

f:id:kazuhironagai77:20210704221220p:plain

f:id:kazuhironagai77:20210704221227p:plain

テストします。

以下の設定にしました。

f:id:kazuhironagai77:20210704221245p:plain

角度やサイズに不満がありますがちゃんと回復薬が表示されています。

f:id:kazuhironagai77:20210704221302p:plain

イーサーの場合です。

f:id:kazuhironagai77:20210704221327p:plain

ダークイーサーの場合です。

f:id:kazuhironagai77:20210704221347p:plain

サイズと向きを直します。

Return Static Mesh Of Items関数に位置、回転、サイズなどのTransform情報を追加します。

f:id:kazuhironagai77:20210704221403p:plain

武器とItemで別なTransform情報を与えるようにしました。

f:id:kazuhironagai77:20210704221419p:plain

テストします。

f:id:kazuhironagai77:20210704221434p:plain

f:id:kazuhironagai77:20210704221443p:plain

f:id:kazuhironagai77:20210704221452p:plain

とりあえずはOKでしょう。

4.2 Itemを拾えるようにする。

PickUpItemウィジェットを改良してItemも拾えるようにします。

f:id:kazuhironagai77:20210704221524p:plain

以下にWidgetのイメージを示します。右端の落とし物の絵と属性は武器・防具専用のモノですのでこれをItem専用に直し必要があります。これは後で直します。

f:id:kazuhironagai77:20210704221542p:plain

今回は、Itemを拾う部分の実装を追加します。

Get Data Table Row Weaponsを追加します。Data TableはItemsをセットします。

ここでItemの名前が正しいのかをチェックしています。

f:id:kazuhironagai77:20210704221558p:plain

ItemsのData Tableは以下の様になっています。

f:id:kazuhironagai77:20210704221615p:plain

次にRPGGameInstanceのArrayであるItemsに拾ったItemの名前を追加します。

f:id:kazuhironagai77:20210704221638p:plain

ItemsはUE4C++のRPGGameInstanceクラスの変数です。

f:id:kazuhironagai77:20210704221655p:plain

この辺のPlayerの操作するCharacterのDataを管理する変数は最終的には全部UE4C++側のGame Instanceクラスで管理すべきなんでしょうか?

やっぱり最近のゲームはこれらのデータは全部サーバーで管理しているんでしょうか?

正直、サーバー関連のProgrammingはあんまり興味がないんです。いや興味はあるんですがUE4ほどの興味は無いです。のであんまり勉強が進みません。

ただAWSにしてもFire baseにしてもお金はかかるはずでEpic Game社が提供しているサーバーは無料ですから、この辺に詳しくなったら結構なビジネスチャンスがあるのではとは思っています。

次は拾ったItemをLevel上から消すための関数です。

f:id:kazuhironagai77:20210704221732p:plain

実装部が以下の様になっているんですがItem Nameが何のための変数だったのか忘れてしまいました。

f:id:kazuhironagai77:20210704221749p:plain

RPGGameInstanceBPにあるItemSpawnDataの実際の要素を見ると

f:id:kazuhironagai77:20210704221806p:plain

Nameには武器の日本語名、ItemNameには武器の英語名が記されています。

しかし武器のdata tableである  Weaponsには

f:id:kazuhironagai77:20210704221822p:plain

英語名はないんです。

あ、分かりました。

その武器の種類じゃなくてその武器そのものを示す名前がないとその武器だけをLevel上から消せなかったです。Item Nameはその武器個別の名前でした。

と言う事は

f:id:kazuhironagai77:20210704221839p:plain

は武器の場合もItemの場合も同じであると考えれます。

となると残りのコードはWeaponのがそのまま使用出来ると考えられます。

f:id:kazuhironagai77:20210704221858p:plain

これでどうでしょうか?

テストしてみます。

RPGGameInstanceBPのArrayであるItemSpawnDataに

f:id:kazuhironagai77:20210704221914p:plain

回復薬のデータを追加します。

f:id:kazuhironagai77:20210704221938p:plain

これで試してみます。

回復薬が地面に出現しました。

f:id:kazuhironagai77:20210704221956p:plain

Eボタンを押すと以下の画面が表示されました。

f:id:kazuhironagai77:20210704222027p:plain

このWidgetはこの後で直します。

「拾う」を押します。

f:id:kazuhironagai77:20210704222054p:plain

Itemが消えました。

Pause画面を開きます。

f:id:kazuhironagai77:20210704222113p:plain

道具袋の中に先程拾ったItemである回復薬がしっかり入っていました。

成功ですね。

4.3 PickUpItem ウィジェットのHUDを直す

以下に示した様に表示されるようにしました。

f:id:kazuhironagai77:20210704222136p:plain

変更したのは以下の部分にBindしている関数です。

f:id:kazuhironagai77:20210704222152p:plain

やり方は全部一緒でItemの場合の表示のためのコードを武器とは別に追加しただけです。

f:id:kazuhironagai77:20210704222208p:plain

出来ました。

PickUpItemの直しは今週、一番大変な部分と思っていたんですが、結果的に凄い簡単に出来ました。

やっぱりこれは先週、調べるだけ調べておいたお陰です。理由は分かりませんが、直す箇所を調べるだけ調べておいて、1週間置いてから直すと凄く楽に直せるようになります。

調べて直ぐ直すのに必要な能力を知力:10、精神力:10、体力:4とすると調べるだけ調べるのに必要な能力は知力:3、精神力:3、体力:4ぐらいで1週間置いてから直すのに必要な能力も同じ位ですみます。

これは一見大したことのない発見のように見えますが実際はかなりの大発見です。

まず、普通の人の知力は2です。頭が良い人でも3です。

それを精神力で無理やりプログラミングに集中する事(つまりプログラミング以外の事は全部忘れる。)で倍の知性つまり6くらいに挙げます。更にコーヒーのようなカフェイン飲料や、砂糖の塊のようなお菓子や炭酸飲料を飲む事(つまり知力のドーピングです。)で無理やり8くらいに上げます。それでも10には足りないのでGoogle先生に頼って作成したいプログラミングに似たコードもしくはそのものズバリを探してきてそのコードを参考にする事(ちょっとだけカンニングする。)事で何とか知力:10の問題を解いていくと言う感じになります。

このやり方は大変な精神力が必要でもあります。知力を2倍にするための集中力を生み出すには高い精神力が必要だからです。前の日に早く寝て十分な睡眠時間を確保する事も必要になります。ちょっとだけと夜更かしすればその分の負担は次の日の朝に必ずかかって来ます。

所が、直す箇所を調べるだけ調べておいて、1週間置いてから直すと必要な能力は知力:3、精神力:3、体力:4ぐらいになります。まだ試した事はないですが、1週間でなく次の日でも同じ効果は出て来ると思います。

つまり、上記で述べた様な無理をする必要が全く無くなります。

普通で良くなります。負担がものすごく軽くなります。

実際の効率から見るとPair Programmingに匹敵するぐらいの発見だと思います。Pair Programmingのように有名に成る事はないでしょうが。一応名前だけ付けておきます。Preparation and Implementation Programmingと名付けました。

5.Monsterがアイテムを落とすようにします

はい。それでは今週も調べるだけ調べておきます。

Monsterがアイテムを落とすように作成すると言いましたが2021-06-13のブログで説明したように、実際は戦闘が終わった時に戦闘場に存在している9体の像のどれかに話しかける事でアイテムが貰える仕組みになります。

f:id:kazuhironagai77:20210704222239p:plain

その時に一個問題があります。

戦闘後の勝利のポーズをPlay Animationで行っているためその後、Player の操作するキャラのAnim Classが外れてしまい、

f:id:kazuhironagai77:20210704222255p:plain

以下に示したように、武器と防具が手から外れた状態になってしまっています。

f:id:kazuhironagai77:20210704222311p:plain

このすぐ後に別なLevelに移動する場合は全く目立たないので問題なかったですが、この後に石像に話しかけるようなActionを取る場合、凄く目立ちます。直す必要があります。

これを来週やります。

名称は「戦闘勝利後のAnimationの直し」とします。

5.1 戦闘勝利後のAnimationの直しのための調査

まず、戦闘を勝利した後のAnimationの表示を実装している箇所をみます。

見つけました。

RPG Game Mode BPのEvent関数であるFight Over のPHASE Victoryの後です。

f:id:kazuhironagai77:20210704222333p:plain

まず最初のノードです。

f:id:kazuhironagai77:20210704222351p:plain

Monsterが分解・消滅するためのAnimationをPlay Animation ノードで実行しています。

Monsterはこの後消滅してしまうので、Play Animationノードを使用してAnim ClassにセットしてあるSkelSwordAni_Cが外れても問題ないです。

f:id:kazuhironagai77:20210704222409p:plain

次は音楽をセットして流していますね。

f:id:kazuhironagai77:20210704222433p:plain

Animationとは関係ない部分なので無視します。

次のノードでDispatcherであるCombat Over Victoryを読んでいます。

f:id:kazuhironagai77:20210704222449p:plain

どんな実装がCombat Over Victoryにされているのか覚えていません。調べます。

Combat Field Mapで実装されていました。Event Stop BGMに繋がっていてBGMを止めます。

f:id:kazuhironagai77:20210704222505p:plain

ここからPlayer の操作するキャラのAnimationの実装が始まります。

カメラの位置と角度を変えるノードです。

f:id:kazuhironagai77:20210704222521p:plain

この機能を作成した時には、まだ戦闘用のLevelを作成していませんでした。のでキャラの撮影をするカメラの位置を指定する為には、キャラに対して行う必要がありました。今は戦闘用のLevelは完成しているのでカメラを別に設置する事も可能です。まあ直す必要は感じませんが。

次のノードは何かを消しています。

f:id:kazuhironagai77:20210704222537p:plain

見たらCombat UIでした。

f:id:kazuhironagai77:20210704222602p:plain

やっと勝利のポーズのAnimationの部分に来ました。

思ったより複雑で、まず武器を装備しているか聞いています。

f:id:kazuhironagai77:20210704222623p:plain

武器を装備していなかった場合、Victory_noWeaponのAnimationが実行されます。

f:id:kazuhironagai77:20210704222641p:plain

武器を装備している場合は、武器が弓矢かそれ以外かで分けられます。

f:id:kazuhironagai77:20210704222656p:plain

弓矢の場合はVictory_BowAnimが実行されます。

f:id:kazuhironagai77:20210704222712p:plain

それ以外の武器を装備していた場合はVictory_SwordShieldAnimが実行されます。

f:id:kazuhironagai77:20210704222733p:plain

成程、この3つのAnimationをPlay Animationノードを使用して実行しているんですね。

分かりました。

この部分をMyThirdPerson_AnimBPに担当させる必要があります。

f:id:kazuhironagai77:20210704222755p:plain

5.2 MyThirdPerson_AnimBPの復習

MyThirdPerson_AnimBPを復習します。

AnimGraphを開いて見ます。

f:id:kazuhironagai77:20210704222816p:plain

Defaultを開きます。

f:id:kazuhironagai77:20210704222833p:plain

うーん。

変数を見ると以下のモノがありました。

f:id:kazuhironagai77:20210704222858p:plain

例えばWithWeaponですがBoolean変数で、以下に示した部分で赤く記した所の条件を担当しています。

f:id:kazuhironagai77:20210704222913p:plain

こんな感じです。

f:id:kazuhironagai77:20210704222945p:plain

この変数にどのようにアクセスして値を変更しているのかを調べれば、同じやり方で戦闘勝利後のアニメーションもMyThirdPerson_AnimBPに追加出来るはずです。

RPGGameModeBP内でMyThirdPerson_AnimBPのWithWeapon変数の値を変更している実装箇所を見つけました。

f:id:kazuhironagai77:20210704223000p:plain

うん。

こんな簡単に出来るんですか。

MyThirdPerson_AnimBPに追加するAnimationに関しては先程、示したAnimGraphのDefault Stateの中身のノードの内、以下の3つにそれぞれのVictoryのポーズを付ければ良いです。

f:id:kazuhironagai77:20210704223017p:plain

f:id:kazuhironagai77:20210704223023p:plain

f:id:kazuhironagai77:20210704223030p:plain

RPGGameModeBP内の勝利のAnimationは以下の部分を変更すれば良いだけです。

f:id:kazuhironagai77:20210704223047p:plain

あ、Set Visibilityノードの後にあるSet Anim Instance Classノードを外す必要もありました。

f:id:kazuhironagai77:20210704223104p:plain

以上です。

6.まとめと感想

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

  • Niagara SystemにおけるRibbonRenderingについての考察
  • Cascade SystemにおけるBeam ParameterInterpolation pointSheetについて
  • RPGItemが拾えるようにした。
  • RPGで戦闘終了後の勝利のポーズのAnimationについての調査

を行いました。

今週はいつもの週より楽でした。多分、Preparation and Implementation Programmingのお陰です。

7.参照(Reference

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

[2] Epic Games. (n.d.). Beam Type Data. Unreal Engine Documentation. Retrieved July 4, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/ParticleSystems/Reference/TypeData/Beam/

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

f:id:kazuhironagai77:20210627215343p:plain

<前文>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<本文>

1.今週の予定

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

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

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

2.Niagaraの勉強

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

f:id:kazuhironagai77:20210627215647p:plain

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

2.1 Component Rendererについて

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

f:id:kazuhironagai77:20210627215715p:plain

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

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

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

f:id:kazuhironagai77:20210627215731p:plain

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

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

f:id:kazuhironagai77:20210627215748p:plain

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

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

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

ありました。

f:id:kazuhironagai77:20210627215804p:plain

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

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

それを開いて見ると

f:id:kazuhironagai77:20210627215819p:plain

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

解説には

f:id:kazuhironagai77:20210627215909p:plain

と書かれていました。

そしてPreviewには

f:id:kazuhironagai77:20210627215923p:plain

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

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

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

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

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

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

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

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

2.2 UE4 - Niagara Ribbons [2]の勉強

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

これを勉強します。

<stretched Textureについて>

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

f:id:kazuhironagai77:20210627220014p:plain

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

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

f:id:kazuhironagai77:20210627220030p:plain

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

f:id:kazuhironagai77:20210627220047p:plain

と紹介されていました。

結構重要みたいです。

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

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

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

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

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

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

f:id:kazuhironagai77:20210627220104p:plain

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

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

f:id:kazuhironagai77:20210627220121p:plain

f:id:kazuhironagai77:20210627220127p:plain

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

f:id:kazuhironagai77:20210627220143p:plain

f:id:kazuhironagai77:20210627220151p:plain

Ribbon Emitter

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

NE_Ribbonと名付けました。

f:id:kazuhironagai77:20210627220212p:plain

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

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

f:id:kazuhironagai77:20210627220242p:plain

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

更にSprite Renderer Moduleも消します。

f:id:kazuhironagai77:20210627220302p:plain

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

消しました。

f:id:kazuhironagai77:20210627220320p:plain

Ribbon Rendererを追加しました。

f:id:kazuhironagai77:20210627220336p:plain

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

f:id:kazuhironagai77:20210627220352p:plain

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

f:id:kazuhironagai77:20210627220406p:plain

はい。予想通りでした。

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

f:id:kazuhironagai77:20210627220423p:plain

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

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

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

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

f:id:kazuhironagai77:20210627220458p:plain

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

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

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

f:id:kazuhironagai77:20210627220519p:plain

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

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

f:id:kazuhironagai77:20210627220537p:plain

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

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

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

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

gameDev Outpost氏の説明によると、

f:id:kazuhironagai77:20210627220554p:plain

f:id:kazuhironagai77:20210627220601p:plain

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

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

f:id:kazuhironagai77:20210627220620p:plain

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

f:id:kazuhironagai77:20210627220637p:plain

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

f:id:kazuhironagai77:20210627220845g:plain

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

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

f:id:kazuhironagai77:20210627220915p:plain

この説明は流石です。

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

f:id:kazuhironagai77:20210627220933p:plain

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

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

Life timeですが、

f:id:kazuhironagai77:20210627220951p:plain

f:id:kazuhironagai77:20210627220957p:plain

値を低くすると

f:id:kazuhironagai77:20210627221013p:plain

f:id:kazuhironagai77:20210627221021p:plain

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

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

f:id:kazuhironagai77:20210627221035p:plain

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

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

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

f:id:kazuhironagai77:20210627221132p:plain

<Level上のRibbon

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

f:id:kazuhironagai77:20210627221158p:plain

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

f:id:kazuhironagai77:20210627221219p:plain

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

f:id:kazuhironagai77:20210627221504g:plain

はい。

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

その結果、

f:id:kazuhironagai77:20210627221602p:plain

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

私が以下の解釈で

f:id:kazuhironagai77:20210627221617p:plain

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

f:id:kazuhironagai77:20210627221634p:plain

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

2.3 Ribbon Renderingの謎を解明する

f:id:kazuhironagai77:20210627221657p:plain

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

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

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

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

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

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

f:id:kazuhironagai77:20210627221714p:plain

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

f:id:kazuhironagai77:20210627221731p:plain

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

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

f:id:kazuhironagai77:20210627221752p:plain

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

f:id:kazuhironagai77:20210627221938g:plain

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

最初のRibbonです。

f:id:kazuhironagai77:20210627222018p:plain

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

f:id:kazuhironagai77:20210627222033p:plain

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

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

f:id:kazuhironagai77:20210627222049p:plain

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

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

f:id:kazuhironagai77:20210627222106p:plain

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

f:id:kazuhironagai77:20210627222128p:plain

の理由も分かります。

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

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

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

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

f:id:kazuhironagai77:20210627222151p:plain

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

f:id:kazuhironagai77:20210627222220p:plain

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

f:id:kazuhironagai77:20210627222237p:plain

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

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

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

f:id:kazuhironagai77:20210627222256p:plain

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

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

3.Cascadeの勉強

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

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

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

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

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

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

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

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

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

Mat_Beamと名付けました。

f:id:kazuhironagai77:20210627222343p:plain

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

f:id:kazuhironagai77:20210627222400p:plain

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

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

f:id:kazuhironagai77:20210627222417p:plain

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

f:id:kazuhironagai77:20210627222436p:plain

普通にDefault Litでした。

f:id:kazuhironagai77:20210627222452p:plain

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

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

f:id:kazuhironagai77:20210627222508p:plain

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

Mat_Beamの作成に戻ります。

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

f:id:kazuhironagai77:20210627222526p:plain

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

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

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

f:id:kazuhironagai77:20210627222544p:plain

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

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

例えばUTilingとVTilingが1の時は

f:id:kazuhironagai77:20210627222600p:plain

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

f:id:kazuhironagai77:20210627222617p:plain

UTilingの値を10に変更すると

f:id:kazuhironagai77:20210627222634p:plain

以下の配色になります。

f:id:kazuhironagai77:20210627222651p:plain

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

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

f:id:kazuhironagai77:20210627222732p:plain

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

次に行きます。

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

f:id:kazuhironagai77:20210627222826p:plain

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

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

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

f:id:kazuhironagai77:20210627222904p:plain

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

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

f:id:kazuhironagai77:20210627222953p:plain

f:id:kazuhironagai77:20210627223001p:plain

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

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

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

f:id:kazuhironagai77:20210627223150p:plain

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

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

試してみます。

f:id:kazuhironagai77:20210627223211p:plain

あれ?

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

f:id:kazuhironagai77:20210627223227p:plain

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

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

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

f:id:kazuhironagai77:20210627223313p:plain

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

f:id:kazuhironagai77:20210627223329p:plain

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

f:id:kazuhironagai77:20210627223348p:plain

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

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

f:id:kazuhironagai77:20210627223404p:plain

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

f:id:kazuhironagai77:20210627223421p:plain

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

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

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

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

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

f:id:kazuhironagai77:20210627223439p:plain

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

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

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

<P_Beamの作成>

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

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

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

f:id:kazuhironagai77:20210627223508p:plain

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

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

f:id:kazuhironagai77:20210627223524p:plain

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

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

f:id:kazuhironagai77:20210627223541p:plain

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

f:id:kazuhironagai77:20210627223600p:plain

f:id:kazuhironagai77:20210627223607p:plain

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

f:id:kazuhironagai77:20210627223630p:plain

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

f:id:kazuhironagai77:20210627223646p:plain

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

f:id:kazuhironagai77:20210627223710p:plain

何でよ?

またこれです。

何の説明もない。

f:id:kazuhironagai77:20210627223727p:plain

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

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

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

f:id:kazuhironagai77:20210627223753p:plain

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

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

f:id:kazuhironagai77:20210627223810p:plain

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

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

以下の様にです。

f:id:kazuhironagai77:20210627223825p:plain

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

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

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

f:id:kazuhironagai77:20210627223840p:plain

Targetも同様にします。

その結果、

f:id:kazuhironagai77:20210627223857p:plain

何も変わりません。

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

f:id:kazuhironagai77:20210627223914p:plain

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

f:id:kazuhironagai77:20210627223931p:plain

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

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

4.Monster Zoneのバグの直し

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

f:id:kazuhironagai77:20210627223956p:plain

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

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

4.1 バグの確認

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

f:id:kazuhironagai77:20210627224025p:plain

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

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

f:id:kazuhironagai77:20210627224055p:plain

Monsterは生成されています。

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

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

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

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

f:id:kazuhironagai77:20210627224121p:plain

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

f:id:kazuhironagai77:20210627224135p:plain

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

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

4.3 このバグについて

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

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

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

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

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

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

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

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

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

f:id:kazuhironagai77:20210627224210p:plain

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

f:id:kazuhironagai77:20210627224246p:plain

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

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

f:id:kazuhironagai77:20210627224302p:plain

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

f:id:kazuhironagai77:20210627224319p:plain

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

f:id:kazuhironagai77:20210627224334p:plain

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

f:id:kazuhironagai77:20210627224350p:plain

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

f:id:kazuhironagai77:20210627224405p:plain

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

f:id:kazuhironagai77:20210627224420p:plain

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

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

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

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

f:id:kazuhironagai77:20210627224442p:plain

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

f:id:kazuhironagai77:20210627224511p:plain

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

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

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

f:id:kazuhironagai77:20210627224535p:plain

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

f:id:kazuhironagai77:20210627224550p:plain

はい。出来ています。

魔法がない場合です。

f:id:kazuhironagai77:20210627224605p:plain

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

f:id:kazuhironagai77:20210627224636p:plain

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

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

f:id:kazuhironagai77:20210627224651p:plain

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

f:id:kazuhironagai77:20210627224707p:plain

テストします。

f:id:kazuhironagai77:20210627224722p:plain

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

そこを直します。

直しました。

f:id:kazuhironagai77:20210627224749p:plain

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

f:id:kazuhironagai77:20210627224804p:plain

出来ました。

今度はテストします。

5.3 テスト

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

f:id:kazuhironagai77:20210627224826p:plain

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

Level 3になった時です。

f:id:kazuhironagai77:20210627224842p:plain

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

Level 4になった時です。

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

f:id:kazuhironagai77:20210627224858p:plain

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

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

f:id:kazuhironagai77:20210627224917p:plain

Levelを最大まで上げます。

f:id:kazuhironagai77:20210627224933p:plain

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

出来てますね。

6.PickUpItemクラスにItemを追加

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

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

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

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

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

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

f:id:kazuhironagai77:20210627225007p:plain

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

f:id:kazuhironagai77:20210627225022p:plain

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

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

f:id:kazuhironagai77:20210627225037p:plain

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

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

f:id:kazuhironagai77:20210627225053p:plain

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

f:id:kazuhironagai77:20210627225108p:plain

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

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

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

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

f:id:kazuhironagai77:20210627225124p:plain

f:id:kazuhironagai77:20210627225131p:plain

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

f:id:kazuhironagai77:20210627225146p:plain

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

f:id:kazuhironagai77:20210627225201p:plain

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

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

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

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

f:id:kazuhironagai77:20210627225217p:plain

PickUpItem Widgetの話も戻ります。

f:id:kazuhironagai77:20210627225234p:plain

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

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

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

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

f:id:kazuhironagai77:20210627225251p:plain

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

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

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

全く覚えていません。

f:id:kazuhironagai77:20210627225310p:plain

中身を見てみます。

f:id:kazuhironagai77:20210627225325p:plain

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

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

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

f:id:kazuhironagai77:20210627225341p:plain

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

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

7.来週以降

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

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

8.まとめと感想

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

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

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

以上です。

9.参照(Reference

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

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

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

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

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

 

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

f:id:kazuhironagai77:20210620204450p:plain

<前文>

<発音記号や発音を勉強する前に>

本当に正しい発音を身に着ける必要があるんでしょうか?

アメリカ人が考える正しくない発音の英語の代表がインド英語です。私がアメリカにいた時は、理系の大学院生以外のアメリカ人は何を言っているのか全く分からんとインド英語をバカにしていました。

ところが、最近はYouTubeの理系、時にComputer Science関連で大学生や大学院生が授業の理解や課題を遂行する助けに使用出来る質の高いVideoのほとんど全部がインド人が作成したものになりました。そうなった今「インド英語何言っているかわからねー」と発言したら、それはインド人の英語の訛りが強くて分からないと言う意味には取ってもらえずインド人の講義している内容が理解出来るほどの頭脳を持っていない人と言う意味に取られるようになってしまいました。

つまり発音をアメリカ人と全く同じになるまで勉強するくらいなら、自分の専門分野で英語の動画を作成した方がアメリカでの評価が高くなる訳です。

となると正しい発音を身に着ける為に必要な学習コストを別な学問に振り分けた方がコスパが良いんじゃないでしょうか?

今日はその辺を踏まえた上で日本の英語発音教材についての私見を述べます。

まず日本の発音教材の私が思う3つの嘘について解説します。

  1. 英語の発音を知らないからネイティブの発音が聞き取れない。
  2. 英語の発音が出来るようになると英語の音も聞き取れるようになる。
  3. 英語の発音記号を勉強する事でネイティブのような発音が出来るようになる。

1についてですが、アメリカで10年暮らした私が断言しますが、アメリカで英語漬けの生活を送れば、英語の発音を全く知らなくてもネイティブの英語は全部聞き取れるようになります。大体2年位でほとんどの日常会話は聞き取る事は出来るようになります。ニュースやドラマなどの会話は結構時間がかかります。毎日見てる前提で更に2~3年位必要です。驚くかもしれませんが専門分野の英語を聞き取るのが一番簡単で、これは下手すると3カ月もあれば大体聞き取れるようになります。

この理由を自分なりに考えたんですが、英語はイントネーションとストレスが最も重要で発音はそれに付随するものだからと考えています。そして英語のイントネーションとストレスは英語を直に聞いていれば日本語が母語の人なら誰でも覚えられます。ただしある程度の必死さは必要で上記の例も必死さでランク付けすると、仕事、日常会話、テレビの娯楽やニュースの順で必死さが減少します。

つまりこの私の個人的な経験から断定すると、ネイティブの発音が聞きとれるようになるためには英語のイントネーションとストレスを英語を直に聞く事で脳に覚えさせる事が最も重要です。なので発音記号の音を覚えさえすればネイティブの英語が聞き取れるようになるとは思えません。

しかも最低でも2年は必要な訳で、英語がしゃべれない日本人が思っているほどネイティブの英語が聞き取れるようになる事は簡単ではありません。

2についてですが、私はアメリカで英語が分からなくて困る事は全くなかったですが、それでもLとRの区別は出来ません。特に子音の後にLやRが続く単語、Play とかPrayなんかは日常会話のスピードですらどっちか分かりません。しかし発音は出来ます。私だけ特別なのかと思ったら、同じ事を言っている日本人は沢山いました。

つまり英語の発音が出来る様になっても英語の音素が聞き取れる様になるとは限りません。

3についてですが、発音だけに関しては音声学を正しく理解した英語のネイティブが付きっ切りで指導すれば可能だと思います。しかしあなたのためにそんなに面倒な事をしてくれる人がいますかね。私の経験から言うと、一つの英語の音を正しく発音出来るようになるのに30分から1時間のワンツーマンの練習が必要です。それだけでも大変なのにその音を作る口の動かし方を次の日には忘れてしまいます。次の日にはまた最初からやり直しです。これを毎日繰り返して3週間位するとやっとその音を発音出来るようになります。

ぶっちゃけアメリカ人にとって日本人は、日本人が思っている程重要な存在じゃないです。日本人から見たインドネシア人ぐらいの立場です。あなたが大学で音声学をしっかり勉強したと仮定して、全く知らないインドネシア人から日本語の発音教えて下さいって言われてそんな大変な事やりますか。私が想像するに金だけとって適当に済ませて、発音出来てますよとおだててお終いじゃないですか。アメリカ人だって同じです。面倒くさいから適当に教えてお終いです。

しかもこんな日常が忙しいのに毎日、通える訳ねーだろとなります。つまり奇跡的に音声学を勉強したアメリカ人が超人的な親切さで貴方に発音を教えようとしても貴方の事情のせいで3番も出来ない可能性が高くなるわけです。

正し、これを調べている間に一個だけフィリピン留学というかフィリピンで合宿して英語の発音だけ徹底的に訓練する学校みたいなのが出て来たんですが、ひょっとするとこれは当たりの発音教材の可能性もあります。まずフィリピンですのでアメリカに留学するほどお金がかからないはずです。更にフィリピン人の英語ですが平均は日本と同じ位で日本人が思っている程上手くはないですが、無茶苦茶上手い人達が一定の数います。大卒レベルのアメリカ人と全く同じ英語をしゃべります。この人達の中で音声学を勉強した人からワンツーマンで英語の発音を教わったら結構上手くなる気がします。しかも合宿形式だから毎日発音の練習するわけで正しい発音をする為に必要な3週間毎日繰り返すが自然に達成出来ます。

唯一の問題はこのフィリピン人達は日本語で教える事は出来ない訳で英語で英語の発音方法を教えるはずです。Bi­labial、Labio­dental、Lingua-Dental、Alveolar、Post­alveolar、Palatal、Velar、Glottalなどの専門用語は前もって理解しておく必要がありますし最低限の英会話は出来る必要があります。

まあ、でも全体的に言えば発音教材が宣伝してるような発音出来るようになれば

  1. 英語のネイティブの発音も聞き取れる。
  2. 英語の音も聞き取れるようになる。

は嘘でしょうし

  1. 英語の発音記号を勉強する事でネイティブのような発音が出来るようになる。

も極少数の例外を除いて嘘でしょう。

じゃ何が本当かというと精々、ネイティブが聞いて理解出来るレベルの発音になる位が大体正しい目安だと思います。

私がアメリカで暮らしていて純粋に発音が通じなくて苦労した音を思い付くままに書き出すと

  • Erの発音
  • Vの発音
  • Angryが通じない
  • ンとNの音は全然違った
  • Yの発音
  • Thの発音

ぐらいです。良く聞くdzとzで困った経験は私はないです。後、factsがfu〇kに間違えられた経験もないです。私は発音記号は全く知らなかったですがFactsはフェアクスと聞こえていましたのでフェアクスと言っていました。それで通じなかった記憶はありません。日本人が発音するZooはアメリカ人にはDzooに聞こえると言う話は、日本に帰って来てから始めて聞きましたので分かりません。

これらの日本人が発音出来ない音はガチで問題起こす可能性があります。白人の女の子と会話しててAngryが全く通じないで「私の事uglyって言ってんの?」と言われた時は全身から冷や汗出て来ました。ただしこれは私の発音が悪かっただけじゃなくてアメリカ人はAngryをエィングリーって発音するんです。後、日本語のンは英語のNとは全く違う音なので私のンの音がdark Lの音に聞こえたのかもしれません。

この辺の発音が聞き間違えられないコツみたいなのを発音教材から教わる分にはかなりコスパはイイと思います。

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

<本文>

1.今週の予定

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

  • Niagara の勉強とCascadeの勉強
  • Monster Zoneのバグの直し
  • ゲームの改善点の直し

2. Niagaraの勉強

何か、先週はやる気が起きなかったんですが、その理由が分かりました。

今まで、私は散々UE4VFX を真に理解するためには、どのようにRenderingされているのかを理解するのが最も重要であると口を酸っぱくして語っていました。つまり

  • UE4VFX は全てParticle Systemで作成されている事。
  • Particle 一個一個にMaterialを貼り付けてそのMaterialをカメラに対して常に正面になるように向けるのがSprite。
  • そのParticle一個一個にStatic Meshを貼り付けているのかMesh。

これらの事を理解するのが絶対必要です。この事をしっかり語っているTutorialには出会った事はありません。つまり世界で私だけが断言しています。

のにRibbon Effectを作成するに当たってRibbon EffectがどうやってRenderingしているのか全く理解しないで進んでいました。自分でここが大切であると断言した事を自分で無視していました。

これではやる気出ないのも当たり前です。

今回は徹底的にRibbon EffectがどうやってParticleをRenderingしているのかを調査し解明しましょう。

2.1 Basics of Ribbons in UE4 [1] の勉強

UE4VFXを自在に使いこなすにはParticle SystemとそれぞれのEffectの理論をしっかり勉強する必要がある。これを断言しているのは世界中で自分だけ。と先程宣言しましたが、ちょっとGoogleで検索したら全く同じ事をしている人がすぐに見つかりました。

f:id:kazuhironagai77:20210620204906p:plain

この人のBlogでCascadeの場合ですがUE4Ribbonがどのような方法で生成されているのかを事細かに説明していますので、これを勉強します。

このサイトの解説によると

RibbonはObjectが通った跡の痕跡を示すもので以下の様に黄色の枠で囲われた球のMeshが左から右に移動した場合、球が移動した跡に作成されます。

f:id:kazuhironagai77:20210620204925p:plain

これだけ見ると球のケツにMaterialが貼り付けられている感じですね。

以下の続きの図をみると球のケツに貼りついているMaterialの長さが変化しています。

f:id:kazuhironagai77:20210620204943p:plain

これは向きが変わったらどうなんでしょうか?

2.2 Ribbon Rendering はparticleのケツにSpriteを貼っただけなのか?

Basics of Ribbons in UE4 [1]を読んでいたらRibbon RenderingってParticleのケツにSprite、もしくはMeshを貼っただけなんじゃないの?という疑問が出て来ました。これは実際にRibbon Emitterを作成してみれば分かります。

試してみます。

f:id:kazuhironagai77:20210620205006p:plain

でEmitter Systemを作成して

f:id:kazuhironagai77:20210620205023p:plain

Ribbon RenderingのMaterialをSmile_Matに変更します。

Leftから見た場合です。

f:id:kazuhironagai77:20210620205042p:plain

Topから見た場合です。

f:id:kazuhironagai77:20210620205059p:plain

これを見ると尻尾型のMeshにMaterialを貼っている感じでSpriteではない事は確かです。

もう少し詳しく見てみます。

Beam Emitter Setup ModuleのBeam Endのxを100にセットします。

f:id:kazuhironagai77:20210620205118p:plain

新しいBeam Width Moduleを追加して以下の設定にします。

f:id:kazuhironagai77:20210620205134p:plain

これでMaterialに使用されているTextureが歪まない状態で表示されるはずです。

Rightから見た状態です。

f:id:kazuhironagai77:20210620205150p:plain

Smileが綺麗な形で見えています。

今度はTopから見てみます。

f:id:kazuhironagai77:20210620205207p:plain

あれ、Spriteと同じようにMaterialをCameraに対して正面になるようにRenderingしていますね。

Previewの画面をPerspectiveにして色々動かしてみると

f:id:kazuhironagai77:20210620205225p:plain

f:id:kazuhironagai77:20210620205233p:plain

f:id:kazuhironagai77:20210620205240p:plain

常にカメラに対して正面と言うわけでもないようです。

Beam Width Moduleを元に戻します。だだしサイズを統一する為にScale Curveを100にしました。

f:id:kazuhironagai77:20210620205257p:plain

イメージが以下の様に変化しました。

f:id:kazuhironagai77:20210620205320p:plain

あー。成程ね。こういう事ですか。

もっとはっきりさせるためにBeam Emitter SetupのBeam Endのxの値を200にします。

f:id:kazuhironagai77:20210620205337p:plain

Topから見たイメージです。

f:id:kazuhironagai77:20210620205354p:plain

Leftからみたイメージです。

f:id:kazuhironagai77:20210620205410p:plain

一見Spriteと同じようにTextureを常にカメラに向けて正面になるように向けているのかと思いますが、Perspectiveで確認すると

f:id:kazuhironagai77:20210620205426p:plain

カメラがX軸に沿って移動した時はTextureはカメラの動きに対して全く動きません。

物凄く原始的な観点から言えば、Ribbon RenderingはParticleの後ろに長方形の厚みの無い紙を貼ってそこに描いた絵を表示していると言う事みたいですね。

厚みが無くて細長い長方形はRibbonの形状そのものなんで、そのままを表現していると言えなくもないですね。

2.3 Static BeamのSpawn Burst Instantaneous Module のSpawn Countが100にセットされている件について

これの意味が分かりません。

f:id:kazuhironagai77:20210620205451p:plain

だってParticleをBurstするのに1個で十分じゃないですか。

1にします。

f:id:kazuhironagai77:20210620205508p:plain

あれ。イメージが消えました。

f:id:kazuhironagai77:20210620205525p:plain

2にしたらこれです。

f:id:kazuhironagai77:20210620205547p:plain

3にしたらまた消えました。

4は以下のようなイメージが。

f:id:kazuhironagai77:20210620205603p:plain

8です。

f:id:kazuhironagai77:20210620205620p:plain

10です。

f:id:kazuhironagai77:20210620205638p:plain

25です。

f:id:kazuhironagai77:20210620205656p:plain

段々スムーズなイメージになって来ました。

50です。

f:id:kazuhironagai77:20210620205712p:plain

まだスムーズさが足りませんね。

100です。かなりスムーズですがまだカクカクしている部分もあります。

f:id:kazuhironagai77:20210620205728p:plain

200です。完全にスムーズなイメージになりました。

f:id:kazuhironagai77:20210620205745p:plain

でもなんでEmitter Spawnがイメージのスムーズさに関係しているんでしょうか?

先々週、作成したリボンではどうだったのか確認しましたが、先々週、作成したリボンではSpawn Bust Instantaneous Moduleは実際は使用していませんでした。

f:id:kazuhironagai77:20210620205802p:plain

以下の様にSpawn Bust Instantaneous Moduleを切っても

f:id:kazuhironagai77:20210620205818p:plain

何も変化しません。

f:id:kazuhironagai77:20210620205836p:plain

何でこんな違いがあるのかと更に調べたら、

先々週、作成したリボンではInitialize Ribbon Moduleを使用してRibbon を作成していますが、

f:id:kazuhironagai77:20210620205854p:plain

今回Templateに使用したStatic Beamは

f:id:kazuhironagai77:20210620205910p:plain

Initialize Particle Moduleを使用してその後でSpawn Beam Moduleを使用していました。

Ribbon Renderingを使用してもParticleのSpawn方法については色々な方法があるみたいですね。

2.3 Initialize Ribbon ModuleとSpawn Beam Moduleについて

Particle Spawn Group [2] によると以下の様に解説されていました。

f:id:kazuhironagai77:20210620205937p:plain

Bezier Splineってどんな形でしたっけ。

調べます。

Bezier Curves and Splines [3] に分かり易い解説がありました。MITの公開講座ですね。UndergraduateのComputer Graphicsの授業で使用されたSlide集のようです。

まずSplineの定義です。

f:id:kazuhironagai77:20210620205957p:plain

Control Pointsを使用する事とそのPointの間をInterpolateする事だそうです。

Cubic Bezier Curveは以下の方法で計算するそうです。

f:id:kazuhironagai77:20210620210013p:plain

でもこのやり方だとApproximationでInterpolationじゃないですね。と言う事はSplineじゃないからBezier Splineは別な方法で計算していと言う事でしょうか?

Bezier Splineの計算方法についての説明はなかったです。

以下に行列に書き直したものにSpline Matrixと記載されていますが、Bezier SplineとCubic Bezier Curveは同じ事を指しているんでしょうか?

f:id:kazuhironagai77:20210620210032p:plain

Bezier SplineとCubic Bezier Curveの違いは分からなかったですがslide自体は分かり易かったです。Wikipediaなんかで調べるよりMITの公開講座を直接見る方が断然分かり易いです。こういう事は結構あります。

脱線し過ぎました。Spawn Beamに戻ります。

f:id:kazuhironagai77:20210620210108p:plain

これをもう一回読み直すと、今日、私が発見したRibbon Renderingの特徴みたいなヤツが全部書かれていますね。つまりRibbon Renderingの特徴と思われていたモノは実はSpawn Beamの特徴だったって事でしょうか?

じゃ、Initialize Ribbon Moduleはどうなのかと言うと以下の解説が書かれていました。

f:id:kazuhironagai77:20210620210126p:plain

Several common parametersをどう解釈するかによりますが、Initialize Particle Module+Spawn Beam ModuleとInitialize Ribbon Moduleはほとんど同じじゃないでしょうか?

多分ですが、違いはInitialize Ribbon ModuleはRibbonを捻じる事が出来る事じゃないでしょうか?

2.4 Initialize Ribbon Module

Initialize Ribbon Moduleで「2.2 Ribbon Rendering はparticleのケツにSpriteを貼っただけなのか?」でやった事と同じ事をやってみます。

まず結果から表示します。その後でどのように作成したのかの説明をします。

Top viewです。

f:id:kazuhironagai77:20210620210150p:plain

Left Viewです。

f:id:kazuhironagai77:20210620210206p:plain

Perspective画面で回転してみました。

f:id:kazuhironagai77:20210620210223p:plain

この結果を見る限りはInitialize Ribbon Moduleを使用した場合もInitialize Particle Module+Spawn Beam Moduleと変わらないように見えます。SpriteをParticleのケツに貼りつけているだけです。

正し、大きく違う箇所もありました。それが必要なModuleです。

f:id:kazuhironagai77:20210620210238p:plain

Initialize Particle Module+Spawn Beam Moduleの時は、ParticleをSpawnするためにSpawn Burst Instantaneous Moduleを使用します。

f:id:kazuhironagai77:20210620210259p:plain

Initialize Ribbon Moduleの場合はSpawn Rate Moduleを使用する必要があります。

Spawn Rateの値が低いとまず何も表示されません。

f:id:kazuhironagai77:20210620210317p:plain

例え表示されてもカクカクのアニメーションになります。

f:id:kazuhironagai77:20210620210750g:plain

流石にScreen shootでは伝えきれないのでGifで映像を撮影しました。ただしサイズが1.42MBで普通のScreenshotを100KBとすると14倍です。

圧縮したら約600KBまで下がりました。これ位なら許容範囲ですね。ちょっとずつGifも使っていきます。

次にAdd Velocity Moduleを追加する必要があります。Spawn Beam Moduleの場合は生成されたParticleの後ろに付きます。しかしInitialize Ribbon Moduleの場合はparticleが移動した痕跡に描かれます。Particleが移動する必要があります。

これ以上はParticleそのものの動きをもっと正確に理解しないと解明出来ないです。来週以降の課題にしましょう。

Ribbon RenderingがParticleのケツにSpriteをくっつけているRendering方法であるという事は今週の調査で判明したと思います。それで充分でしょう。

Initialize Ribbon Module を使用したRibbon Renderingを以下に示した様にLevel上で動かすとSpawn Rate Moduleが使用されているのが良く分かります。

f:id:kazuhironagai77:20210620211234g:plain

今週のNiagaraの勉強はここまでとします。

3. Cascade の勉強

3.1 Basics of Ribbons in UE4 [1]の続き

「2.1 Basics of Ribbons in UE4 [1] の勉強」で少しだけ勉強したBasics of Ribbons in UE4 [1]の続きをやります。

<Souler coastersRibbonの違い>

まず、Ribbonはpanning textures、所謂  Souler coastersじゃない事を宣言しています。

Souler Coasterは以下の様な捻じれたMeshにTextureを貼るEffectだそうです。

f:id:kazuhironagai77:20210620211414p:plain

ふーん。

ですがこれだって一種のRibbonと思うんですが違うのでしょうか?

<How Ribbons work with UV sets 0 and 1

ここでUV0とUV1を使用した場合のRibbonの違いについて述べています。ただこれを理解するためにはCascadeRibbonが作成出来ないと理解出来ませんね。

3.2 Intro to Cascade: Creating a Ribbon Emitter | 08 | v4.2 Tutorial Series | Unreal Engine [4] 」でRibbon作成の基礎を学ぶ

もう行ったり来たりして錯綜していますが、しょうがないです。

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

因みにこのTutorialにやや対応しているContent ExampleのEffectにあるRibbon (ただし下に示したのは4.26版)の例では2.5に配置されています。

f:id:kazuhironagai77:20210620211448p:plain

先週勉強したSampleは1.2のヤツでRibbonは遥か後に勉強します。

出来ました。

f:id:kazuhironagai77:20210620211505p:plain

f:id:kazuhironagai77:20210620211513p:plain

何これ。全然違うじゃん。と思うかも知れませんが、基礎だけ学びました。

そしてもっとそぎ落としていきます。

f:id:kazuhironagai77:20210620211530p:plain

f:id:kazuhironagai77:20210620211536p:plain

これ以上無い位要らない箇所を削ぎ落しました。

3.3 再びBasics of Ribbons in UE4 [1]の続き

前節で作成した最低限の機能しかないRibbon EffectのRequired ModuleのMaterialをSmile_Matに変更します。

f:id:kazuhironagai77:20210620211558p:plain

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

f:id:kazuhironagai77:20210620211856g:plain

これはBasics of Ribbons in UE4 [1]で述べているUV0の場合と同じです。

f:id:kazuhironagai77:20210620211939p:plain

今度はUV1にセットしてみます。

f:id:kazuhironagai77:20210620211957p:plain

はい。

f:id:kazuhironagai77:20210620212011p:plain

あれ?

Tutorialだと以下の様になっているんですが?

f:id:kazuhironagai77:20210620212028p:plain

ひょっとしてUV1ってTexCoord[1]の事じゃないんでしょうか?

調べます。

3.4 UV0とUV1について

Working with UV Channels [5] によるとTexCoord[0]がUV0でTexCoord[1]がUV1で合っています。

更にTexCood[0]の場合、以下のTextureを

f:id:kazuhironagai77:20210620212052p:plain

以下の図のように(つまりそのまま)に貼り付けるそうです。

f:id:kazuhironagai77:20210620212108p:plain

ところが、TexCood[1]の場合、以下の様に貼り付けるそうです。

f:id:kazuhironagai77:20210620212127p:plain

うーん。

同じじゃね。

色々探したんですがUV0からUV1にセットするとTextureの貼り方が

f:id:kazuhironagai77:20210620212145p:plain

から

f:id:kazuhironagai77:20210620212200p:plain

に変わると主張しているTutorialはBasics of Ribbons in UE4 [1]以外見つかりませんでした。

正直ちょっと怪しい気がしてきました。

区切りもいいですし今週はここで止めてCool downします。

4. Monster Zoneのバグの直し

4.1 Monster Zoneのバグについて

Monster Zoneには現在2つのバグが存在しています。

最初のバグは、以下の図で示したようなMonster Zone1のTerritory内かつMonster Zone 2のblock内で戦闘になった場合です。 

f:id:kazuhironagai77:20210620212235p:plain

戦闘後にLandscape4に帰還するとMonster Zone 1のモンスターは生成されますが、Monster Zone2のMonster は生成されません。Monster Zone 2は移動し放題になってしまいます。

次のバグは Block内に侵入はしているが、Territoryにはギリギリ侵入していない状態で戦闘になった時です。

以下の図の場合だと赤く記された部分で戦闘になった場合です。

f:id:kazuhironagai77:20210620212253p:plain

戦闘から戻って来ると、Monsterが消えています。これはTerritoryに侵入していないのでMonsterが生成されないためです。

4.2 Monster Zoneのバグの直し方

これらのバグの直し方は簡単です。

今まで、戦闘から戻った時、記録したTerritoryを元にMonsterの生成を行っていました。これをTerritoryではなくBlockに変更します。これでOKです。

正しBlockはArrayになるので実際のコードは少しだけ複雑になります。

<Territoryの記録などについて>

Blockの記録を作成する前に現状はどうやってPlayerのいるTerritoryを記録しているのか、その記録を元にMonsterを再生しているのかなどを調べておきます。

PlayerのいるTerritoryを記録する変数はRPG Game Instance BPにあるMonster Territory Numberです。

f:id:kazuhironagai77:20210620212322p:plain

この変数を追ってみます。

まずMonster ZoneクラスでTerritory内に侵入した時に呼ばれています。当然ですね。

RPG Game Instance BP のMonster Territory NumberにMonster Zoneクラスの変数である別のMonster Territory Numberの値をセットしています。

f:id:kazuhironagai77:20210620212501p:plain

そして当然ながらTerritoryから出た時にRPG Game Instance BP のMonster Territory Numberを0にセットしています。

f:id:kazuhironagai77:20210620212520p:plain

それだけでした。

ええ。もっと色々使用してたと思ったんですが。

敢えてもう一個だけ挙げるとすればLandscape4 のBeginPlay関数で呼ばれていました。

f:id:kazuhironagai77:20210620212537p:plain

一応RPG Game Instance BP のMonster Territory Number が0の時は使用する予定なのでこれも記録しておきます。

これで全部でした。

あれ。おかしいぞ。

倒したモンスターをMonsterSpawnData_Landscape4から消去する時にRPG Game Instance BP のMonster Territory Numberを使用していたはずです。

f:id:kazuhironagai77:20210620212602p:plain

ありました。

f:id:kazuhironagai77:20210620212619p:plain

更にもう一か所忘れていました。Monster ZoneクラスのEvent Begin Play関数でTerritory内のMonsterを生成する時です。

f:id:kazuhironagai77:20210620212635p:plain

これで全部です。

つまりRPG Game Instance BPにあるMonster Territory Numberを使用しているのは、

  • Monster ZoneTerritoryに侵入する。
  • Monster ZoneTerritoryから退散する。
  • Monster ZoneEvent BeginPlay関数でMonster を生成する。
  • RPGGameModeBPで倒したモンスターをMonsterSpawnData_Landscape4から消去する。

の4つの時に使用されています。

<直し方についての考察>

最後の倒したMonsterをMonsterSpawnData_Landscape4から消去する時はRPG Game Instance BP のMonster Territory Numberから行う必要があります。のでRPG Game Instance BP のMonster Territory Numberも必要です。

残りの3つは新しく作成するMonster ZoneのBlockに侵入した時ための変数で管理すべきです。

4.3 Monster Block Numbersの作成

Monster Block NumbersをRPG Game Instance BPに作成します。

f:id:kazuhironagai77:20210620212712p:plain

ここにMonster ZoneのBlockに侵入した時にそのMonster ZoneのMonster Territory Numberを追加します。

以下のコードを追加しました。

f:id:kazuhironagai77:20210620212729p:plain

更に確認のためにRPG Game Instance BP のMonster Block Numbersにある整数をPrintします。

f:id:kazuhironagai77:20210620212745p:plain

テストします。

f:id:kazuhironagai77:20210620212804p:plain

出来ていますね。

今度はMonster ZoneのBlockから退散した時にそのMonster ZoneのMonster Territory NumberをRPG Game Instance BP のMonster Block Numbersから消去します。

BlockのOn Actor End Overlap Eventに以下のコードを追加します。

f:id:kazuhironagai77:20210620212823p:plain

勿論、この部分のコードは戦闘で別のLevelに移動する時は呼び出されないように作成しています。

テストします。

f:id:kazuhironagai77:20210620212839p:plain

f:id:kazuhironagai77:20210620212845p:plain

Monster ZoneのBlockから退散した時にMonster ZoneのMonster Territory Number と同じ数字をRPG Game Instance BP のMonster Block Numbersから消去出来ている様です。

本当にRPG Game Instance BP のMonster Block NumbersからMonster ZoneのMonster Territory Number と同じ数字を消去出来ているか確認するために以下のコードを追加しました。

f:id:kazuhironagai77:20210620212904p:plain

出来ています。

f:id:kazuhironagai77:20210620212924p:plain

最後にMonster ZoneのEvent BeginPlay関数でRPG Game Instance BP のMonster Block NumbersからMonster を生成するようにします。

Monster ZoneのEvent BeginPlay関数からいかのコードを外して

f:id:kazuhironagai77:20210620212941p:plain

以下のコードを追加しました。

f:id:kazuhironagai77:20210620212956p:plain

これで全部直ったはずです。

テストします。

以下の赤色の部分で戦闘をします。

Monster Zone2 のモンスターと戦闘しますが、Monster Zone1のBlock内にも侵入していますのでMonster Zone1のモンスターも出現しています。

f:id:kazuhironagai77:20210620213014p:plain

戦闘から戻ると遠くにMonster Zone1のMonsterが生成されている事が確認出来ました。

f:id:kazuhironagai77:20210620213035p:plain

勿論、Monster Zone2のモンスターも生成されています。

f:id:kazuhironagai77:20210620213051p:plain

一応成功です。

これで完成です。と思ったら

f:id:kazuhironagai77:20210620213111p:plain

この直し方だと

f:id:kazuhironagai77:20210620213128p:plain

このバグは直せない事に今、気が付きました。

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

今週はここまでです。

5. ゲームの改善点の直し

5.1 Start画面の部屋がStarter Kitで作成されているのでFantasy感が薄い

以下の様に直しました。

f:id:kazuhironagai77:20210620213210p:plain

f:id:kazuhironagai77:20210620213222p:plain

f:id:kazuhironagai77:20210620213230p:plain

こうやって見ると使用しているImageがちょっとしょぼいですね。

f:id:kazuhironagai77:20210620213247p:plain

以下の様に描き直しました。

f:id:kazuhironagai77:20210620213309p:plain

f:id:kazuhironagai77:20210620213317p:plain

もう少しレイアウトを考えないと駄目ですね。今週はここまでにしておきます。

5.2 戦闘後にLevelが上がった場合

今週は軽く戦闘後のセリフの管理方法の復習程度で留めておきます。

戦闘が終了してPlayerのキャラのLevelが上がる場合、RPG Game Mode BPの以下の箇所でLevelが上がった事を知られるセリフを追加しています。

f:id:kazuhironagai77:20210620213343p:plain

関数Get Dialogue From Combat Dialogue 2DTの実装は以下の様になっています。

f:id:kazuhironagai77:20210620213358p:plain

Get Data Table Row Combat_Dialouge1からセリフを引っ張って来ています。

Get Dialogue From Combat Dialogue 2DT関数のparameter、Indexの値は15にセットされています。

f:id:kazuhironagai77:20210620213418p:plain

のでGet Data Table Row Combat_Dialouge1の番号16のセリフが選択されます。

f:id:kazuhironagai77:20210620213437p:plain

以上でした。

この後に以下に示した「読みましたボタン」を表示します。

f:id:kazuhironagai77:20210620213452p:plain

そして「読みましたボタン」をクリックするとLevelが上がった事を知らせ更にどのParameterがどれ位上昇したのかを知らせる様にしたいです。

この「読みましたボタン」、自分で作成したくせにどうやって機能しているのか全く忘れていました。

以下にRPG Game Mode BPで実際に使用されている「読みましたボタン」のコードを示します。

f:id:kazuhironagai77:20210620213509p:plain

まずCombat UI ウィジェットのSet Confirmed Button Visible関数を呼び足して「読みましたボタン」が見える様にします。

因みにSet Confirmed Button Visible関数は以下の様な実装になっています。

f:id:kazuhironagai77:20210620213526p:plain

そして見える様になった「読みましたボタン」をクリックするとEvent DispatcherであるConfirm Button is Clickedが呼ばれます。

f:id:kazuhironagai77:20210620213549p:plain

f:id:kazuhironagai77:20210620213556p:plain

すると最初のRPG Game Mode BPのコードに戻って来てBind Event to Confirm Button is Clicked のEventが発動します。

f:id:kazuhironagai77:20210620213614p:plain

ここからがポイントですが、このEventの内容が毎回変わります。

例えば今回の戦闘が終了した後では以下の様な内容になっています。

f:id:kazuhironagai77:20210620213631p:plain

戦闘中に攻撃などの選択をした時は以下の様な内容になっています。

f:id:kazuhironagai77:20210620213647p:plain

こんな方法で「読みましたボタン」を実装していたなんて完全に忘れていました。

因みに「読みましたボタン」を押してConfirm Button is clickedが呼ばれた後は以下のコードが実行されます。

f:id:kazuhironagai77:20210620213706p:plain

GameModeをRPGGameModeBPにCast するのはEvent BeginPlayでやっておくべきでしょう。その後の関数、Had Read Fight is Start()も何をやっているのか不明です。これは後で調べます。その後のSet Visibility()で「読みましたボタン」をCollapsedにするのは「読みましたボタン」を見えなくするためですね。最後のPlay Sound 2Dはボタンを押した時の音を出していますね。

Had Read Fight is Start()関数が何をやっているのか不明なので調べます。後、この関数の名前、もう少し分かり易い名前に変えます。

この関数BPで作成した関数ではなくUE4C++のRPG Game Modeで作成した関数でした。

f:id:kazuhironagai77:20210620213723p:plain

以下の部分を見るとこの変数は戦闘が開始した時にTrueにセットされるべき変数のようです。

f:id:kazuhironagai77:20210620213739p:plain

もう少しコードをキチンと読み直す必要がありますがHad Read Fight is Start()関数を毎回呼ぶ必要はないと思います。これが原因のバグは今まで発生していませんので今週は直しませんが後できちんと調べて直します。

この辺の戦闘システムを作成していた時はまだ手探りの状態で作成していたので、今見ると何でこんな書き方しているの?という部分も結構あります。特にUE4C++とBPの連結部分が曖昧な所がありましたし。その辺も後で直していきます。

今週は実装部は作成しませんが、仮に作成すると以下に示した感じになると思います。

f:id:kazuhironagai77:20210620213757p:plain

Levelが上がったら「読みましたボタン」を表示します。次にそのボタンをクリックした時に発動するEventの内容を実装します。

そのEventでは、最初に以下に示したCombat UIのコメント欄のコメントを総て消します。

f:id:kazuhironagai77:20210620213819p:plain

そしてLevelUpした内容について書き込んでいきます。

セリフだけ先にDataTableに作成しておきます。

f:id:kazuhironagai77:20210620213840p:plain

これで

  • KUMOのレベルが上がりました。
  • KUMOのレベルは2になりました。
  • KUMOの最大HP3上がり103になりました。
  • KUMOの最大MP1上がり21になりました。
  • KUMOの攻撃力は1上がり51になりました。
  • KUMOの防御力は1上がり31になりました。
  • KUMOの運は1上がり2になりました。

のような表示がコメント欄に現れます。

後、魔法の習得についてのコメントを忘れていました。

f:id:kazuhironagai77:20210620213906p:plain

追加しました。

  • KUMOは魔法、炎()を覚えました。

と表示されるようになります。

あれ?RPGGameModeBPのTick()関数内に以下の関数が書かれていました。

f:id:kazuhironagai77:20210620213931p:plain

名前からして明らかにLevel upに関連した関数ですがどこで使用しているんでしょうか?

RPGGameModeBPのheader fileを見たらこの関数はFunction SpecifiersにBlueprint Implementable Eventを使用していました。

f:id:kazuhironagai77:20210620213954p:plain

のでBPを見ると以下の実装をしていました。

f:id:kazuhironagai77:20210620214015p:plain

「うーん。何しているんだ。この関数は?」と眺めていたら思い出しました。

武器や防具を装備した時にキャラの攻撃力や防御力が上昇します。しかしこれは実際にはキャラの攻撃力や防御力が上昇した訳ではなくて武器や防具を外したら元に戻ってしまいます。

しかしUE4C++に作成したキャラクターの属性を管理するクラスであるGameCharacterクラスの変数にはキャラの武器や防具込みの攻撃力と防御力を管理する変数しかなく

f:id:kazuhironagai77:20210620214034p:plain

Levelが上がった後の基礎攻撃力などを計算するのが大変面倒になる場合がありました。

ので別に武器や防具を外した状態の攻撃力、防御力を示す変数をBPでCharacterの3Dなど管理しているThirdPersonCharacterクラスに作成したんでした。

この辺も後でスッキリ整理したいです。

ただし今回のLevel upした後のセリフの追加には関係ないので今回はそのままにしておきます。

もう時間が無くなってしまったので今週はここまでにします。

5.3 PickUpItemクラスにItemを追加

来週やります。

5.4 Monsterがアイテムを落とすようにします

来週やります。

5.5 Warp Passの作成

来週やります。

5.6 Landscape4にgood skyを追加

来週やります。

6. まとめと感想

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

  • Niagaraの勉強:Ribbon RenderingとはどんなRenderingなのか?
  • Cascadeの勉強:CascadeにおけるRibbon Renderingについて
  • Monster Zoneのバグの直し
  • ゲーム全体の直しの内、Start画面の直し、Level Upした時の表示されるコメントの直しの準備

を行いました。

7. 参照(Reference

[1] Hey, J. (n.d.). Basics of Ribbons in UE4 by Jordan Hey. ArtStation. Retrieved June 20, 2021, from https://www.artstation.com/kanoba/blog/p3yX/basics-of-ribbons-in-ue4

[2] Epic Games. (n.d.-a). Particle Spawn Group. Unreal Engine Documentation. Retrieved June 20, 2021, from https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/ParticleSpawn/

[3] Matusik, W. (n.d.). Bézier Curves and Splines. MIT CSAIL. Retrieved June 20, 2021, from https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/lecture-notes/MIT6_837F12_Lec01.pdf

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

[5] Epic Games. (n.d.-b). Working with UV Channels. Unreal Engine Documentation. Retrieved June 20, 2021, from https://docs.unrealengine.com/4.26/en-US/WorkingWithContent/Types/StaticMeshes/HowTo/UVChannels/