<前文>
2021-06-27のブログの前文でɑの音がアーに聞こえる単語とオーに聞こえる単語があると話しました。
私にはどうしてもこの音が同じ音には聞こえません。しかし同じ事を言っている人は一人も見つかりません。これはノイローゼになってしまったのかなとも思いましたが、確認する方法を思い付ました。
それは唇の形を見る事です。
アメリカ英語のɑの音は以下のVowel Chart [1]によると
右下の唇を丸めない音です。ɑの音は唇を丸めて発音する事でɒの音(いわゆるオーの音)に変化します。
Vowel Chart [1]には一般的なアメリカ英語のVowel Chartも載っていてそれによると
唇を丸めて発音するɑの音、つまりɒの音はありません。
更にCot–caught mergerが起こるとこのɑの音とɔの音がɑの音になってɔの音も無くなります。つまりオの音が無くなる訳です。上の図だと元から消えていますね。ただし二重母音(diphthong)のoʊは有りますのでオウの音はあります。上の図のOはoʊを表しているのかそれとも単独でoの音があるとしているのかちょっと分かりません。
で、思い付いたんですが、この「アメリカ英語にはɒの音がない」と言うのが怪しいのではないのかと。
だったらɑの音の単語を発音している時の唇を見れば区別がつくんじゃないのか。と閃きました。
そこでyouglish [2]の出番ですよ。
October (ɑkˈtoʊbər)で調べて見ました。
このɑの音、私にはオにしか聞こえません。
0.5倍速にしてOの発音が聞こえた時に一時停止して唇の形が見えるものを切り抜きました。
はい。唇が完全に丸くなっています。
やっぱり、と思ったんですが、ˈtoʊの発音の口の形をしている可能性もあります。一時停止するのが遅すぎたらˈtoʊの口になってしまうからです。
後、10人くらいのOctoberの発音を聞いたのですが、その内の2人はアクト―バーとはっきりとアと発音している人がいました。残りの人は少なくとも私にはオクト―バーと聞こえました。
Octoberはɑの音の直ぐ後にtoʊの発音が続くのでもっと調べやすい単語に変更します。
Sorry (ˈsɑri)にしました。これならスの音が聞こえた瞬間に一時停止すれば唇の形をはっきり見る事が出来ます。
うーん。Octoberほどはっきりしていませんが、やや丸くなっている気はします。
Fatherのɑの音は少なくとも私にはアにしか聞こえませんので比較対象としてFather(ˈfɑðər)の唇の形を見てみました。
まったく唇を丸めていませんね。
この結果だけ見ると、やっぱりアメリカ英語のɑの音は単語によってはかなりɒの音に近づいていると考えられます。と言うかやっぱりアメリカ英語にもɒの音はあるんじゃないでしょうか。
それでは今週の勉強を始めます。
<本文>
1.今週の予定
今週は以下の事をやっていきます。
全部は無理かもしれませんがやれるだけやっていきます
2. Niagaraの勉強の続き
公式のDocumentであるNiagara Visual Effects
Niagara Visual Effects | Unreal Engine Documentation [3]を見ると
GuideにCreate a Beam Effect in NiagaraがRibbonとは別にありました。
今週はこれを勉強します。もしこのDocumentが短くて何も新しく勉強する所がない場合、Smokeのdocumentでもやる事にします。
2.1 Create a Beam Effect in Niagara [4]を勉強する
注目すべき点としては
- CascadeのBeamにおけるSheetやInterpolation Pointのパラメーターがどうやって実装されているか。
- Niagara SystemのBeamはRibbon Renderingを使用します。しかし実際のBeam Renderingはどのように行われているのでしょうか?CascadeのBeamと同じなのでしょうか?それともRibbon と同じなのでしょうか?
- CascadeのBeamは起点となる最初の面は常にカメラ側を向いています。Niagara のBeamはどうなんでしょうか?
- CascadeのBeamは起点が常に画面から見て前になるようにRenderingされます。これってバグだと思っています。NiagaraのBeamはどうなんでしょうか?
などがあります。これらの点に注意して勉強していきます。
このdocumentではStatic BeamをTemplateに使用していますね。
この時点でもう50%くらい完成していますよね。
<Change Renderer Settings>
Ribbon Renderer Moduleのparameterを弄っていきます。
Curve Tensionは何を管理するParameterなんでしょうか?
と書かれています。
0の時です。
1の時です。
Beamが細くなっていると言えばなっていますね。でも良く分かりませんね。
Beam Width Moduleがあります。
これのScale Curveの値を50に変更して
同じ事を試してみます。
0の時です。
1の時です。
変わっていない?
もしかすると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 についてです。
Loop DurationにRandom Range Floatをセットして
0.1と0.2をそれぞれの値にセットします。
Beamが点滅しなくなりました。
Loop Durationは次のLoopが始まるまでの期限を指定しているはずです。一応確認します。
Loop Durationを5秒にセットしました。
すると0秒と5秒の時にBeamが現れます。
Beamは3秒間表示され消えます。
今度はLoop Durationを4秒にセットしました。
今度は0、4、8秒の時にBeamが現れるようになりました。
はい。合ってますね。
Documentの設定だと0.1~0.2の間にDurationがセットされるので
Beamの寿命が3秒にセットされている今の状態だとずっとBeamが表示される訳です。
次にEmitter Update GroupのBeam Emitter Setup ModuleのParameter、
Absolute Beam Endにチェックを入れます。
このParameterの機能があんまりはっきりと説明されていません。
Documentには以下の様に説明してありました。
Beam RenderingでBeamの起点と終点を指定するのは重要です。それを担当するのがこのBeam Emitter Setup Moduleみたいです。
それぞれのParameterを見ると以下の物があります。
Beam StartはBeamの起点を指定しています。Simulation Positionがセットされています。Simulation Positionは
と書かれていますが、簡単に言えばLevel上に配置されたNiagara systemの位置から開始すると言う事でしょう。
そしてDocumentの説明では、
とありますが、要するに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していません。
想像通りのEffectが作成されています。
Absolute Beam EndにCheckします。
やっぱりWorld Coordinateにおける200、0,0を指しています。
Documentの設定はオカシイですね。
次にBeamにcurveを追加します。
まずBeam Emitter Setup ModuleのUse Beam Tangentsにcheckを入れます。
すると以下のParameterが現れます。
Beam Start Tangentの設定をMultiply Vector by Floatにします。
すると以下の様な表示に変わりました。
これはもうCascadeのTangentの設定と全く同じですね。
Document通りの値を追加します。
以下のようになりました。
うん。中々きれいなCurveだなと思って一応Level上でも確認したら
Level上ではとんでもないCurveになっていました。
Scaleを0.5と1から0.1に変更しました。
まあまあ、オカシクないCurveになりました。
まあ、この辺の値はCascadeと同じでしょうから後で自分で調節します。
後、この節の一番最初で述べたParameterであるCurve Tension
の機能はTangentを指定する事じゃなかったですね。このParameterの機能も後で調べます。
最後にSpawn Burst Instantaneous moduleのSpawn Countを35にセットします。
このParameterについては前に良く調べました。2021-06-20のブログにまとめてあります。
簡単に説明するとSpawn Countの数が少ないとBeamが部分的にしかRenderingされません。
<Edit the Particle Spawn Group Settings>
まず最初にInitialize Particle Moduleの
Life Timeを0.2に変更します。
Life Time、こんな所にいたのか。これでBeamが点滅するはずです。
Screenshotなので点滅しているのか、これからは分かりませんが実際は点滅しています。
その後で、Documentでは以下に示した様にSpawn Beam Moduleについての説明があります。
これの事ですね。
Parameterも一個しかなくて良く分からないModuleです。
Documentの説明を信じればBeamを作成したい時は、このModuleを追加する必要があります。しかし単に追加すれば良いので何もParameterを弄る必要はないそうです。
CursorをSpawn Beamに重ねたら以下の説明が表示されました。
結構重要な内容が書かれています。
- Particleを起点と終点の間の線状に配置します。
- 古典的なBeamをRibbon Rendererで作成するために使用されます。
- これで作成されたBeam は起点と終点をフレーム毎に計算する必要はありません。
マジですか。BeamってParticleを起点と終点の間に線上に配置していたんですね。それでSpawn Burst Instantaneous moduleのSpawn Countの数が少ないと変なImageになったんですね。
今度は、Beam Width Moduleです。
Curveの0.5の位置が1の値になるように調節します。
0と1の傾きも調節しました。
更にScale Curveは5に変更しました。
このModuleはBeamの太さを管理しているModuleです。
<Edit the Particle Update Group Settings>
はい。最後のGroupに来ました。
まず、Color ModuleのColorを変更してBeamの色を変えます。
やっぱり光らせるために1以上の値をセットしましたね。
実際光っています。
今度はBeamをジグザグにするためにJitter Position Moduleを追加します。
追加しただけで以下の様な感じになりました。
実際のLevel上では以下に示した様になっています。
うん。このModuleは何をしているんでしょうか?
取りあえず先をやってから考えます。
次はUpdate Beam ModuleをJitter Position Moduleの前に追加します。
またJitter Position Moduleに戻ってJitter AmountとJitter Delayに以下の値をセットします。
これで終です。
以下の様になりました。
実際のLevel内ではこんな感じです。
この節の最初で以下の疑問を書きましたがこれらの答えはまだ分かりません。
更にこのDocumentをやっている中で、新たな疑問も出て来ました。
- Ribbon Renderer ModuleのCurve Tensionはどんな機能なのか?
- Jitter Position Moduleは実際は何をしているの?
- 何でUpdate Beam ModuleをJitter Position Moduleの前にセットしないといけないのか?
などです。これらの疑問は次の節で検討します。
2.2 Niagara SystemにおけるBeam Renderingの疑問と検証
<CascadeのBeamにおけるSheetやInterpolation Pointのパラメーターがどうやって実装されているか。>
まずそのものズバリSheetやInterpolation PointというParameterが無いか調べました。
なかったです。
それで考えて見ましたがSheetは兎も角Interpolation PointがParameterとしてあるならBeamの起点と終点のTangent を指定した時点でCurveになる訳はないです。その後でInterpolation Pointを指定して初めてCurveになります。と言う事は少なくともInterpolation PointというParameterはNiagara SystemのBeamには無いのかもしれません。
SheetはどっかのModuleにはありそうな気がしています。が見つかりませんでした。
<Niagara SystemのBeamはRibbon Renderingを使用します。しかし実際のBeam Renderingはどのように行われているのでしょうか?CascadeのBeamと同じなのでしょうか?それともRibbon と同じなのでしょうか?>
これはSmile ちゃんを使用して確認してみましょう。
起点と終点にある面が常にカメラ側を向いています。この点は起点だけカメラを向いているCascadeとは違いますね。
後Sheetが一枚だけ作成されています。Sheetの数は増やせそうですね。
更にWire Frameを見ると以下のようになっています。
Cascadeの場合を以下に示します。
一見違うように見えますが、終点を含む面が常にカメラ側を向くとなると同じになると思います。
後、Spawn Burst InstantaneousのSpawn Countの値によってRenderingがどう変わるのかを調べます。
0、1の時です。
何も現れません。
2の時です。長方形のイメージが現れました。
Wire Frameを見ると以下のようになっています。
成程、辺が2個ある長方形になっています。
3の時です。
うん。これはCascadeのBeamにおけるInterpolation Pointと同じですね。もっと試してみましょう。
4の時です。
これは?何で3つのSmileが出来ているんでしょうか?
Wire Frameの方は想像通りですね。
今度は5つです。
また変なMaterialの貼り方をしています。
辺の数は5個でSpawn Burst InstantaneousのSpawn Countの値はBeamの辺の数を表しているのは間違いないですね。
後は、この変なMaterialの貼り方について調べるだけですね。
6~10にしました。
25です。Smileがやっと一個になりました。
Wire Frameを見ても綺麗な扇型になりました。
はい。
結論をまとめます。
- NiagaraのBeamのRenderingは基本的にはCascadeのBeamのRenderingと同じです。ただしCascadeのBeamは起点の面だけが常にカメラに向かっているのに対してNiagaraのBeamは起点の面と終点の面の両方が常にカメラ側を向いています。
- NiagaraのBeam ではSpawn Burst InstantaneousのSpawn Countの値はBeamの辺の数を表しています。CascadeにおけるInterpolation Pointの機能と同じです。
- NiagaraのBeamではMaterialは3つ貼られます。Spawn Burst InstantaneousのSpawn Countの値が増える毎に真ん中のMaterialのサイズが大きくなって最終的には一個のMaterialがBeam全体をカバーするようになります。
以上です。
<CascadeのBeamは起点となる最初の面は常にカメラ側を向いています。Niagara のBeamはどうなんでしょうか?>
この質問は既に調べてしまいましたね。NiagaraのBeamは起点の面と終点の面の両方が常にカメラ側を向いています。
<CascadeのBeamは起点が常に画面から見て前になるようにRenderingされます。これってバグだと思っています。NiagaraのBeamはどうなんでしょうか?>
自分で質問を作成しておいてこの質問の内容すっかり忘れていました。
良い質問過ぎます。質問の内容を読んでいて、こんな質問考えるヤツは天才だと思いました。それで良く考えたらこの質問考えたのは私でした。
冗談はさておき調べて見ましょう。
起点が手前で、終点が奥になります。
この場合は手前の起点が前にRenderingされています。
終点が手前で起点が奥になります。
はい。CascadeのBeamとは違い、手前の終点の方が奥の起点より前でRenderingされています。
この結果から考えるとCascadeのBeamのRenderingの常に手前が前にRenderingされるのはバグですね。
<Ribbon Renderer ModuleのCurve Tensionはどんな機能なのか?>
と書かれていますが、数値を幾ら弄っても実際のBeamのCurveの形状に変化は見られません。
現時点では影響のないParameterなのではないかと思っています。
<Jitter Position Moduleは実際は何をしているの?>
Jitter Position Moduleがoffの時です。
起点を含む面がカメラを向いているのが分かります。
Jitter Position ModuleがOnの時です。
起点を含む面がカメラを向いていません。
Jitter Position ModuleのJitter Amountの値を変えてみます。
0の場合です。
Jitter Position Moduleをoffにした場合と同じです。
1の場合です。
起点を含む辺が僅かに歪んでいます。
3の場合です。
起点を含む辺がかなり歪んでいます。
Wire Frameで見るともっと良く分かります。
これがJitter Position Moduleがしている事のようです。
<何でUpdate Beam ModuleをJitter Position Moduleの前にセットしないといけないのか?>
Update Beam ModuleをOffにしてみました。
起点を含む面が元の位置に戻らず、どんどん最初の位置がずれて行っています。つまりUpdate Beam Moduleは起点の面をNiagara Systemが配置された点に戻す役割を果たしていたんでした。
Update Beam ModuleのNiagara Module Scriptを開くと以下の様なノードがOutput Moduleに繋がっています。
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]ないで説明がありました。
UE4C++のTutorialとはC++ 3rd Person Battery Collector Power Up Game |v4.9| Unreal Engine [6]のTutorialの事です。
この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の具体的な使用方法を説明している箇所を探します。
多分これでしょう。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は以下の様に説明されています。
ので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に変更します。
そしてBP内からそのParticle SystemをSpawn Emitter Attached ノードを使用して呼び出します。
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のサンプルを見てみます。
この雲みたいやつにしますか。
というのはNiagaraで次に勉強する予定に入れているのが公式のDocumentのRecreate the Starter Content Smoke Effect in Niagara [9] だからです。
比較対照するためにCascadeでも似たようなEffectを勉強しておいた方が得な気がしています。
3.3 Particle Shadow Castingの勉強
Particleの影の投影について?
あれ。Smokeみたいなやつの作成じゃなかったのか?ちょっとParticle Systemを開いてみます。
Emitterも一個しかなくて思ったより簡単かもしれません。
実際に配置してみました。
あれ?Content Exampleではあった影が無くなっています。この雲みたいなのを作成するのが目的なので影の事は後で考えます。
Wireframeで見ると一目瞭然ですね。
Particleを大量に発生させてそれに常にカメラに向いている面を貼り付けています。その面に指定したMaterialを貼り付けています。
普通のSpriteです。
Emitterで確認しても特別なData Typeは使用してません。
Moduleを見ると見た事ないのは一個だけあります。
SubImage Index Moduleだそうです。
公式のDocumentのSubUV Modules [10] によると、
あ、MaterialのTextureに良く以下ののようなImageを沢山並べたヤツを使用しているのがあります。
それをEffectで使用するためのModuleのようですね。そう言えばこのImageがいっぱいあるTextureから作成したMaterialの使用の仕方が全然知りませんでした。この辺も勉強する必要がありますね。
3.4 M_cloud_litの勉強
SubUVを使用したMaterialの使用の仕方を勉強する前にParticle Shadow Castingで使用されているmaterialであるM_cloud_litについて調べて見ます。
まずMaterialのResultノードから見てみます。
この出力の種類はBlend ModeをTranslucentにセットしていますね。
Base Colorがあって、Emissive Colorも出力していますね。
それぞれの値がどのように計算されているのかを見てみます。
Base Colorです。
8*8のImageのまま出力しているんですね。ひょっとしてすべてそうなんでしょうか?
そうでした。
するとこのタイプのMaterialを使用する特別な方法がCascade側にあると言う事ですね。
それだけ分かれば十分です。Particle Shadow Castingの勉強に戻ります。
3.4 Particle Shadow Castingの勉強 Part 2
色々調べたんですがSubUVのTutorialはNiagaraが主流になってしまってCascadeはほとんど見つかりませんでした。
のでそれぞれのModuleにあるSubUV関連のParameterを見ていきます。
まずRequired ModuleにあるSubUV関連のParameterです。
良く分かりませんね。
何となく分かるのはSub Image HorizontalとSub Image Verticalが8にセットされている事が、MaterialのImageが8x8だった事に一致している事だけです。
うーん。
公式のDocumentであるDefault Required and Spawn Modules [11]を見てみますか。
Required ModuleのSub UVの所です。
アニメーション?
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上に配置したらその影が出来ないんです。
まずLightの設定を変える必要があるそうです。以下に示したCast Translucent Shadowsにチェックを入れます。
そう言えばContent ExampleでもなぜかParticle Shadow CastingだけLightが右上から照射されていました。
はい。チェックされていました。
因みにこのSpot Lightに重なる様にS_EV_SimpleLightBeam_03と言うStatic MeshがSpot lightに重なる様に配置されていて最初、これをSpot Lightと勘違いしていました。
それでずっとCast Translucent ShadowsなんてParameterはないと思っていました。
後、試しにSpot LightのCast Translucent Shadowsのチェックを外したら雲の影も消えました。
次です。
今度はLevel上に配置したParticle SystemのParameterを変更します。
LightingのCast Shadowにチェックを入れます。
入れる前です。
入れました。
影が突然現れました。
でも何か影が濃すぎる気がします。
最後の変更だそうです。MaterialのOpacityの計算にDepth Fadeノードを使用していると影が出なくなるそうです。
これを外します。
Particle Shadow Castingに使用されているMaterialであるM_cloud_litではOpacityの計算にDepth Fadeノードは使用されていませんでした。
今度は雲の影をもっとスムーズにしていきます。
M_cloud_litのTranslucency Self ShadowingのShadow Density Scaleの値を変化させます。
0.1にして見ました。
影が薄くなってますね。
1にして見ました。
濃くなりました。
Tutorialでは0.5位が見た目が良い。と言っていましたので0.5にしてみます。
うーん。正直、雲の形が変わっているので影か薄くなっているのかどうか分かりません。
次は影のResolutionを変えるそうです。
今度はParticle Systemから変えます。
Boundsをクリックして境界線を表示させます。
次にBoundsのSet Fixed Boundsを選択します。
Emitterの選択を外してBoundsを表示させます。
この中のMinとMaxの値を弄る事で雲のサイズが変化するそうです。
後で直すのが大変そうなのでこの値は弄るのは止めてTutorialだけ見る事にします。
Tutorialでは以下のような影になりました。
影が細部まで綺麗に写っている気がします。
以上でした。
<今週の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変数を作成します。
勝利のポーズを取る時にTrueになる変数です。
武器を装備していない場合です。
弓と矢を装備している時の場合です。
それ以外の武器を装備している時です。
4.2 RPG Game Mode BPのコードの改良
以下の部分を直していきます。
以下の様になりました。
実際に外した部分です。
最後にMy ThirdPerson Anim BPのVictory変数をfalseにします。
勿論、Set Anim Instance Classは要らないので外します。
これで完成した。と思ったら思い出しました。
前のこれと同じ物を作成した事をです。
たしか変なアニメーションになったんで仕方なくPlay Animation ノードに変更したんでした。
取りあえず結果を見てみます。
4.3 テスト
テストします。
武器なしの時です。
普通に勝利のポーズを取っています。どこもおかしくないです。
武器を装備した時です。
これもおかしくないですね。
弓を装備した時です。
弓と手が離れていますが、それは元からなので今回は無視しておきます。
勝利のAnimationには何の問題もありません。
あまりに簡単に終わってしまったので拍子抜けですが出来ました。
後、多分ですが前回Play animation ノードを外した時に変なアニメーションになった理由はMy ThirdPerson Anim BPのAnim Graphの以下の部分
でLoop Animationにチェックしたままにしていたせいだと思います。
兎に角出来ました。
Preparation and Implementation Programmingはやっぱりすごい効果があります。全然疲れないし、時間も前の何分の1かで済んでしまいます。今までの越えなければならないハードルの高さが10位だとすると2か3位になっています。
来週は2倍の量がこなせそうですので、先週の2倍分、調査、検討する事にします。
5.戦闘後にアイテムが手に入る場合
5.1 色々な検討
戦闘後にアイテムが手に入る場合と入らない場合はどのような割合になるのでしょうか?
また、手に入るアイテムの種類はどの様に配分すべきなのでしょうか?
戦闘後にアイテムが手に入る確率は20%ぐらいが丁度良いと思います。それは最初の10回の戦闘はPlayerの操作するキャラのレベルが戦闘後、毎回上がるからです。その間に2回程度アイテムが手に入る事が分かればPlayerもどのくらいの確率でアイテムが手に入るのかが推測出来き、それ以降の戦闘に対しての準備や対策が建てられるからです。
アイテムの種類については2021-06-13のblogで検討した内容で良いと思います。
ただし流石にこの期に及んで50%の確率でしかアイテムが貰えないのは厳しすぎます。一個は必ず貰えるようにしましょう。
となるとまず作成する必要があるのは、20%の確率で元の世界に戻らないようにする仕組みです。
そして石像と会話した後で元の世界に戻れるようにします。
段々、何を制作しないといけないのか見えて来ました。
まとめます。
- 20%の確率で元の世界に戻らないようにする仕組み
- 石像との会話
- 会話の後に元の世界に戻る仕組み
です。
5.2 「20%の確率で元の世界に戻らないようにする仕組み」の検討
まず戦闘に勝利した後、RPG Game Mode BP内でどんなノードが実行されるのかを確認します。
前節のMy Third Person Anim BP内のVictory変数がFalseにセットされた後から見て行きます。
カメラの位置を元に戻しています。
Down Victory Music変数をTureに変更しました。
Down Victory Music変数はEvent Tickで使用されていました。
TrueになるとBGMの大きさが0になるまで少しずつ下げていきます。
次のノードはHad Read Fight is Overノードです。
戦闘に勝利した後だけでなく戦闘から逃げ出した時もこのノードに繋がっています。
戦闘から逃げ出した後で褒美が貰えたらオカシイです。このノードの後に石像と話す実装をする場合は戦闘に勝利した場合と戦闘から逃げた場合の別々な実装を作る必要がありますね。
Had Read Fight Is Over関数についてです。
UE4C++の方の関数でした。FightISOverIsRead変数にTureをセットしています。
FightISOverIsRead変数がTureになるとTick()関数の以下の部分が実行されるようになります。
Pointerなどの後処理を行っているだけですね。特にBP側に指令を発したりはしていませんね。
次は「読みました」ボタンにBindしたEventを全て外しています。
この「読みました」ボタンの仕組みについては散々勉強したので今回はパスします。
その次のノードは倒したモンスターをRPGGameInstanceBP内のデータから消去しています。
ここでMonsterの消滅を実行していたんですね。
一秒待っています。
理由は忘れました。
何か重大な理由があったはずです。ここで待たないと何か不都合な事が起きたのは覚えています。
はい。最後に元のLevelにワープしています。
このOpen Levelノードのすぐ前で「20%の確率で元の世界に戻らないようにする仕組み」を作成出来ると一番簡単です。
しかし戦闘に勝利した場合と戦闘から逃げ出した場合の違いをどうやって区別しましょうか?
良い変数を見つけました。
この変数Victory、Combat Over State のEnumでPHASE Victory, PHASE Game Over, PHASE Escapeの種類があります。そして今の時点ではVictoryにセットされたままのはずです。この変数を使えば戦闘に勝利した場合と戦闘から逃げ出した場合を分けれるはずです。
ちょっとだけ試してみます。
自由に歩けるようになりました。
骸骨は消した方が良いです。回っている骸骨が3D酔いを引き起こします。
5.3「20%の確率で元の世界に戻らないようにする仕組み」の手順
20%の確率で当たる実装はどうとでも作成できるので来週考えます。その20%の確率に当たった場合、まずWidgetで特別な褒美が石像からもらえる事を連絡します。
そのWidgetでは
- 褒美としてItemが貰える事
- Itemをもらうためには石像に話しかける必要がある事
- 話しかける石像によってもらえるItemが違う事
を説明します。
Widgetは今、作成してしまいましょう。
イラストはこんな感じです。
Widgetのデザインはこんな感じです。
「話しかける石像によってもらえるItemが違う事」に関しては、実際に石像に話しかけて見れば良いと思い消しました。
次に「回っている骸骨」を消します。
「回っている骸骨」はBackgroundSkullBPと言う名前のBPクラスから生成されたInstanceでLevel、Battle Fieldに静的に配置されています。
この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を見て確認しましょう。
Viewportはこんな感じでした。
Boxの位置は変える必要がありますね。あるいはMeshを完全に外してしますのも手かもしれません。
Exclamation markを光らせる部分の実装です。
正直、何でこんな複雑にしたのか覚えていません。Boxに侵入したら光るだけでは駄目なんでしょうか?
思い出しました。
確か全部のNPCのExclamation Markが光ってしまうので上記のようなコードにしたんでした。
これは実装する時にもう一回検討しましょう。Begin Overlap関数に実装するだけで上記の問題は解決しそうです。
Begin Overlap関数を見て行きます。
cast to Third Person Characterノードに繋がっています。
これは侵入したActorがPlayer が操作するキャラであるかどうかの確認をここで行っているでした。
次のノードに行きます。
NPC_Person BP クラスの変数であるVillage Nameの値をThird Person Characterクラスの変数であるVillage Nameにセットしています。
NPC_Person BP クラスのVillage NameはEnumで村の名前を保持しています。Instance Editableなのでlevel内に静的に配置したそれぞれのInstanceに別の値をセットする事が出来ます。
村人との会話の区別に使用しているはずです。
次はRPGGameModeBPを呼び出して変数化していました。
これは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にセットします。
因みにOccupationとMy Place For EventsはEnumで以下の要素で構成されています。
以上でした。
これだけでは何をやっているのか不明です。のでこのExclamation markが見える時にEボタンを押した場合についての検討を次に行います。
まずThird Person Character BPクラスを見てみます。
Third Person Character BPクラスにはEvent Do Somethingがあります。
このEventはEボタンを押すと発動します。
キャラクターを操作するためのキーボードやマウスの操作についての管理は一括してThird Person Characterが担当すると決めています。
Playerが操作するキャラがNPCに話しかける場合もThird Person Character BP内で管理しています。
このやり方は以下のノードのようなスパゲッティコードを生み出していますが「キャラクターを操作するためのキーボードやマウスの操作についての管理は一括してThird Person Characterが担当する」と言う原則は守っているので一長一短がある実装方法です。
NPCの場合はどんな実装がされているのかを見てみます。
NPCは沢山の種類があるのでその代表としてMy Place For Events がPE_TalkingNPC_Oldmanの場合を見てみます。
Widget、Oldman Welcomeを開きます。
こんな絵が出て来ました。
思い出しました。NPCの作成方法は結構大掛かりで大変でした。
このwidgetの特徴はNPCのセリフをそのセリフを管理しているData Tableから呼び出した表示する事です。更にそのセリフを管理しているData TableはそのNPCのセリフに対するPlayerの回答も用意されていて結構複雑な作りになっています。
NPCとの対話用のData Tableは以下の様な作りになっています。
流石にこの辺の作りは覚えています。アドベンチャーゲーム方式でセリフを管理しています。
ConversationにNPCのセリフが書かれています。
Answer Choice(何故かData TableにはAnser Choiceになっていますね。)にはNPCのセリフに対してのPlayerの回答が書かれています。その回答を選択した場合はJump To Commentに書かれた番号のCommentに飛びます。
このData Tableを正しく読めるような実装をOldman Welcomeウィジェット内で実装しているはずです。
まずCustom EventであるConversation Startが呼ばれています。
Village Nameによって分岐しています。
これはそれぞれの村でNPCのData Tableは別なので当然です。
最初の村の場合を見てみます。
Get Data Table Row Names関数が使用されていました。この関数は最初の村の老人用のセリフを管理したData Table、FistVillage_Oldmanを読み込んでそのData TableのRow Nameを返します。
FistVillage_OldmanのRow Nameは以下のものです。
次のノードです。Get Data Table Row()関数が使用されています。
Get Data Table Row()関数ではComment Numberで指定された値のFistVillage_OldmanのRow NameがGet Data Table Row()関数にパスされそのRow Nameの担当する列がまるまる返されてきます。
Comment Numberで指定された値は、0なので
が返されます。そしてRow Nameが担当している列のデータ(以下の物)が返されます。
Conversationにある値はComment変数にセットされます。
Comment変数の値は以下のTextBlockにバインドした
Get Text Block Oldman Dialog Text 0 関数によって直ぐにComment欄に表示されます。
その次のノードであるAnswer CommentにAnswer Choiceにある全ての要素が記録されます。
そしてその配列は次のFor Each Loopに渡されます。
ここで、それぞれの要素毎にAnswer Button ウィジェットが作成されます。
Answer Button ウィジェットはただのボタンのWidgetで
ボタン内のTextには先程、Answer Choice からAnswer Commentにパスされた要素の内のPlayerの回答部分が表示されます。
そのための実装部分を以下に示します。
更にこのボタンがクリックされた場合は、以下の実装部分によりOldman Welcome ウィジェットのComment Numberが指定されている番号に変更します。
その後、Clear Children関数で
以下の赤丸で囲った部分に表示されているボタンを全て消去し、
Oldman Welcome ウィジェットのCustom EventであるConversation Startを呼び出します。
この後は、上記のOldman Welcome ウィジェットのCustom EventであるConversation Startに戻って同じ事を繰り返していきます。
大変でしたが一通り復習出来ました。
5.6「石像との会話」の作成方法について Part 2
「石像との会話」では前節で復習したNPCとの会話のような複雑な対話システムは必要ありません。しかしItemを修得する必要があります。
ので先週作成したPick Up Itemクラスでどのように収得したItemを道具袋に追加しているのかを確認します。
ただし流石に先週作成したものの全てのノードを見て行くのは無駄なので実際にItemを追加する箇所だけ復習します。
それはPick Up Item ウィジェット内の以下の実装部です。
最初のノードでそのItemが本当に存在しているItemかどうかを確認しています。
次のADDノードでRPG Game Instanceクラスの変数ItemsにそのItemを追加しています。これで修得したItemが道具袋に収納された状態になりました。
何かPCの調子がオカシイので、突然ですが今週の作業はここまでとします。
6.まとめと感想
今週は以下の事についてやりました。
- Niagara Systemの勉強
- Cascade Systemの勉強
- BPでBeam EmitterのTargetを指定する方法について
- 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