<前文>
<三国志の動画について>
年末から新年にかけて三国志や春秋戦国時代の本やBlogそして動画ばかり見てました。
大変面白かったです。
特にYouTubeの動画が、製作者のオリジナルな解釈や推測があってとても勉強になりました。
ところがですね。
三国志関連のYouTubeの動画って大抵ゆっくりボイスで編集されているんですが、そのせいですぐ収益はく奪されるわけです。それで動揺している動画が一緒に上げられているんです。それ見たらなんて言うか一気に冷めてしまいました。
視聴者は三国志関連の専門家の動画製作者だから、諸葛孔明じゃないけど当然そういう事態が起きる事位は想定して動画を制作していると期待して見てる訳です。だから対策も既にバッチリ準備してもう三国志に登場する軍師の様な対応を見せてくれると期待するじゃないですか。そしたら収益はく奪されてそれで動揺している動画が上げられている訳です。そういうのを見るととてもがっくりしてしまいます。
勿論、全員がそうと言う訳ではなくて適切な対策を準備していて、順調に収益のはく奪の取り消しを行った動画を上げている方もいましたが、全体的にはただただ動揺している動画を上げている人の方が多かったです。
昔、渡辺昇一氏が、自身の本を出版している出版社から自身を批判される本が出版された時、毅然として自分の本の版権を取り上げて別の出版社から本を出版する事を行いました。
渡辺昇一氏の本の内容は兎も角として、それがプロ根性だと思います。
そして三国志関連のYouTubeの動画の質はプロの作家の人と比べても全く劣っていないか、個人的な意見ですがもっと優れているでしょう。その動画の質に相応しいプロとしてのプライドを持って対応してほしかったです。
数年前の話ですが、トヨタの社長が呼ばれた事でも有名な米国の議会にGoogleのCEOであるSundar Pichai氏が呼ばれた時、議員から「YouTubeは人種差別主義者やネオナチなどのプロパガンダの発信源になっている。」と批判されると、彼はそういう事態になっている事は承知しています。しかしそう言う事を言う人達から発言の機会を取りあげる事は、言論の自由と言うもっと大きな問題を引き起こす事になります。だからGoogleとしてはそういう事を発信する人達の広告収益をはく奪する事でやっても利益が出ないと言う事を示すしか対応策がないんです。と答えていました。
勿論、その後で中国でお前は何をやってんねん。と議員から突っ込みを受けていましたが、それは別な話なのでここでは止めておきます。
その話を聞いて私はピンと来ました。GoogleからすればYouTubeの広告収益をはく奪するのは、人種差別主義者やネオナチなどのプロパガンダを発信する人達と同類と見なされない限り無いんです。
アメリカでは、賃金を支払わない事に対してとても厳しいです。少なくとも世間的には、賃金を支払わない事は奴隷を使用したと同じと見なされます。
そしてここが重要ですが、アメリカでは元々、人種差別主義者やネオナチなどの信望者は人間として扱われていません。私がいた州ではちょっとでも人を小突いたりしたらすぐに警察がやって来て逮捕されてしまうんですが、警官もその揉め事の原因が、人種差別やネオナチの信者との小競り合いと分かると、プイと見てみぬふりして事件そのものを揉み消してしまいます。
人種差別主義者やネオナチの信者ってのはそういう扱いを受けても仕方ないとみんなから思われています。
YouTubeの広告収益をはく奪されると言うのはそれと同レベルと見なされてしまっている訳です。もっと毅然と対応して欲しかったです。
<犬と馬とクジラ>
このBlogの前文に何回も書いていますが、アメリカ人にとって、犬と馬とクジラは特別な動物です。道端で誰かが猫を蹴飛ばしていても、アメリカ人は何とも思いませんが、犬だったら発狂して助けにきます。この前、アメリカの女子高生がペットの犬を助けるためにクマに素手で向かっていった動画がネット上に上げられていましたが、アメリカ人は犬を助けるためにはそれくらい必死になります。
正月にネット見てたら、馬刺しを食べてる日本人を見つけて発狂しているアメリカ人に発狂している日本人の集団がいました。
そのコメントで笑ったのが「アメリカ人は俺らの食べる物に何でもケチつける。豚や牛はどうなんだ。」と言う反論です。確かに一部のアメリカ人は日本というかアジア人のする事に対して何でも批判します。しかし馬や犬を家族のように大切に扱うのはアメリカ人全体の話です。規模がまるで違います。
彼等はこの問題の深刻さを全く理解していないんです。
私は、私の書いた前文の内容の価値を再確認しました。この前文を読んでいた人は、アメリカ人との関係において「犬と馬とクジラ」には特別、注意を払う事が出来き、無用なアメリカ人とのトラブルを避けれる訳です。
<学生ローンとAOC氏>
お正月ですので、私のBlogを読んでくれている読者に特別ボーナスな情報を書いておきます。
私は、バイデン政権が誕生した時、2年も経たない内に民主党に投票したアメリカ人の期待は幻滅に変わると予測しました。アメリカの民主党は投票者のために働く意思は全くなく、それは学生ローンの免除に対して全く手を付けない事で判明するとまで言いました。アメリカは日本とは、別な学歴社会で大卒でないと知的産業や管理職には絶対なれないようになっています。それで貧しい家庭に生まれた子が成功するためには大学に行くしかないんです。そのためにはほとんどの学生は学生ローンを組むしか無いんですが、そこに年金ファンドやらなんやらが入り込んで学生ローンを借りた人を生涯食い物にする仕組みが出来上がっています。だからお金持ちの家に生まれた子は貧しい家に生まれた子をずっとあごで使って暮らしていける訳です。
その連鎖を切らなかったら貧しい層はずっと貧しいままです。しかし私の予測通りバイデン政権はその問題にこの2年間の間全く手を付けませんでした。
そして支持率も徐々に低下していきました。
そしたらニューヨーク州の下院議員であるAOC氏がその事についてバシッと指摘していました。しかも言いっぷりも凄かったです。Wall Streetがリーマンショックか何かの時に負債を免除されたんですが、その負債の免除額の10分の1で学生ローンは免除出来ます。Wall streetを救う事がアメリカを救う事なら、学生ローンから学生を救う事はもっとアメリカを救う事になりますみたいな、Wall Streetからたっぷり寄付をもらっている民主党の大御所の議員に対しての皮肉を込めて痛快な言いっぷりでした。
彼女が今の主張を変えずに、議員として戦う事が出来るのなら女性初のアメリカ大統領になる可能性は十分にあると思われます。
今から彼女には特に注目しておくと後で得な事が起きるかもしれません。
それでは今週の勉強を始めます。
<本文>
1.今週の予定
今週もいつも通りやっていきます。
2.Niagara: CGHOW氏の何かを勉強する
と言っていました。
ので今週はCGHOW氏のDistort in all Directions in UE5 Material and Niagara [1] を勉強します。
2.1 Distort in all Directions in UE5 Material and Niagara [1] を勉強する
サラッとDistort in all Directions in UE5 Material and Niagara [1] を見ましたが特に自作した3dモデル何かを使用している部分もないのでこのTutorialを見ながら実装する事は可能そうです。CGHOW氏がTutorial内でも述べていましたが、このTutorialはほとんどMaterial内の設定方法がメインです。
ここのTutorialはどうやってTextureを中心から歪ませるかがメインです。そこに注目してやっていきます。
<Materialの作成>
歪ませるTextureですが、いつものSmileを使用します。ノイズですが付属のPerlin Noiseで代用します。
まずDistortionの基本形を以下に示します。
TexCoord[0]の値にNoiseを足してTextureを歪ませています。
結果です。
Noiseの値が大きすぎてTexCoord[0]の値がかき消されてしまっています。Noiseの値を以下の方法で小さくします。
単純ですが0.1を掛けてNoiseの値を小さくします。
結果です。
こんどはSmileが歪んでいるのが分かります。
もう少しだけ強く歪ませます。0.25を掛けました。
結果です。
この方法でTextureを歪ませるとTextureが左上に移動してしまいます。
さらに強く歪ませるために0.5を掛けます。
完全に左上に移動しました。
Textureは歪ませたいがTextureの位置はそのままにしたいです。今回のTutorialはそれを勉強します。
<<X軸、Y軸にDistort>>
その準備としてX軸方向のみ、Y軸方向のみにDistortする実装を作成します。
以下に実装を示します。
Noiseに掛ける値をAppend ノードを使用してXとYの値を別々に指定出来るようにしました。
結果です。
xの値を増大させました。
Textureは左方向に移動します。
今度はYの値のみを増大させました。
結果です。
Textureは上下に移動しています。
x軸の場合は左右に移動しました。
<<Textureの上半分は上に移動、下半分は下に移動するようにする>>
ParameterのY軸の値を変化した時にTextureの上半分は上に移動、下半分は下に移動するようにします。
そのために以下の実装をします。
結果です。
実装部分の検証です。
新しく追加したこの部分でTexCoord[0]の真ん中から下半分に0から0.5、上半分に0から-0.5の値が保持されました。
次にその値とYを掛けます。
今まではYの値はTexture内の全ての要素で同じ値でしたが、これで上半分はー、下半分は+になりました。しかも中心から離れる程、値も大きくなります。
Xにも同様の実装を追加します。
結果です。
XとYを一つにまとめます。
結果です。
Texture内のイラストが最初から画面一杯のため歪みが良く分からないです。
<<別なTextureで試してみる>>
別なイラストのTextureを用意しました。
あんまり綺麗には歪んでいませんね。
かなり微調整してみました。
うーん。芸術性を追求するためにはこれからかなり頑張る必要がありそうです。
<<歪みを円状に固定する>>
Tutorialに歪みを円状に固定する方法が載っていました。それを試します。
最初に実装部を記しておきます。
Radial Gradient Exponentialノードを使用しています。
こんな結果になります。
円形の外側は問答無用で真っ黒にしていますね。
結果です。
前のよりはかなり芸術性が高くなった気がします。
<Pannerを追加する>
まず最初は普通にPannerノードを追加します。
取りあえずx方向に移動させます。
こんな感じになりました。
X方向にだけ移動しています。
これをTextureの中心から外方向に移動するようにします。
実装方法です。
Vector to Radial ValueノードをPannerノードのCoordinateに接続しただけです。
Vector to Radial Valueノードは初めて使用するノードです。後でどんな機能のノードなのか調べます。
こんなになりました。
結果です。
かなり良いです。
水面に写った絵が波に揺られて歪んでいるような雰囲気があります。とても綺麗です。
Tutorialではこの後にTilingの効果をPannerに追加しているのですが、結果を見てもどう変化しているのかが分かりません。今回はそのまま使用して後で意味を検証します。
まず-0.5をTexCoord[0]に足します。
これって原点を移動しただけですよね。何でTilingに関係しているんでしょうか?
次にTexCoord[0]のTilingの値を2.0に変更します。
すると渦の中心が左上にずれました。
これを先程の
を使用して直す様です。
-1に変更しました。
すると
渦が中心に戻りました。
成程、このためにAddノードを追加したんですね。
段々、意味が分かって来ました。
ただNoiseのTexCoord[0]のTilingをする意味が分かりません。これすると何が変わるんでしょうか?
次にTexCoord[0]のUVのTiling値がどう変化しても対応出来るように以下のような実装をしました。
うーん。これじゃParameterのTilingの値はTexCoord[0]のUVのTiling値の変化と一致してないですよね。
一応、この結果を確認します。
やっぱりTilingの値を上げたら、歪みの中心が右上に移動しています。
以下の様に実装部を改良しました。
これでTilingのParameterの値を変化させても歪みの中心は常にTextureの中心になるはずです。
テストします。
Tiling=1の時です。
真ん中から歪んでいます。
Tiling=5の時です。
歪みの幅が狭くなりました。ただし歪みの中心はTextureの中心のままです。
これがNoiseのTilingの効果だったんです。
そりゃ動画を見ただけでは何をやっているのか分からん訳だわ。
Tutorialでもこの後で、間違いに気づいて直していました。
<<更に改良>>
更に改良しているんですが、これが何のためにやっているのか全く分かりません。今度もやっていく内に理解出来るかも知れないので取り敢えずやってみます。
Erodeの効果を追加するみたいです。
Erodeって侵食って意味です。どうやってこれを追加するんでしょうか?
もしかすると侵食以外の意味もあるのかもしれません。
以下の実装を追加しました。
このMultiplyノードの結果を以下のSubtractノードに繋いでいます。
結果です。
歪んだ部分の絵が消えています。かなり印象深くなりました。
正しErodeの値は0でこれだけ消えています。
マイナスにしたら消えている部分が戻るのか確認します。
Erode = -5000
完全ではないですが消えている部分はかなり戻っています。
Erodeの値を-100から3くらいで変化させてみました。
Imageが消えるのは別に波紋の間だからと言う訳ではなく、黒に近い色から消えていますね。
波紋に沿って絵が消えるのだともっと綺麗だったでしょうね。
まあ、Erodeの意味は分かりました。
2.2 Niagaraの作成
<Dynamic Parameterの追加>
それぞれのParameterをDynamic Parameterにまとめます。
TutorialでDistortノードから出てる2つのLineをCursorで引っ張って
Dynamic Parameterに移してるんですが、
地味にカッコイイですが、やり方が分かりません。
分かりました。
Ctr+ShiftでMouseの左ボタンをクリックするとLineを引っ張って移動出来ます。
DistortとErodeだけDynamic Parameterに追加しました。
Tilingはどうするんでしょうか?
取りあえずはTutorial通りにやっていきます。
<Niagaraの作成>
Fountainを追加したNiagara Systemを作成します。
Spriteを以下の様に発生させるようにFountain Emitterを変更します。
何時もやっている内容と同じなので詳細は省きます。
次にRender SectionのSprite Renderer Moduleの
のSprite Renderingに先程作成したMaterialをセットします。
こんな感じです。
Particle Update SectionにDynamic Material Parameter Moduleを追加します。
値は取りあえず以下の様にしました。
Distort にFloat from Curve を追加しました。
値は以下の様にセットしました。
こんな感じになりました。
Tutorialではこの後、Erodeの値にもFloat from Curveを追加しています。
そしてやっぱりその後で、Tiling ParameterをDynamic Parameterしているので全部やって更に微調整しました。
その結果です。
あんまり上手く動画が取れなかったんですがそれなりにスムーズな歪みになりました。
以上です。
3.Material : Content Exampleを見るの続き
当然ですが、今週は先週の続きのTutorial、Ben Cloward先生のDirection Masks - Shader Graph Basics - Episode 27 [2] をやります。
ぱっと見たら先週の
歪まないProjection方法については歪んでいる箇所をMaskして隠す方法しか教えていませんでした。Projection全体を歪ませない方法は次のTutorialで教えるそうです。
計算方法を見たらDot Productの部分だけ何をしているのか不明でしたが残りは大体は理解出来ました。
自分でやってみます。
3.1 Direction Masks - Shader Graph Basics - Episode 27 [2]を実装する
まず、結果を先に示します。
実装部分です。
赤で囲った部分が今回新しく追加された部分です。
結果です。
分かり易くするために先週の結果も示します。
Projectionで間延びしたTextureを黒塗りで隠しました。
これが今回、勉強する内容に成る訳です。
一応、復習のために先週やったTextureのProjectionを以下に示しておきます。
今週の実装部分もUnityを使用して解説されているのでUnityの解説を見ながら、それぞれのノードの役割を理解していきます。
<Directional Maskの実装>
Directional Maskを作成するのにまず必要なのは、Normal Vectorだそうです。Unityでは以下に示したVertex Normalを使用しています。
Tutorialによると別にVertex NormalじゃなくてPixel Normalでもどっちでも良いそうです。
UEでは以下のVertex Normal WSノードを使用しています。
公式のDocumentであるCoordinates Expressions [3] には以下の解説がありました。
特に新しい情報はないですね。
因みにUEのMaterialでもPixel Normalもあるのか調べたら以下のノードが見つかりました。
Vertex Normal WSノードと同じCoordinates Expressions [3]に以下の解説がありました。
こっちがVertex Normal WSノードのPreviewで上から見た状態です。
こっちはPixel Normal WSノードのPreviewです。
ほとんど同じですね。
Coordinates Expressions [3]のPixel Normal WSノードの所にVertex Normal WSノードとPixel Normal WSノードの違いを示す分かり易い例が載っていたので、それをもう少し分かり易くしてここに再現します。
Vertex Normal WSをBase Color、Normal MapをNormalに接続します。
結果です。
Normal Mapが無視されています。
今度はVertex Normal WSの代わりにPixel Normal WSをBase Colorに接続します。
結果です。
今度はNormal Mapの影響を受け色が変化しました。
Pixel Normal WSノードなので当然、Normal Mapの影響を計算した後のNormal Vectorの値が返ってくる訳です。
私はUnityは全く触った事はないですが、UnityのMaterialのVertexとFragmentを分けた構成は分かり易いように見えますね。
次にNormal VectorにあるNegativeの値を消すそうです。
Vector Normal WSノードのPreviewを回転させると以下に示したような黒く表示されている箇所があります。
この部分がNegative な値を示しています。
Cubeで見るともっと分かり易いです。
表から見るとこうですが、裏は
真っ黒です。
Abs ノードを使用します。
この辺はどうしてNegativeな値が駄目なのかの理由が分からないと何でAbsノードを使用する必要があるのかも分かりません。
ので結果だけ示しておきます。
Negativeな値だった箇所がPositiveになって全体的に白くなっていますね。
次は、値の変化が滑らか過ぎるのでContrastをつけるそうです。
Powerノードを使用して8乗します。
結果です。
Powerは以下に示した様にExpの値が大きくなるとカーブがきつくなります。
ので8乗したら白い部分がほとんど無くなったんでしょうね。
この結果をSplit Components ノードでマスクすると
既に特定の色(つまり特定の方向)以外をMaskする事が出来ます。
これで完成でも良いんですが、このTutorialでは更に、以下に示したPowerの結果の黒い部分を取る実装を追加しています。
そのやり方をここにまとめます。
まずPowerの結果と(1,1,1)でDot Productを計算します。
すると以下に示した様に、黒い所は黒く、それ以外の色の所は白くなります。
Dot Productの計算から考えるとRGBのそれぞれの値に(x+y+z)の計算結果を入れたんでしょうね。だからGray Scaleになったんでしょうね。
先程のPowerの結果をこのDot Productの結果で割ります。
すると以下の様にDot Productの黒い部分が消えます。
?
何で?
黒い部分の値がNegativeな事はないはずですから0なはずです。0で割ったら駄目でしょう。
まあ、完全な0ではないんでしょうな。(0.00001、0、0)みたいな値なんでしょう、それでその値と(1,1,1)のDot Productは0.00001だから
(0.00001/0.00001、0/0.00001、0/0.00001)=(1,0,0)
となって黒い部分が消えたんでしょうな。
これでDirection Masks - Shader Graph Basics - Episode 27 [2]は全部です。
今週はここまでとします。
4.NPCのAIを作成する
今週やりたい事を以下にまとめます。
- NPCのTickのTriggerの回数を少なくする
- NPCが止まった時にIdleするだけでなく別の動きを追加する
- NPCによっては歩き回らない。夜でも存在するなどの選択が出来る様にする。
- 全部のNPCを動的に生成する
出来るところまでやっていきます。
4.1 NPCのTickのTriggerの回数を少なくする
調べたらNPCじゃなくてMap1でした。
Set Actor Tick Interval ノードを使用します。
確認します。
Event TickにPrint Stringを追加します。
Print StringのDurationのDefault値は2秒なので、1秒間に一回だけTickするなら常に2回だけ表示されるはずです。
常に2回だけ表示されています。
更に影の動きが滑らかでは無くなりました。
これじゃ、Costがかかっても滑らかな方が良いです。Set Actor Tick Interval ノードは外します。
4.2 NPCが止まった時にIdleするだけでなく別の動きを追加する
先週、Generic NPC Packを調べたら止まっている時に使用出来そうなMotionが沢山ありました。
これはNPCが散歩している時は良いんですが止まっている時が少し不自然な感じがします。
これを先程のGeneric NPC Packを使用して直すようにします。
このAnimationを追加する事にします。
NPC_AnimationBPを開き
AnimGraphを開き
State Machine、DefaultにNPC_Poseを追加しました。
NPC_Pose内で先程のAnimation、Anim_Body_Streach1を追加しようとしたら
ないです。
Anim_Body_Streach1のRetargetする事を忘れていました。
2021-12-20のBlogにRetargetingのやり方が載っていましたのでそれに沿ってやっていきます。
Anim_Body_Streach1を右クリックしてRetarget Anim AssetsからDuplicate Anim Assets and Retargetを選択してSelect Skeletonを開いたら
NPC用のSkeletonが表示されていません。
何で?
調べたらなんとこのGeneric NPC PackのSkeletonは別の所にありました。
Third Person Characterで使用されているSkeletonと名前が一緒で中身も多分一緒だと思いますが、別なSkeletonでした。
こっちのUE4_Mannequin_Skeletonを開いてRetarget Managerを開き
以下の条件でSaveします。
もう一度、Anim_Body_Streach1を右クリックしてRetarget Anim AssetsからDuplicate Anim Assets and Retargetを選択してSelect Skeletonを開きます。
今度は選択出来るSkeletonが3つ程表示されました。
先にこっちのUE4_Mannequin_Skeletonのポーズを直します。
T字にしました。
以下のボタンの使用方法が分かりません。
適当に押してSaveしました。
もう一度、Anim_Body_Streach1を右クリックしてRetarget Anim AssetsからDuplicate Anim Assets and Retargetを選択してSelect Skeletonを開きます。
今度はSourceのMannequinがT字になっています。
SK_Character_Fantasy_Skeletonを選択してRetargetを押します。
新しいAnim_Body_Streach1が出来ました。
NPCが伸びしています。
NPC_Poseを開くと今度は先程作成したAnim_Body_Streach1があります。
Anim_body_Streach1をセットしました。
一つ前のState Machine、Defaultに戻って以下のTransition Ruleに
以下の設定をしました。
ここに使用しているPose変数は新しく作成しました。
このPose変数の値をBehavior Treeから変更するために
新しいServiceを作成しました。
場所的にTaskで作成した方が、Behavior Treeは簡潔に見えるのですが、If節の{}内を指定するのはServiceが担当すべきという信念に基づいて敢えてServiceで作成しました。
新しいServiceの実装内容です。
Behavior Treeの以下の部分に追加しました。
一見するといびつでTaskからNPC_AnimationBP のPose変数の値を変更するとBehavior Treeはもっと綺麗になるんですが、TaskはAIで操作されるキャラが何かしの動作をすべきと考えているので敢えてServiceを使用しています。
テストします。
出来ています。
どうでも良いですがGeneric NPC PackのAnim_Call_Someone_1の
Motionが手を招く形になってますね。
これ日本では人を呼ぶGestureですが、アメリカだとあっちへ行けの意味になりますね。
このMotionを作成したのが日本人なのかそれとも日本以外にも同じGestureで人を呼ぶ国があるのか興味深いですね。
もう少し色々なMotionを追加したいですが、別な部分とのバランスもあるので今週はここまでとします。
4.3 NPCによっては歩き回らない。夜でも存在するなどの選択が出来る様にする
これは個々に対応した方が良いですね。
<夜でも存在するNPC>
夜でも存在するNPCは先週、作成したNPCを朝、夜で生成、破壊する実装部で管理した方が良いです。
後、この部分の整理も必要ですね。今の機能ではNPC一人にしか対応していません。
この部分を直すのをすっかり忘れていました。
<歩き回らないNPCの作成>
これはNPC_Personごと新しく作成した方が良いですね。
ただし、Behavior Treeだけ別に作成する事も可能かもしれません。
それだけ調べてみます。
MYNPC_AIControllerを見ると以下の方法でBehavior Treeを指定しています。
AI ControllerにはNPC_Personから以下の方法で値をパスする事が出来ます。
すると複数のBehavior Treeの指定も出来そうです。
試してみます。
試したら良く分からないbugを発見したのでちょっと中止します。後でもう一回考えます。
<Bugの直し>
NPCが伸びをしている時にPlayerを見つけた場合、伸びを止めません。
それだけならまだしもその後は伸びをしたまま移動し始めます。
Debugすると理由が分かりました。
NPCが伸びをした状態でPlayerを発見すると残りの要素がキャンセルされてしまうので
Change PC Poseが呼ばれません。
以下の場所にChang NPC_Positionを追加しました。
テストします。
NPCが伸びをしている時に近づきました。
伸びを止めてこっちを見ました。直りました。
伸びをしている時なんですが、腕が異常に長くなっています。
こっちは普通です。
NPCのMeshのScaleを変えたせいかもしれません。後で検討します。
<先週の実装部分の整理>
NPCの生成部分の実装を見てみると
NPCの生成に以下のデータが必要です。
- 生成場所のLocation、Rotation、そしてScale
- 村の名前
- 職業
- Meshの種類
更に追加点として
- 夜は消滅するのか徘徊するのか
- どのBehavior Treeを使用するのか(これは中止したい。AI Controllerも別なものを作成した方が簡単のようです。NPC_Personの別バージョンで対応します。)
も必要になります。
NPCの生成に必要なDataを保持するためのStructを作成してみます。
これを元にGame Instance内にArrayを作成します。
と思ったらこんな表示が。
これは後で調べます。
RPG Game Instance BP内に先程作成したStructを使用して
Arrayを作成しました。
中のDataは一個だけです。
先週、Map1のBPに作成したNPCを生成したり消したりする実装部分を先程作成したRPG Game Instance BP内のArrayのDataを使用出来るように改良します。
Array内には一個のNPCのDataしか入っていませんが、まずそれで試してみます。
昼はNPCが出現しました。
夜になるとNPCは消えました。
NPC、一体なら出来ています。
もう一体増やして見ましょう。
以下のDataを追加しました。
テストします。
昼です
2体のNPCは普通に生成しました。
夜になったらNPCは2体とも消えました。
出来てるみたいです。
今週はここまでにして、来週、今日作成したGame Instance 内のNPCの生成データのArrayを使用して村のNPCを全部動的に生成する事にします。
<Texture Streaming Poolに関する補足>
Fixing ‘Texture Streaming Pool Over Budget’ in UE4 [4]に詳しい説明がありました。今週はこの問題に取り組む時間はありませんが、これを読んだら解決しそうです。来週、このBlogも読む事にします。
5.Game Design:ポケモン+HxHの念能力( 戦闘システムの作成)
5.1 Monsterの召喚Widgetの作成
Monsterの召喚Widgetですが、Drag and Dropで作成したいです。のでそれを最初に勉強します。
5.2 Drag and Dropの機能を追加する
Drag and Dropの機能を追加するために以下のTutorialを見つけました。
以下にURLと簡単なコメントを記録しておきます。
- 公式のDocumentであるCreating Drag and Drop UI [5]
- Mathew Wadstein氏 のHTF do I? Drag and Drop: The Basics ( UE4 ) [6] とHTF do I? Drag and Drop: Using a Class Operation ( UE4 ) [7]、あとHTF do I? Drag and Drop: Using a Payload ( UE4 ) [8]もある
- Reids Channel のUnreal Engine 4 - Inventory System - Drag and Drop (1/3) [9] とその続き
- Ryan Laley氏のUnreal Engine 4 Tutorial - Ability System Pt.18 - Drag and Drop [10]
- Jayanamの Unreal Engine 4 Inventory Tutorial: Drag and Drop (1) [11] とその続き
どれで勉強しても同じだと思いますが以下の公式のTutorialだけは私はお勧めしません。
公式のDocumentや公式のOnline Courseは非常に良いですが、このシリーズははっきり言ってクソです。もしかしたら良いコースもたまにはあるのかもしれませんが、全体的に言って5分で説明出来る事を1時間かけてしゃべっています。しかも分かりにくい。更に公式のTutorialなので必ず最初の方でお勧めされます。
一応、確認のために最後にちょっとだけ見てみますが時間の無駄になるとは思っています。
最初、公式のDocumentであるCreating Drag and Drop UI [5] を見たんですが、Mathew Wadstein氏 のHTF do I? Drag and Drop: The Basics ( UE4 ) [6]のTutorialの方が分かり易そうなのでこっちから勉強します。
5.3 Mathew Wadstein氏 のHTF do I? Drag and Drop: The Basics ( UE4 ) [6] とその続きを勉強する
一個のTutorialで終りだと思ったら3つもありました。Drag and Dropのノードをポンと使用すれば終りと言う訳ではないみたいですね。
<HTF do I? Drag and Drop: The Basics ( UE4 ) [6]の勉強>
このTutorialで解説する以外にもDrag and Dropを作成する方法があり、それも後で解説しますが、このやり方がもっとも根本的であると説明しています。更にこのやり方だと学習者がDrag and Dropの原理を理解しやすいそうです。
最初にDrag and Dropを簡単に説明していました。それを殴り書きでまとめると大体以下の様になりました。
- 画面上のDrag and Dropの対象物をクリックしてDragする
- その対象物はDragされた事によりDrag and Drop EventのDragを発する
- それはDrag and Drop Operationを発動する事になります。
- Drag and Drop OperationとはDragされた対象物が持っている情報を、Dropした所に移す事です。
- Dragしている間をどのように表現するかも決定します。
- Dropが受け入れられたらDrag and Drop EventのDropが発します。
何となく言っている事は分かります。
個人的な推測を言うとDrag and Dropの勉強で大切なのはどこでEventを発するかのようですね。
あとDrag and Dropを作成するためには4つのWidgetが必要になるそうです。
兎に角やってみましょう。
最初のWidgetはDragされるWidgetの作成のようです。DragされるWidgetそのものの作成なのかDragされるWidgetを入れる容器のためのWidgetの作成かはまだ分かりません。
Horizontal Barを入れて終でした。
見にくいのでBorderでWrapして色を追加しました。
どうやらDragされるWidgetそのものの作成ではなく、DragされるWidgetを入れる容器のためのWidgetの作成のようです。
次にこのUIをこのLevel上で開くための実装をLevel BPで作成しました。
こんな感じです。
Set Input UI Onlyノードを使用しているのでUI上をCursorが移動する以外のInputは機能しなくなっています。
今度はDragされるWidgetそのものを作成するようです。W_Draggable Itemと名付けました。
Designは単純なImageを表示するだけです。色はTutorialでは緑を選択していましたが、緑は既にBGCで使用してしまったので黄色にしました。
サイズは128x128です。
最初に作成したWidgetに戻り、今作成したこのWidgetを生成します。
こんな感じです。
テストします。
当然ですが、この状態で黄色の四角を選択してDragしても何も起きません。
黄色の四角を選択してDrag出来るようにするためにはW_Draggable Itemウィジェットに戻り、FunctionsにあるOnMouseButtonDowmをOverrideします。
FunctionsのOverrideをここでするのはあんまりやった事ないです。
以下の様に実装しました。
Mouseのボタンがクリックされるとこの関数が呼ばれて、そこからMouseの左ボタンがDragされているかどうかを更にCheckしているんでしょうか?
何で最初からDetect Drag if Pressed()関数を使用しないんでしょうか?
Detect Drag if Pressed()関数はDragしている間中発動する関数じゃないのかもしれませんね。
この辺は後で確認します。
今度はOn Drag Detected()関数を上書きします。
うーん。ちょっと分からない事がありますがとりあえず先に進みます。
これでテストします。
黄色のItemをMouseの左ボタンでDragするとHelloがPrintされました。
試しにMouseの右ボタンでDragしてみましたが何の反応もありません。
成程、On Drag Detected () 関数は単にMouseをDragしただけでは呼ばれないようです。この関数を呼ぶためには以下のDetect Drag If Pressedノードから呼ぶ必要があるみたいです。
しかもこのノード、On Drag Detected () 関数を呼ぶ場合は、左のMouseのボタンでDragされた場合のみとの条件まで付けています。
On Mouse Button Down () 関数はMouseのどんなボタンがDownされても呼ばれます。色々な条件でMouseのButtonはDownされますがその中で、左のボタンがDragされた場合のみOn Drag Detected () 関数を呼びます。
On Drag Detected () 関数が呼ばれたら、On Drag Detected () 関数内でOverrideされた以下の実装を実行します。
続きをやっていきます。
まずOn Drag DetectedにCreate Drop Operationノードを追加します。
このノードを使用してDragして移動している時に表示されるWidgetを作成します。
以下の方法でCreate Drag Drop OperationノードのDefault Drag Visualにパスします。
こんな感じでItemがDrag出来る様になりました。
今度はDragしたItemをセットするためのWidgetを作成します。
単にImageをWidgetに貼りつけただけです。
ここにItemがDropされたらこのImageの色がRandomに変化する実装をOn Drop()関数に実装します。
このWidgetを一番最初に作成したWidgetであるW_DragFromから以下の様に呼び出します。
こんな感じになりました。
最後にTagのPassの仕方を解説しています。これは特にやらなくても理解出来るのでここでは記録しません。
これだけだけ勉強すれば後は自分で作れそうですが一応残りのTutorialも勉強しておきます。
<HTF do I? Drag and Drop: Using a Class Operation ( UE4 ) [7]の勉強>
ここでは、Create Drag Drop Operationノードに使用されているClassを自分する方法を勉強します。
Blueprint Classを開いてDrag Drop Operationクラスから新しいクラスを作成します。
こんな感じです。
ここからの説明はBPの一般的な使用方法を知っていればほぼ分かる事なので簡単な例だけやる事にします。
変数を追加します。
Expose on Spawnにチェックを入れます。
するとCreate Drag Drop OperationノードでClassに今作成したBP_Drag Drop Testをセットすると
新しい項目のTestが出来ます。
以上です。
<HTF do I? Drag and Drop: Using a Payload ( UE4 ) [8]の勉強>
このTutorialはCreate Drag Drop OperationノードのPayloadの使用方法についての解説でした。
Payloadを使用してObjectをパスしてもした先でCastして元のクラスに戻さないといけないのであんまり使用しない気がします。ので軽く見るだけにしました。
5.4 他のTutorialも軽く見ておく
<公式のDocumentであるCreating Drag and Drop UI [5] >
このTutorialは以下に示したように
PlayerがHealth Barの位置をDrag and Dropで自由に移動できるようにするためのTutorialでした。
ぱっと読んだ感じでは基本的に使用しているNodeやFunctionはMathew Wadstein氏のTutorialと同じでした。
<Reids Channel のUnreal Engine 4 - Inventory System - Drag and Drop (1/3) [9]>
これはDropした時は3DのItemになるTutorialでした。今回は使用しないのでパスします。
<Ryan Laley氏のUnreal Engine 4 Tutorial - Ability System Pt.18 - Drag and Drop [10] >
これは元々制作しているGameのAbility Systemの作成の一環としてDrag and Drop の機能を追加していました。しかしTutorialそのものは分かり易かったです。
<Jayanamの Unreal Engine 4 Inventory Tutorial: Drag and Drop (1) [11] とその続き>
最初の2,3分だけ見ましたが、Mathew Wadstein氏のTutorialと同じやり方でした。
5.5 Drag and Dropを使用したMonsterの召喚Widgetの作成
取りあえず自分で作成してみます。
先週作成したこのWidgetに追加して作成します。
こんな感じで作成しました。
Monsterの絵は適当にその辺にあるイラストから持ってきました。
MonsterをDragします。
MonsterをDrop Boxに落とします。
実装方法は、Mathew Wadstein氏 のHTF do I? Drag and Drop: The Basics ( UE4 ) [6]のTutorialのやり方そのままです。
一応、記録に残しておきます。
赤く囲った部分のImageが
On Mouse Button Down関数とOn Drag Detected関数が上書きされているWidgetです。
On Drag Detected関数は以下の様にOverrideしました。
Create Drag Drop OperationノードのDrag Drop OperationはImageをパスするので以下の新しいクラスを作成しました。
追加した変数は一個だけで
タイプはSlate Brushです。
この辺の設定は、仮組なので理由は何もないです。
黄色で覆った箇所はDragされたWidgetをDropする箇所で、
On Drop 関数は以下の様にOverrideしました。
OperationからImageを受け取る為にCastする必要がありました。これだとPayloadを使用した場合とあんまり変わらないですね。
5.6 このDrag and Dropの問題点と来週以降の課題
まだ全然出来ていない状態で問題点を書き出すほど進んでいませんが一個だけ忘れない様に書いて置きます。
MonsterをDropした後にMonsterのListからそのMonsterを消す必要があります。
今週は単なる絵を表示しただけですが、来週はMonsterのクラスそのものをパス出来るようにします。
そのためにはMonsterクラスをまず作成する必要があります。更にPlayer が所持しているMonsterのリストの作成も必要です。
それらをした後で、上記のMonsterを選択するWidgetの直しが出来るようになります。
今はちょっと頭の中が整理出来ていないのでまた来週以降考えます。
6.RPGのストーリーに関する修正
6.1 先週のまとめ
先週から更にアイデアが膨らんだのでその記録をしておこうと思います。
先週のストーリーについてのまとめでは、
- 隠れたテーマが必要。
- 隠れたテーマは良識に反してるが真実を表していないといけない。
の2点から
にしました。
それで一つの例として以下の設定を考えました。
ここからの修正です。
先週はこれでもかなり良いと思ったんですが、2つの欠点がある事に気が付きました。
6.2 二つの欠点について
spider-man: into the spider-verseはあんまり映画を見ない私でも特別に見に行って更に大満足した稀有な映画ですが、その中のセリフに「ヒーローの仕事は世界を救う事じゃなくて、困っている○○さんとかを救う事だ。」みたいなのがありました。これってヒーローっていうより物語の作成方法についての教えだと思って聞いていました。
それの観点から言うと、人類を救うってテーマは駄目なテーマになります。テーマはもっと身近な話にする必要があります。
もう一つの欠点ですが、はっきり言いますが、今の私が全くのオリジナルな話を作成しても他人の興味を引く事は出来ない事です。もし私が既にある程度有名で、固定ファンもある程度いる状態なら全くのオリジナルな話を作成してもみんなから興味を持って貰えますがそうなるまでは何かの人気作品におんぶ及び抱っこで注目を集める必要があります。
以下に先週のストーリーの欠点をまとめます。
- 物語のテーマが世界を救うみたいな曖昧で抽象的になっている。近所の○○さんを救うみたいな具体性がない。
- ストーリーが完全オリジナルで世間の注目を集める事が出来ない。何かの人気作品におんぶ及び抱っこする必要がある。
この二つの問題を解決した修正案を思いついたので記します。
6.3 ストーリーの修正案
以下のストーリーを考えました。
主人公は小学生5年生で、夏休みで田舎のおばあちゃんの家に遊びに来ています。そこでは読書感想文の宿題をします。そのために宮沢賢治氏の「銀河鉄道の夜」を読むんです。読むんですがカムパネルラの死にどうしても納得出来ないんです。主人公は、途中でカムパネルラが死ぬのは良いとしても、最後は奇跡的に生き返るべきだと思うんです。それで田舎のおばあちゃんの家の近くの神社でカムパネルラを生き返らせてくれとお願いします。
その夜、奇妙な夢を見ます。神社の神様が主人公の寝床に現れて「カムパネルラを生き返らせる方法がある。どうしても彼を生き返らせたかったら、明日の夜、近所の神社に来るように。」と言う夢です。
主人公は居ても立っても居られなくなって次の日の夜、こっそりおばあちゃんの家を抜けて近所の神社に行きます。すると夢に出て来た神様が待っていて主人公に「今から銀河鉄道がやってくるからそれに乗って幻想界に行くんだ。そこで金の切符を探しなさい。金の切符の力ならカムパネルラを生き返らせる事が出来る。」と告げます。
意を決した主人公は銀河鉄道に乗りこみます。そして冒険が始まります。
6.4 修正したストーリーのポイント
まず、ストーリーは身近な話に変更しました。世界を救うとか曖昧な点は外しました。小学生5年生の読書感想文がメインで、主人公は「銀河鉄道の夜」の結末に納得していないと言う平凡な話です。これで抽象的な内容からはおさらば出来ました。
次に隠れたテーマである「良識に反しているけど正しい選択」ですが、小説の結末を変えると言う、良識に反しますが主人公的には正しい行動を取ります。
最後に「ストーリーが完全オリジナルで世間の注目を集める事が出来ない。何かの人気作品におんぶ及び抱っこする必要がある。」ですが、例えば小学生5年生の主人公がHxHの展開に納得出来ない。話を変えるとすればHxHの読者を丸取り出来ますが、それは著作権の侵害で訴えられてしまいます。 宮沢賢治氏の「銀河鉄道の夜」は日本人全員が聞いた事のある大変有名な小説ですが、既に著作権が切れていますから幾ら利用しても問題ありません。
7.Map1のBug直し:武器屋で買える武器の設定の追加
7.1 転職後のParameterについて
転職石があればレベルが何でも転職出来るようにします。ただし転職した後のレベルは常に1です。Monsterの種類によって、剣でしか倒せない。Hummerでしか倒せない。魔法でしか倒せない。魔法騎士でしか倒せない。のような縛りを入れる事にします。そして転職石は戦闘中でも使用出来るようにします。
これが一番、話が膨らみそうです。
偶然ですが、この設定だと何も直す必要がありません。ので先週のままでお終いです。
7.2 道具袋のWidgetの直し
転職するItemなのに現在の職業の表示が有りません。追加します。
どの画面でも以下のParameterを表示するようにします。
出来ました。
これで一応、武器屋の設定の修正は全部、終わりました。
このRPGのストーリーが完全に決まったので、来週からはPrologueを直して行こうと思います。
7.3 Prologueの案
こんな感じの紙芝居のようにしようと思っています。
僕は○○。
小学5年生。
今は夏休みで今日から3日間、おばあちゃんの家に遊びに行きます。
お父さんとの約束で、おばあちゃんの家にいる間に読書感想文の宿題をやる事になっています。
残りはまだ出来ていません。来週作成します。
8.UE5:Naniteの勉強
先週の続きで公式のDocumentであるNanite Virtualized Geometry [8] を読みます。
番号が先週と違うと混乱するので番号は先週の続きで書きます。
先週は英文の意味が良く分からない箇所があってそこでグダグダして止まってしまいました。まだNaniteの仕組みを理解していないので解説を完璧に理解するのは不可能です。軽く読んでいく事にします。
7.10 Visualization Modes
以下の部分の解説がしてあります。
このDocumentではUE5のサンプルであるproject Valley of the Ancientsが使用されていますが、私のPCではそのサンプルはとてもじゃないけど動きません。
のでこの節の勉強はここまです。
7.11 Console Variables and Commands
NaniteのDebugやConfigurationの確認のために以下のStateやCommandが使用出来るそうです。
例えばr.Nanite 0のCommandを使用する事でRuntime中にNaniteのRenderingを使用したり中止したり出来るそうです。
それによってNaniteの効果を確認する事が出来るそうです。
これは何も疑問も生まれない説明です。後でproject Valley of the Ancientsが使用出来るPCが手に入ったらr.Nanite 0のCommandを試してみます。
<Nanite Proxy Rendering Modes>
以下の様な説明がされています。
- NaniteはNaniteが使用出来ない箇所では、Proxy Mesh Rendering Modeを使用します。
- Naniteを使用するかProxy Mesh Rendering Modeを使用するかは、Nanite.ProxyRenderModeで指定出来ます。
r.Nanite.ProxyRenderModeのProxyRenderModeの部分に数字を入れるんですかね。そうしないと先の説明で出て来たr.Nanite 0のCommandと一致しませんから。
この辺はproject Valley of the Ancientsが使用出来るPCを手に入れてから試す事になります。今は推測する事しか出来ません。
その下の説明を読むと、
- 0を指定した場合は、Nanite。
- 1を指定した場合は、
- 2を指定した場合はProxyだけどShow->Nanite Proxy Visualizationが使用出来る。
と読めます。
実際に試してみる事が出来ないので何とも言えないですが、多分解釈は合っているでしょう。
次に行きます。
<Nanite Stats Command>
Command、Nanitestatsを使用すると以下の様な表示がされるそうです。
試してみます。
表示はされました。
ただ私のUE5 のProjectでは数字がないです。Naniteは全く使用していないので当然ですね。
これ消すのはどうしたら良いんでしょうか?
UE4のCommandだと同じCommandを打つと消えたので同じでしょう。
消えません。
うーん。困った。
先に以下のCommandを試します。
Nanitestats VSM_Directionalを試します。
何か違う項目が表示されました。
この辺は必要になった時に勉強する事にします。
Nanitestatsの表示を消す方法が分からないので表示はそのまま残しておきます。
<Controlling Nanite Streaming Pool Size>
NaniteのStreamingに使用出来るMemoryのサイズはr.Nanite.Streaming.StreamingPoolSizeで管理出来るそうです。
流石にこの辺まで弄る事はないでしょう。次に行きます。
<Setting Maximum Clusters in a Single Pass>
Single Pass一つで使用出来るClusterの候補や可視化したClusterの最大数をr.Nanite.MaxCandidateClustorsやr.Nanite.MaxVisibleClustersで指定出来るそうです。
検索したらr.Nanite.MaxCandidateClustorsやr.Nanite.MaxVisibleClustersが表示されますね。
こんな難しい機能を使用する可能性はないです。
<Nanite Virtualized Geometry [8]のまとめと感想>
これで公式のDocumentであるNanite Virtualized Geometry [8]を読み切りました。
2021-12-13のBlogから始めて5回、約一カ月強かけてやっと読み切りました。あんまりきちんと理解したとは言えませんが何となくNaniteの仕組みと長所や短所は理解出来ました。来週からはTutorialを探して実際にNaniteを作成してみようと思います。
YouTubeで検索したら以下のTutorialが出て来ました。
どれかは役に立つでしょう。今週はここまでにします。
9.まとめと感想
もう疲れました。くたくたです。
今週の最大の収穫は今作成しているRPGのストーリーのPrologueが決まった事です。これで全体がピリッとしましたし、これから何をやらないといけないのかもはっきりしてきました。
10.参照(reference)
[1] CGHOW. (2021, July 13). Distort in all Directions in UE5 Material and Niagara | Download Project Files [Video]. YouTube. https://www.youtube.com/watch?v=jiiUVxygeKU
[2] Cloward, B. [Ben Cloward]. (2021, December 16). Direction Masks - Shader Graph Basics - Episode 27 [Video]. YouTube. https://www.youtube.com/watch?v=HKSIxFnsHuk&list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl&index=27
[3] Epic Games. (n.d.-a). Coordinates Expressions. Unreal Engine Documentation. Retrieved January 16, 2022, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Materials/ExpressionReference/Coordinates/#vertexnormalws
[4] Mower, N. (2021, November 21). Fixing ‘Texture Streaming Pool Over Budget’ in UE4. Techarthub. Retrieved January 16, 2022, from https://www.techarthub.com/fixing-texture-streaming-pool-over-budget-in-ue4/
[5] Epic Games. (n.d.-b). Creating Drag and Drop UI. Unreal Engine Documentation. Retrieved January 16, 2022, from https://docs.unrealengine.com/4.26/en-US/InteractiveExperiences/UMG/HowTo/DragAndDrop/
[6] Wadstein, M. [Mathew Wadstein]. (2016, November 6). HTF do I? Drag and Drop: The Basics ( UE4 ) [Video]. YouTube. https://www.youtube.com/watch?v=WfF3fb0WaoY
[7] Wadstein, M. [Mathew Wadstein]. (2016b, November 12). HTF do I? Drag and Drop: Using a Class Operation ( UE4 ) [Video]. YouTube. https://www.youtube.com/watch?v=rx56zqdZx8Y
[8] Wadstein, M. [Mathew Wadstein]. (2016c, November 13). HTF do I? Drag and Drop: Using a Payload ( UE4 ) [Video]. YouTube. https://www.youtube.com/watch?v=pv6U28TTyXo
[9] Reids Channel. (2020, January 8). Unreal Engine 4 - Inventory System - Drag and Drop (1/3) [Video]. YouTube. https://www.youtube.com/watch?v=dnoMQF1ZqtQ
[10] Laley, R. [Ryan Laley]. (2020, August 7). Unreal Engine 4 Tutorial - Ability System Pt.18 - Drag and Drop [Video]. YouTube. https://www.youtube.com/watch?v=yu4brVb6S88
[11] Jayanam. (2017, June 3). Unreal Engine 4 Inventory Tutorial: Drag and Drop (1) [Video]. YouTube. https://www.youtube.com/watch?v=7NNL7mwl3Ss
[12] Epic Games. (n.d.-c). Nanite Virtualized Geometry. Unreal Engine Documentation. Retrieved January 16, 2022, from https://docs.unrealengine.com/5.0/en-US/RenderingFeatures/Nanite/