<前文>
<PS5とUE5>
あんまりGameそのものには興味のない私はPS5が日本で全然流行ってない事を先週まで知りませんでした。
PS5 を買えない日本人(の貧乏?)がやばい。みたいな論調が日本では主流のようですが、私は逆にUE5の方が大変な事態じゃないのかなと思っています。
今週はそれについて解説します。
まず3D Graphics ProgrammingってGame会社が作っているんじゃないんです。大学、それもその筋の研究者が色んな大学から沢山集まってそれぞれの専門分野を作成しています。何が言いたいのかと言うと3D Graphicsが成立するためには、とんでもないお金を掛けて基礎研究する必要があります。その成果がGPUになったりUE5のようなGame Engineになったりしています。だからその大量のお金を掛けて研究した基礎が無いと、GPUもGame Engineの様な華やかな部分も出来ないんです。
ところが、やっぱり大学で研究するとなると大学故の制約があるんです。
例えば、Global Illuminationの計算をもっと簡単で速くするとか、動的に歪みのある大量のVertexの処理を高速で行う。みたいな定量的な評価が出来かつ社会からのニーズがある分野はどんどん予算がついて研究されてます。しかしアニメ風のrenderingの仕方とか3Dで美人のModelを作成するための研究は、定量的な評価が出来ないどころか、美人であるとかアニメ風であるっていう事は客観的な評価すら出来ないので予算が付きません。
特にアニメはアメリカの大学では学問と見なされていません。だから例えば大学の芸術でアニメは勉強出来ないんです。これ凄いんですがGameや映画は学問として認めれられているんです。
でもアメリカ人は日本のアニメ風のGameがやりたくてしょうがないんです。
どれくらいアメリカ人が日本のアニメ風の文化が好きか、日本にいると体感出来ませんが物凄い好きです。
しかしアメリカの大学ではアニメ風のRenderingとかの研究の予算は非常につきにくいので、日本のアニメ風のGameをアメリカ人だけで作成する事は無理です。日本の力が必要なんです。
しかし日本人がPS5で遊べないとなると日本のGame会社もUE5でGameを作ろうとは思わなくなるでしょう。
結果的にアニメ風のGameはSwitch用にUnityで作成しようと言う雰囲気が生まれるんじゃないでしょうか?
確かに最新の3D Graphicsの技術を集めたUE5とPS5のGameをPlay出来ない日本のSoftware 技術はGameに関しても先進国から中進国位の衰退に直面するでしょう。それはそれで日本で暮らす我々は大変ですが、その結果、もっと大変になるのは最新鋭の技術を持ちながらアニメ風のGame が作られなくなるUE5の方な気がします。
だってアメリカ人、日本のアニメ風のGameが大好きですから。
Epic Games社側で、日本でUEを使用してアニメ風のRenderingを研究している個人やグループにMega Grantsを渡して、UEがアニメ風のGameに対して積極的に支援したり、日本にアニメ風のRenderingを研究するための施設を東大クラスの大学院と共同で作ったりしてアニメ風のRenderingに対してUEは真剣に取り組んでいると言う姿勢を日本で思いっきりアピールすれば別な展開が生まれるかもしれませんが、このままの状態だと結構、最悪な結果になる気がします。
それでは今週の勉強を始めます。
<本文>
1.今週の予定
今週もいつも通りやっていきます。
- Niagara: HLSL Triangle code to UE4 Material nodes Tutorialの続き
- Material : Content Exampleを見るの続き
- NPCのAIを作成する
- Game Design:ポケモン+HxHの念能力( 戦闘システムの作成)
- Map1のBug直しの続き
- UE5:naniteの勉強
2.Niagara: HLSL Triangle code to UE4 Material nodes Tutorial [1] の続き
先週の続きでCGHOW氏のNiagara: HLSL Triangle code to UE4 Material nodes Tutorial [1] の残りをやっていきます。
2.1 ノードを改良して見た目を綺麗にする
<Fracノード>
公式のDocumentのMath Expressions [2] にFracの解説がありました。
Floorは単なる小数点の切り捨てです。xの値が1.5だった場合Floor(1.5) は1になります。1.5-1=0.5です。
4で掛けているのでU軸、V軸ともに0から4になっています。それらの全ての数字にFracをかけると
となります。
<Custom Rotator>
公式のDocumentのCustomRotator [3] はここです。
この公式のDocumentのCustomRotator [3]にはNodeにCursorを乗せてCtrl+Altからではたどり着ません。
Material Functionと言う全く別の所に飛んでしまいます。
これは端に間違いだと思うんですが、違うんでしょうか?
Rotation Centerが自作の回転と違い+になっています。後は特に解説する所はないです。
中を開くと以下の様な実装になっていました。
こっちが自作した回転の実装です。
比べると結構計算方法が結構違います。
まず回転の中心に関してですが、私が自作した回転は中心の移動は含んでいません。回転の外側で実装する必要があります。その場合もTextureの中心で回転させたい時はU軸に-0.5、V軸に-0.5ずらす必要があります。
Custom Rotatorノードの方を見るとInputした値に-1を掛けてTextureに足しています。
計算方法は微妙に違いますが、結果は一緒になりますね。
ここでは-1を掛けて足していますが、これって単に引くよりもCostが低くなるんでしょうか?
興味深い所です。
回転の計算式で興味深い処が一点ありました。
SinやCosに0~360度を0~1に変換して渡す場合、SinやCos のPeriodの設定が1になっているとSinやCos のPeriodの設定が6.28でSinやCosに0~360度の値を渡した場合と同じ結果に成ると言う事を示している箇所がありました。
これは面白い発見ですのでテストして確認します。
テストします。
元の絵です。
回転した後です。
時計回りに回転してます。
SinノードとCosノードのPeriodを6.28に戻して
90度回転させます。
90度/360 度=0.25なので同じ結果になるはずです。
なっていました。
残りはDotノードを使用したりしていますが計算の順番が違うだけで同じ事をしていました。
Dotノードについても細かく検討しようと思ったんですが、これ以上Custom Rotatorにこだわると粒度(Granularity)がバラバラになりそうなので今回はパスします。
<それぞれの三角をバラバラに回転する>
以下の計算でそれぞれの三角形に別々な値を作成しています。
まずTexCoord[0]にMultiplyノードで4で掛けています。
最大値が4になっています。勿論、上記のMultiplyノードの色は1以上は全て同じなのでImageからは分かりません。
Floorを掛けます。
0~0.9999…が0になり1.00~1.9999…が1になり2.00~2.9999…が2になり3.00~3.9999…が3になります。
うーん。4は4ですよね。
最後の1Pixelは4があるんでしょうか?
4で割ります。
0/4=0、1/4=0.25、2/4=0.5、3/4=0.75、4/4=1です。最後の1は1Pixel分だけとあるようには見えないですね。
気になるのでSmooth Stepノードをつけて確認してみます。
0.9以下は黒く、1以上は白く表示されるはずです。
あれ。真っ黒ですね。
あ。
0から0.999とかまでで1は入っていないんですね。Floatの数え方を忘れていました。
解決です。
最後にPerlin NoiseのTextureに繋いでいます。
これはTextureの
(0, 0)、(0, 0.25)、(0, 0.5)、(0, 0.75)、
(0.25, 0)、(0.25, 0.25)、(0.25, 0.5)、(0.25, 0.75)、
(0.5, 0)、(0.5, 0.25)、(0.5, 0.5)、(0.5, 0.75)、
(0.75, 0)、(0.75, 0.25)、(0.75, 0.5)、(0.75, 0.75)、
の箇所の値を取っているだけで別にNoizeであるならPerlinである必要はないですね。
<時間で三角形を回転させる>
以下の部分ですね。
ここは時間である値を-1から1の間で変化したい時、sinを使用する定番のヤツですね。
でもこれだと最後に0~1の間に変換した方が良い気がしますが。
試してみます。
こんな感じになりました。
前の状態です。
うーん。どっちが良いか。
色の調節にはSaturateノードが使用されています。
色に対しては-1~1で良い気がします。
うーん。半分消えているのは多過ぎな気がしますね
Saturateの前に0.5足しました。
イイ感じです。
2.2 Flower Effect in UE4 Niagara Tutorial [4] を勉強する
CGHOW氏のFlower Effect in UE4 Niagara Tutorial [4] を勉強します。
何かTextureをMaterial内で色々弄ってそうなのと単純に綺麗だからです。
まずぱらっと全部見ました。
自作が必要なMeshとかはなかったのでやっていきます。
<M_Patternの作成>
Radial Gradient Exponentialノードを使用します。
Densityに7000をセットすると境界が非常にはっきりした円が描かれます。
Radial Gradient Exponentialノードの実装についても検証したいですが、これは来週以降します。
ここから中が空洞の円を作成します。
一つ目の方法は半径の少しだけ小さい円を同じ方法で作成してそれを引きます。
こんな感じです。
もう一つの方法は3ColorBlendノードを使用するやり方で
黒がA、白がC、その間がBで使用した色で表示されます。
なので以下の様な色を指定すると
こうなります。
更にResult ノードの設定を以下のようにして
以下の様に実装します。
バックが透明になりました。
更にLerpを追加して色をつけます。
取りあえずこんな色にしました。
Opacityに5を掛けます。
うーん。これは何が目的なんでしょう。この辺も来週以降考えます。
<<円に歪みを加える>>
この円に歪みを追加します。
まずRadial Gradient ExponentialノードのUVsに以下の実装を追加します。
Texture SampleのTextureは付属のPerlin Noizeを使用しました。
Radial Gradient Exponentialノードのイメージは以下に示したようになりました。
Texture Sampleの値に0.15を掛けて値を小さくすると
円に近い形に戻ります。
しかしこの方法では円の中心も移動してしまいます。
ので以下の様な実装にします。
なんでこれで中心が固定されるんでしょう。これも来週以降検証します。
更にTexture SampleにPannerノードを追加して動きを加えます。
一寸、Tutorialよりも動きが速い感じがします。
Noizeに使用しているTextureが違うので完全な一致は無理ですので許容範囲と見なして先に進みます。
色々な値を弄ってTutorialの感じに近づけました。
これで一応、Materialの作成が終わりました。
<Niagaraの作成>
今度はNiagaraを作成します。
Niagara SystemでFountainを追加します。
Preview Scene Settingの設定を以下のようにして
PreviewのBackgroundの色をこんな感じにしました。
Renderer SectionのSprite Renderer ModuleのMaterialを先程作成したのと交換しました。
更にSorting ModeをCustom Descendingに変更しました。
Sorting Modeは初めて使用するParameterです。後でどんな機能なのかを検証します。
こんな感じです。
Tutorialの例は以下の様に黒い淵がはっきりしています。
以下の部分に1.2を掛ける事で黒い線の部分を太くしました。
Ringの太さが
1.2倍になっているはずです。
結果です。
前よりは黒い線がはっきりしています。
先程のLerpにParticle Colorを追加します。
そしてParticle Spawn SectionのInitialize Particle Moduleから
Colorをセットします。
こんな感じです。
Particle Spawn SectionのAdd Velocity in Corn Moduleを消してAdd Velocity From Point Moduleを追加しました。
こんな感じです。
Sizeを変化させます。
Particle Update SectionにScale Sprite Size Moduleを追加します。
Tutorialでは以下の様に設定していますが、
私のScale Sprite Size Moduleは項目が少し違っているので以下の様にセットしました。
よく見たらTutorialではUE4を使用していました。
結果は同じになるはずです。
結果です。
サイズがSpriteの寿命によって変化しています。
色も変化させます。
Particle Update SectionにColor Moduleを追加します。
色の指定はこんな感じです。
結果です。
Niagara から操作しやすいようにMaterialのParameterをDynamic Parameter ノードを使用してまとめます。
ParameterのDistortとTileをDynamic Parameterにまとめました。
Dynamic Parameterと普通のParameterの違いはわかりません。これは来週調べます。
NiagaraのParticle Update SectionにDynamic Material Parameters Moduleを追加します。
TileとDistortの値をRandomにします。
結果です。
Level上に配置してみます。
<色々なVariationのFlower Effectを作成する>
作成したNiagara EffectとMaterialを複製します。
新しいFlower EffectはEdgeの色もControl出来るようにします。
LerpノードのBにParticle ColorとDynamic Inputを掛けた値を繋げます。
これだと色をControlするんじゃなくて色の輝きの強さをControlしますね。
Dynamic ParameterのEdgeの値に140をセットします。
こんな感じです。
ちなみにEdgeにNegativeな値を入れると
こんな結果になります。
Edgeが黒くなりますね。
Particle Update SectionのColor ModuleのScale Colorの値を下げる事で色を暗くします。
こんな感じです。
これが2個目のFlowerのEffectです。
<<三番目のFlower Effect>>
三番目のFlower Effectを作成します。
Black BodyノードをParticle Colorの代わりに使用します。
BlackBody ノードは黒体放射を表すノードだと思うんですがこれも後で調べます。
BlackBodyノードで色を決定するのでNiagaraのParticle Update SectionにあるColor関係のModuleは必要ないです。
消します。
更にDynamic Parameterで
温度を指定します。
結果です。
こんな感じです。
<<四番目のFlower Effect>>
Particle Spawn SectionのSphere Location Moduleを消し更にAdd Velocity From Point Moduleを外して、Torus Location Moduleを追加します。
Torus Location ModuleのTorus Distribution ModeはDirectになります。
Emitter Update SectionのSpawn Rate Moduleを消してSpawn Burst Instantaneous Moduleを追加します。
Spawn Burst Instantaneous ModuleのSpawn Countに10をセットします。
またParticle Spawn SectionのParticle Spawn Sectionに戻り
U PositionにReturn Normalized Exec Indexをセットします。
Tutorialの方ではNormalized Index Scaleという項目が存在してます。
UPositionにReturn Normalized Exec Indexを追加した方法が違っているのかもしれません。これも後で検証します。
結果です。
微調整をした後で、Particle Spawn SectionのAdd Velocity From Point Moduleを起動します。
こんな感じになりました。
Emitter Update SectionのEmitter State Moduleの
Loop Durationの値を0.2にセットします。
すると
となります。
Level上に配置します。
するとTorus は上向きに作成されているので上記のような配置になってしまいます。
Tutorialではこれを直すためにEmitter Settings SectionのEmitter Properties Moduleに
Local SpaceにCheckを入れて
回転させています。
こんな感じになります。
しかしEmitter Settings SectionのEmitter Properties ModuleのLocal SpaceのCheckを外しても同じ事が出来ます。
結果です。
全く同じ様に出来ました。
Emitter Settings SectionのEmitter Properties ModuleのLocal Spaceの機能については後で調べます。
<<5番目のFlower Effectを作成します>>
Emitter Update SectionのSpawn Burst Instantaneous Moduleの
Spawn Countの値を10に下げます。
以下のようになります。
この結果を見ると明らかですが、Spriteの位置が毎回、正確に同じ場所から誕生しています。これに揺らぎを加えます。
それを可能にするのがParticle Spawn SectionにあるTorus Location ModuleのNormalized Angle Around Torus Axisです。
Normalized Angle Around Torus Axisに0.2を入れてみます。
以下の様な結果になりました。
うーん。
Spriteの発生位置にブレが出来ているのか分かりません。
しかしTutorialの本筋はそこではなくて、これをEmitter一回毎にセットし直さないといけないそうです。
その方法について解説していますのでそれを行います。
まずFloat型のEmitter Name Spaceの変数を作成します。
Particle Spawn Section にSet Parameters Moduleを追加します。
Set Parameter内でFloat型のEmitter Name Spaceの変数を作成します。
名前はRot_Offsetです。
次にこの変数を先程のParticle Spawn SectionにあるTorus Location ModuleのNormalized Angle Around Torus Axisにセットします。
最後にParticle Spawn Section のSet Parameter Module内でRot_Offset変数の値にRandom Range Floatをセットします。
結果です。
Spriteの位置が微妙にずれています。
これで完成ですが、更に良くするためにMaterialも改良します。
LerpとEmissive Colorの間にHue Shiftノードを追加します。
Hue Shiftノードについては後で調べます。
Hue ShiftノードのHue Shift Percentage (s) ResultにDynamic Parameterを繋ぎます。
しかしDynamic Parameterの四つの要素は既に使用されています。
そこで新しいDynamic Parameterの使用が必要になるんですが、それは
Parameter Indexの値を0から1に変化すれば良いようです。
Niagaraに戻り、Particle Update SectionのDynamic Material Parametersの
Write Parameter Index1にcheckを入れて
HueにRot_Offsetをセットします。
その結果、
になりました。
Level上に配置するとこんな感じになります。
今週はここまでです。
知らないノードの機能などについては来週検討します。
3.Material : Content Exampleを見るの続き
ここの所、Ben Cloward先生のTutorialから離れていたのでContent Exampleは今週はお休みしてBen Cloward先生のSwizzle & Channel Manipulation - Shader Graph Basics - Episode 25 [5] をやる事にします。
3.1 Swizzle & Channel Manipulation - Shader Graph Basics - Episode 25 [5]を勉強する
一応全部見たんですが、超簡単に言えば、以下のNodeの使用方法についての説明です。
まずChannelとは、以下の例で言えば、
R、G、B、AがそれぞれのChannelに当たります。
そしてChannel Manipulationとは、これらのChannelの数を減らしたり増やしたり順番を入れ替えたりする事を指します。
それでですね。
一応、ここで説明された内容は全部、知っている事でした。でしたが、初心者に自分で説明する気になって勉強してみます。
<Channel Manipulationに関する3つの事>
<<Channel Manipulationに使用する以下のノードのCostはfreeである>>
つまり、RGBAの内、Rだけ計算する必要がある場合、RGBAからRのみを分離して計算してその後で、残りのGBAと計算したR’の値でRGBAに戻した方が、RGBA全てに計算するよりもCostが少なくてすみます。
<<Channel Manipulationのやり方はUnityとUnrealではかなり違う>>
これは、まあどうでも良いです。
<<それぞれのChannelを表すのにRGBAやXYZWなどの違う表示が使用されるが名前が違うだけで中身は一緒である>>
XYZとRGBは交換して使用する事も出来きます。
RPGは色に関するDataに使用されます。XYZは座標に関するDataに使用されます。更にTexture座標に関してはUVが使用されます。これらは単に名前が違うだけでChannel Manipulationに関しては同じものとして扱う事が可能です。
この辺は初心者は結構、迷う箇所かもしれません。特にTexture座標がUVで呼ばれる事に関しては???でしょう。
<Task1:Texture SampleのRGBAのAを除いてRGBにする>
これはUnityではそれなりの手順が必要ですがUnrealではTexture Sampleノードに標準でついている機能です。
それ以外の、例えばComponent 4 VectorノードのRGBの値だけ取り出す時は、Maskノードを使用します。
MaskノードはMaskと打っても表示されません。
ComponentMaskと打つ必要があります。
更に、MaskはDefaultでは
RGのみOutputする仕様になっているのでBにCheckを入れる必要があります。
<RGBとAを合わせてRGBAを作成する>
RGBとAを合わせてRGBAのような4つのChannelを持つノードを作成する事とAppendすると言います。
UEではそのものずばりAppendノードを使用します。
Append ノードの正式な名称はAppend Vectorです。
これは間違えてAppendしか打たなくても出て来るのでAppendノードが見つからない事はないでしょう。
<RGBの値のうちRとGを交換したい>
これはSwizzleノードを使用すると出来ます。
後Swizzleノードは、XYの値を交換してYXにする事も出来ます。
しかし場合によってはSwizzleノードで対応出来ないRとBを交換したいとかRとAを交換したいとかをする必要があります。
その場合は、Append Manyノードを使用します。
Append Manyノードならばどんな組み合わせも可能です。
Texture SampleノードはRGBAが全部分かれていますが、Constant 4 Vectorノードの場合はRGBAは分かれていません。
その場合はSplit Componentノードを使用します。
ただしこのノードFloat3 を分解してそれぞれのChannelに移すだけなのでAの値がないです。
RとAの値を交換したい場合、以下のような実装をする必要があります。
以上です。
3.2 TexCoord[0]と計算だけで三角形を作成する
2021-12-13のBlogでTexCoord[0]と計算だけで三角形を作成する位は、私だって出来ます。と言って出来ませんでした。
これが出来たとしても何かCostが低くなるとかがあるのかは分からないですが、MaterialのMatrixの計算の理解と手段を自分の物にするための練習にはうってつけなのでもう少し頑張ってみました。
今週の結果は以下のようになりました。
実装方法は以下に示します。
やっぱり三角形は真ん中が中心で正三角形にしたいですね。
もう少し考えてみます。
4.NPCのAIを作成する
4.1 NPC用のAIのための4つのクラスを作成する
まずはUEのAIを作成するために必要な4つのクラスのうち、既に作成されているCharacterクラス以外の3つのクラスを作成します。
4つのクラスを繋げます。
CharacterクラスであるNPC_PersonのBPのAIに先程作成したAI_Controllerをセットします。
MyNPC_AIControllerのBPを開きBehavior Treeを実行するために以下の実装をします。
実行するBehavior Treeは勿論、先程作成したMyNPC_BehaviorTreeです。
最後にMyNPC_BehaviorTreeを開いてBlackboard Assetから仕様するBlackboardを指定します。
指定するBlackboardクラスは勿論、先程作成したMyNPC_Blackboardです。
テストします。
まずBlackboardクラスにBoolean変数を作成します。
次にBehavior TreeでそのBool変数がTrueになったら文字を表示する実装を組みます。
Task、PrintStringTaskの実装は以下の様になっています。
実行されると“I see you”がPrintされます。
先程作成したAI ControllerクラスであるMyNPC_AIControllerのBPにこのBlackboardクラスの変数であるCanSeePlayerの値をTrueに変更するためのEventを実装します。
このEventをCharacterクラスであるNPC_Personからある条件の時に呼び出します。
結果です。
I see youがprintされています。
NPC用のAIは機能していますね。
4.2 BehaviorTree を作成する
Behavior Treeの内容ですが、普段はMonsterのように一定の範囲を歩き回ったり止まったりします。
Playerの操作するキャラがTrigger Box内に入ると、立ち止まってPlayerの操作するキャラを見るようにします。
MonsterのBehavior Treeです。
これをそのまま利用します。
こんな感じで作成しました。
NPCの最初の位置を以下の方法で取得しようとしていますが、出来るのか不明です。
ちょっとテストしてみます。
駄目みたいです。
うーん。AI ControllerからそのAIを使用しているCharacterを呼び出すノードが有った気がしますが覚えていません。
探したんですが見つかりません。
以下の方法で代用しました。
まずMYNPC_AIControllerにVector型の変数FirstPlaceを作成します。
更にBlackboardクラスのVector型の変数であるFirstPlaceにMYNPC_AIControllerの変数であるFirstPlaceの値をCopyするEventを作成します。
NPC_PersonのBPでMYNPC_AIController のFirstPlaceにNPCの位置をセットします。
セットが終わったら先程作成したEventを呼びます。
これで代用します。
最終的にはNPCも動的にSpawnさせる事になるはずなので、結局これは仮の処置になりますので、今回はこれで行きます。
テストします。
それぞれのNPCがそれぞれが配置された場所を保持しているのが確認とれました。
<NPCが移動する所を確認する>
Nav Mesh Volume Boundを置いてNPCが移動するか確認します。
全然移動しません。
Debugします。
Decoratorである“Is Random Place”の変数を作成していませんでした。
直しました。
テストします。
移動はしますが、地面をSlideしています。
NPCのAnimationを作成していなかったです。
先に、PlayerがNPCと会話出来る距離に近づいた場合、Playerの方を見て待つ部分の実装をします。
以下の部分です。
Blackboardクラスに新しい変数、PlayerCharacterを作成します。
Find Player Serviceの
Player ObjectにPlayerCharacterをセットします。
更にRotate to Face BB entry の
Blackboard KeyにPlayerCharacterをセットします。
テストします。
近づくと王様はこっちを振り返って見つめて来ました。
出来ています。
<NPCが散歩中にPlayerと遭遇したら散歩を中止してPlayerの方を見るか確認します>
今、NPCが散歩しています。
途中でPlayerの操作するキャラが近づいてきました。
散歩を中止してPlayerの操作するキャラを見るTaskを実行し始めました。
出来ています。
4.3 Animationを追加する
何と、NPCのAnimationの作成方法をすっかり忘れてしまいました。
これです。
うーん。Animationの勉強もしないといけないんでしょうが、今回は付け刃ですましたい。適当に調べて作成します。
5.NPCのAnimation BPを作成する
5.1 復習します。
取りあえずMonsterのAnimation BPをみて復習します。
これです。
しかし自分で作成しているにもかかわらず、何で全く覚えていないんでしょうか?
AnimGraphを開きました。
Defaultを開きます。
SPawnを開きます。
おお、段々思いだしてきました。このPlay Skeleton_Swordman_SpawnがAnimationを担当しているはずです。
やっぱりそうでした。以下のAnimation_squenceが呼ばれていました。
しかしNPC用のAnimation_squenceは以下のヤツが一個あるだけです。
これをどうやって作ったのかを調べる必要があります。
<NPC用のAnimation_squenceの作成方法>
NPC用のAnimation_squence は2021-09-12のBlogで作成しています。
NPC用のThirdPersonIdleの作成方法を以下に整理します。
<<Third Person Idleの作成方法>>
を選んでRetarget Anim Assetsを選びます。
多分、これですね。
すると以下の様なWindowが開きます。
ここで、UE4_Mannequin_Skeletonのポーズを以下の様に変更します。
Retargetボタンを押します。
これでNPC用のAnimation_squenceが出来るそうです。
思い出して来ました。
これはどこかのTutorialを見ながらやったんです。2021-09-12のBlogをよく探したらありました。Skeleton Assets: Anim Retargeting Different Skeletons | 03 | v4.8 Tutorial Series | Unreal Engine [6] です。
ぱっと見ましたが、前回これらの設定は行っているはずなので多分ほとんどの事はやらなくて良いはずです。
5.2 Third Person WalkからNPC用のAnimation_squenceを作成する
Retarget Anim Assetsを選択します。
思った通り全部設定されています。
前回やったようにRetargetをクリックします。
出来ました。
こんな感じです。
NPC用のAnimation_Sequenceはこの二つで十分なはずです。
5.3 NPCのAnimation BPを作成します
Animation BPからSK_Character_Fantasy_Skeletonを選択して
NPC_AnimationBPを作成します。
NPC_AnimationBPのAnimGraphを開いてState Machineを追加します。
名前はMonsterのAnimation BPの時と同じ、Defaultにしました。
Defaultの内部はMonsterのAnimation BPのIdle/Runだけが必要なので
以下の様に作成しました。
MonsterのAnimation BPのIdle/Runを開くと以下の様な実装がされています。
変数のSpeedの値ですが、MonsterのAnimation BPのEvent Graphを開くと以下の様な実装で指定されています。
SkelSword1D1ですが、
BlendSpace1Dから作成されています。
これにSpeed変数をパスする方法が良く分からないです。
中を開くと横軸がSpeedになっているので
これが入力値になっているのでしょうか?
うん。
多分そうでしょう。
良しこれを真似てNPC様に同じものを作成します。
NPC用の走っているAnimation_squenceを作成しました。
多分、NPCが走る事はないと思いますが、折角、BlendSpace1Dから作成するので走るAnimationも追加しておきます。
BlendSpace1DからNPC用のIdle/Runを作成しました。
Axisの設定はMonsterのAnimationで使用されているSkelSword1D1と全く同じです。
それぞれのAnimationをGraph上に配置しました。
これでNPC用のIdle/Run用のAnimationは完成ですね。
こんな簡単でしたっけ。
前やった時はえらい苦労した記憶がありますが。
まあ、私の実力が向上したと考えて先に行きます。
NPC_AnimationBPのIdle/Walk Stateを開いて
以下の実装をします。
更にNPC_AnimationBPのEvent Graphを開いてSpeed変数に値をセットします。
Monsterでやったやり方と全く同じです。
NPC_Person BPに戻ってAnimationの設定を行いました。
これで全部出来たはずです。
5.4 NPCのAnimation BPのテストとDebug
テストします。
結果のScreenshotです。
移動する時にきちんと指定したAnimationで移動しています。
そこは大成功です。
Debugする必要はなさそうです。
しかし思いっきり走っています。ここはNPCなのでゆっくり歩いてほしいんです。これは来週直します。
今週のNPCのAIの作成はここまでです。
6.Game Design:ポケモン+HxHの念能力( 戦闘システムの作成)
先週、考えてた戦闘システムのプロトタイプを作成します。
6.1 ターン制の戦闘システムの構築
に載っている通りの戦闘システムを作成する事も考えたんですが、試作段階にUE4C++ばかりか普通のC++まで使用するのはオーバーキルな気がします。のでこの本で紹介されているターン制の戦闘システムの構造だけはそのままにして全部BPで作成します。
この本では戦闘システムを複雑な方法で作成していますが、結論で言えばターン制の戦闘は以下の5つの状態で構成されています。
最初の状態である行動を決定する状態、2番目の状態である決定した行動を実行する状態、それによる結果(勝利、敗北、逃走)です。
これに敵と自分のターンが加わります。
ので、以下の様に改良します。
- 先攻後攻を決める
- 先攻が次のターンの行動を決める。
- 後攻が次のターンの行動を決める。
- 先攻が1で決めた行動を実行する。
- 後攻が2で決めた行動を実行する。
- 勝負がつくまで1~5を繰り返す。
- 勝利、敗北、逃走のどれかになる。
これで試しに作成する事にします。
<先攻後攻を決める>
これは端にRandom で決定して良いでしょう。試作ですし。
対戦型にして2人で戦うのか?AIと戦うのかについても考える必要があります。取りあえずはAIと戦うようにします。
<先攻が次のターンの行動を決める>
先攻がAIの場合と人の場合があります。この行動を決定するのは先攻か後攻かより、AIかそうでないかが重要ですね。
<<先攻がPlayerの場合>>
盤上に存在する全ての見方の行動を決定する必要があります。
<<<魔術師の場合>>>
魔術師の場合は、先週考えた通り、
の魔法から選択する事になります。
<<<召喚したモンスターの場合>>>
取りあえず召喚したモンスターがとれる選択は魔法攻撃、通常攻撃、魔法防御、通常防御位にします。Monsterは戦闘が開始するまでに勝敗が決定する戦略的な戦闘を担当するので、戦闘時の選択で勝敗が決定する要素はなるだけ避けたいです。
<<先攻がAIの場合>>
先攻がAIの場合は、Monsterのみが存在している場合と魔術師が存在している場合で違います。
Monsterのみが存在している場合は、Monsterが魔法攻撃、通常攻撃、魔法防御、通常防御のどれかを選択します。
魔術師が存在している場合は、Playerの選択と全く同じです。
<後攻が次のターンの行動を決める>
先攻で話した内容と全く同じ事をします。
<先攻が1で決めた行動を実行する>
魔術師がMonsterを召喚したり、召喚されたMonsterが攻撃をしたりします。
<後攻が2で決めた行動を実行する>
先攻で決めた内容と同じ事をします。
<勝負がつくまで1~5を繰り返す>
魔術師のHPを1500としてそれが無くなったら敗北にします。敵がMonsterしかいない場合は、敵のMonsterを全滅したら勝ちにします。
<勝利、敗北、逃走のどれかになる>
勝利の時は、報酬が貰え、敗北の時はGame Overです。逃走はGame Overにはならないですが報酬はもらえません。
6.2 魔術師やMonsterのParameterの作成
「6.1 ターン制の戦闘システムの構築」のみを決定したらすぐに試作品の作成に入れると思ったら、戦闘の勝敗を決定するためには魔術師やMonsterのParameterを考える必要がありました。
<MonsterのParameterについて>
HPとタイプが必要です。後、戦闘力もです。この3つがあれば最低限の戦闘が可能と考えています。
- タイプ
- HP
- 戦闘力
<魔術師のParameterについて>
魔術師は魔法を使用するのでMPが必要です。Monsterと違い直接戦う事はないのでタイプと戦闘力は要りません。
- MP
- HP
6.3試作について
取りあえずこれだけ決定しておけば戦闘システムの試作は出来そうです。一週間、このアイデアを寝かせて来週から試作品の作成にかかります。
7.Map1のBug直しの続き
7.1 最初の村で買える武器や道具の種類を減らす
村や町は行ったり来たりする予定なのでどの村の武器屋でもどんな武器でも買えるが買う為には資格が要る形にした方が良いと思っています。
職業によって買える武器が変わるのは現実的です。
Playerの操作するキャラのParameterの一つにOccupationがあります。
現在、Playerの操作するキャラのParameterの初期値を管理しているData TableであるYour Hero Classesには
一個しかデータがありません。
Playerの操作するキャラの3D モデルに使用しようしているModular RPG Heroes Poly artには以下のモデルが存在しています。
これらを整理して職業を決定します。
そしてそれらの職業に対応してこれらの武器の使用権限も決定する事にします。
こういうGame Designをある程度最初に決めておかないと何をProgrammingすれば良いのかも決まらなくて堂々巡りしてしまう訳ですね。
Game Designに関しては普通のProgrammerは勉強した事はないですし、どう勉強すれば良いのかも分かりません。
Game Designを担当する人達はGame Plannerと言うらしいですが、Game Planerが書かれた日本語の本を何冊か読みましたが、とても教科書として読める内容ではなかったです。これは英語の本でもそんなに変わらないみたいです。ただ全ての教材が駄目と決まったわけではなく中には凄い本がある可能性はあります。
私が言える事が一つあるとすればGame Designは必ずAlgorithmに変換する必要があります。それが出来ないとProgrammerはどうCodeに落とせば良いのか分かりません。だからGame Plannerは実際にCodeを書く必要はないですが、Game Plannerが作成するGame Designは必ずAlgorithmに変換できる必要があります。
ここでProgrammingを書いた事が無い人が作ったGame DesignがAlgorithm化出来る訳ないだろうと言う当然の帰結が判明します。
つまり、現在の風潮であるGame PlannerはGameを沢山Playした人で、DesignやProgrammingが出来なくても良い。みたいなのは完全に間違っています。
7.2 武器の種類を整理する
<弓矢>
弓矢は女子にも扱える強力な武器です。狩人が獲物を捕らえる時にも使用します。
<剣と盾>
剣と盾は沢山の種類があります。
木の盾や短剣は誰でも買える、鉄の剣や鉄の盾は騎士だけが買える、魔法の盾や魔法の剣は魔法戦士だけが買えると言うような分類が出来ると思います。
<杖>
杖は当然、魔術師のみが装備出来ます。
<斧、Hammer>
斧やハンマーは力が強くて強健な戦士が使用する専用の武器のイメージがあります。
以上です。
7.3 職業を決める
上記の武器、防具の関係から必要な職業が大体判明しました。
<初級者>
初級者が使用出来る武器は以下の2つです。短剣(小)と短剣(大)です。
さらに以下の2種類の木の盾が使用出来ます。
初心者の見た目は、
です。
<狩人>
狩人が使用出来る武器は弓と矢です。
弓と矢は強力な武器なので狩人の資格がある人だけが装備出来ます。
以下の3Dモデルが狩人っぽいです。
<戦士>
戦士は力が強く、戦闘の専門家です。普通の人には扱えない重たい武器を使用してMonsterと戦います。
使用出来る武器はAxeやHammerです。
AxeやHammerは重いので両手で扱う事にします。丁度両手用のMotionもありますし。
3Dモデルは以下のHeavy Knight SKを使用します。
<騎士>
騎士は位が高く、鉄の武器を携帯する事が許されています。以下の武器を装備する事が出来ます。
うーん。最後の剣と盾を魔法戦士用に残しておくと盾が一個余ってしまいますね。
Shield 03SMは戦士用の盾にした方がバランスが良いかもしれません。
見た目は以下のModelを使用します。
どことなく高貴な雰囲気がします。
<魔術師>
魔術師の装備は杖のみです。
杖のMotionは以下の物を使用します。
見た目は
にします。
<魔法戦士>
魔法戦士は魔法の剣と魔法の盾を使用出来る最上級の職業です。
見た目は以下の3Dモデルを使用します。
これで売れる武器の分類が出来ました。
7.4 職業のDataを追加する
以下の様に職業を追加しました。
このDataを読み込む箇所を全部抜き出します。
このGame CharacterクラスのCreateYourHero()関数で使用しています。
ここで大切なのはPlayerRowNameを使用してこのDataTableのRowを読んでいる所です。
そしてそのPlayerRowNameにはS1が使用されています。
ここでも使用されています。
DataTableのRow Nameは変更していないのでこれらの実装で破綻が生じる事は無いと思います。
検索で引っかかったのはこれだけでした。
このGameInstanceクラスのInit()関数はGameを開始した時の読み込みに使用するだけのようです。もうこっちの仕組みはすっかり忘れてしまいました。
転職の仕組みは後で考えるとしてテストしています。
何の問題もなくYourHeroClassesのDataTableのDataが読まれています。
それより大変なバグを発見してしまいました。
道具袋では以下の様に表示されていますが、
装備品では以下の様に日本語で表示されています。
後、職業はどこにも表示されていませんね。
7.5 Pause画面の直し
これも直します。
Pause画面ではPlayerの操作するキャラのParameterは全部表示されるようにします。
以下のParameterです。
このGoldだけは使用していないので、他のParameterは全て表示するようにします。
まずこれらの日本語の名称を考えます。そしてそれらを統一して表示するようにします。
<Player Name>
「名前」にします。
<Occupation>
「職業」にします。
<MHP>
「最大生命値」にします。
<MMP>
「最大魔力値」にします。
<HP>
「生命値」にします。
<MP>
「魔力値」にします。
<ATK>
「攻撃値」にします。
<DEF>
「防御値」にします。
<LUCK>
「幸運値」にします。
<XP>
当然「経験値」にします。
<LV>
「レベル」にします。
直しました。
Backの絵が歪んでいます。別な絵に変更しました。
うーん。後ろの絵がこの作品のイメージに合わないです。
道具袋や装備品も直します。
装備品は取りあえずこのままにしておきます。
キリが良いので残りは来週やる事にします。
8.UE5:naniteの勉強
先週の続きで公式のDocumentであるNanite Virtualized Geometry [7] を読みます。
番号が先週と違うと混乱するので番号は先週の続きで書きます。
7.3 How does Nanite work?
ここでは2つの状態におけるNaniteの働きについて解説しています。その2つとはMeshをUE5にImportする時とRenderingする時です。
<Importing Mesh>
このDocumentによるとMeshをUE5にImportする時に三角の塊に分解するそうです。
元々、Meshって三角の塊じゃないのと思うんですが、どう違うんでしょうか?
後、これ読むとMeshをImportする時にNaniteを使用するための何かをする必要がありそうです。
<Rendering>
Play中のmesh内の三角の塊はカメラからの距離に比例して色々なサイズのLODに変更されるそうです。
これはDemo画面でも見ました。
以下に示したような画面表示に変更されて
点々の部分のサイズがカメラが近づくと変化していくやつです。
多分これの事を言っているんでしょう。でもこの点々、三角形には見えない気がします。三角形の塊が色で表されているんでしょうか。
この後で、
- この三角形の塊はカメラからの距離によって形を変化させるにもかかわらず常に回りの三角形の塊と滑らかに繋がるとか
- On DemandでDataが流れて来るのでCameraに写っているLevelの細かさをRenderingするのに必要なDataしかMemoryに保持していない。
などのNaniteの特徴が説明されています。
これらの事が可能になっているのはNaniteが今までのDraw Callとは全く別のRendering方法を採用しているからだそうです。
おお。
UE5でNaniteを扱うのにNaniteのRendering方法を勉強する必要はないと思いますが、単純に興味があります。その辺の情報も少し提供してほしいです。
例えばGlobal Illuminationとかだと関連する沢山の論文が発表されているじゃないですか。そういうのってNaniteのRenderingにもあると思うんです。その辺の情報がほしいです。
7.4 What Types of Meshes Should Nanite Be Used For?
はい。
Rigの入っている歪みが出来るSkeletal MeshにはNaniteは使えません。
と思ったら全然別な話が書かれていました。
ここではSkeletal Meshに関する話はなくてどんなMeshに対してもNaniteは使えるけど特に以下の3つの場合に特に使えます。みたいな話が書かれていました。それぞれの場合について考察します。
成程。Z-Brushなんかで作成したMeshは非常に細かいMeshがあちこちに存在してそうです。
そういう3d ModelをそのままUEにImportすると細かいMeshの部分のCostも大きなMeshと同じ位のCostがかかって見た目以上の重さになっていた訳ですね。それをNaniteが解消してくれる訳ですね。
先週のBlogで
と書きましたが、Hierarchical Instanced Static Mesh Component を使用してMeshのInstanceをVideo Card内で複製すると滅茶苦茶Costが低く出来、何万個のInstanceを生成してもそんなにCostがかからないそうなんです。
NaniteのRenderingはこれを同じ事を自動でやっているんじゃないでしょうか?それならInstanceを沢山配置してもCostがほとんど無料みたいになってもオカシクはないです。
ただ現実のLevel Designで岩とかの配置は良いんですが、木はどうなんでしょうか?
木は風が吹くと歪みます。Naniteの適用範囲外な気がします。
そういえばUE5のDemoも木のない砂漠で行われていました。この辺のNaniteが適応出来る境界についてはしっかり理解しておくべきですね。Naniteが効くと思って木を何万本も配置したら駄目でしたってなったら大変ですから。
このOccluderの意味が分かりません。
OccluderってGoogleで検索すると以下の様な視力検査に使用する目を隠す棒が出て来ます。
当然ですがこの文脈においては、この視力検査の棒の意味では使用されていません。
Occluderの元になっていると思われる単語、Occludeは止める、とか流れをブロックするみたいな意味の動詞です。
更に3D Graphicsで良く使用されるAmbient OcclusionのOcclusionも止める、とか流れをブロックするみたいな意味があり、こっちは名詞です。ただしAmbient Occlusionのように3D Graphicsの世界で使用された場合、Occlusionは特に光の進行をBlockすると言う意味に限定して使用されている気がします。
これらの事を考慮するとこの文章におけるOccluderの意味は「遮蔽物」ぐらいが適当だと思われます。
ただ何を遮蔽するのかが分かりません。単純に考えればDataの読み込む流れを遮蔽する、もっとも複雑な形で大量のDataを持つMeshを指していると考えられます。しかし3D Graphicsの世界ではOcclusionは特に光の遮蔽に関する事に使用されるのでひょっとすると光を遮蔽するMeshに対して言っているのかもしれません。あるいは全く別にCameraに対しての遮蔽物を指している可能性もあります。
この節の感想は以上になります。
7.5 Enabling Nanite Support on Meshes
ここでは具体的にMeshをUE5にImportする時にどうすればNaniteが使用されるMeshに変換されるのかについての解説がされています。
<Importing a Static Mesh>
やり方は公式のDocumentのこの項を見ればわかるので敢えてもう一回ここに書く事はしませんが、Documentで見るだけだと結構不安です。やっぱりこういうのは動画でみたいです。
<Batch Selection and Individual Assets>
こっちは何を解説してるのかと思ったら、既にImportしたMeshでNaniteにしなかったヤツをNaniteに変換する方法についてでした。
実際にNaniteを使用するとしたらこっちが主流になりそうです。
7.6 Supported Features of Nanite
ここで(現状の)Naniteが使用出来る場合と出来ない場合についての詳しい解説がされています。
<Geometry>
(現状の)Naniteが使用できるMeshは以下の4つだそうです。
Hierarchical Instanced Static Meshがしっかり入っていますね。Geometry Collectionが何なのかは分かりません。
その下にしっかり解説されていました。現状、Naniteが使用出来るのはRigidなMeshだけでDeformationするMeshに関しては静的、動的に関わらず使用出来ないと。
次の文が一寸意味不明です。
直訳するとこうなります。
これはNaniteのMeshの位置(情報)は、ある意味、Mesh全体の位置に対して一個の4x3の行列を掛けただけで表せる位置(情報)より複雑であると言う事です。
普通、頂点の位置を表す行列は(x,y,z,w)でxyzで三次元状の位置を表し、うろ覚えですがWは位置なら0、Vectorなら1を指定しているはずです。この位置を移動するのに行列を掛ける訳です。
これは最近、散々勉強しているMaterialのTextureの回転なんかもそうです。2021-10-31のBlogを見ると、頂点(vertex)を回転させるためには、以下の行列を掛けています。
あれ、この例だとWに1が入っていますね。Wの値は位置なら1、Vectorなら0だったかもしれません。
兎に角、こういう行列を掛けてMeshの位置に移動、回転、拡大縮小などの干渉をする訳です。
この事を言っているのかと思って読んでいると、4x3の行列を掛けてと言っています。上記の様にMeshの位置に移動、回転、拡大縮小などの干渉をするは4x4なんです。
しかもここでa single …と「一個の…」とわざわざ強調しています。
更に前の文章との繋がりも不明になります。
前の文章で、現状、Naniteが使用出来るのはRigidなMeshだけでDeformationするMeshに関しては静的、動的に関わらず使用出来ないと言っています。ので当然次の文ではその説明が来るはずです。
この文に対する説明が、
これはNaniteのMeshの位置(情報)は、ある意味、Mesh全体の位置に対して一個の4x3の行列を掛けただけで表せる位置(情報)より複雑であると言う事です。
だとするとNaniteの位置情報は、普通のMeshと違って、一個の4x3の行列を掛けただけで表せる位置(情報)より複雑だからDeformationするMeshに関しては静的、動的に関わらず使用出来ないんです。となります。
この解釈が合っているのか間違っているのか判断出来る情報は全くないです。
まあでも間違っていると断定出来る情報もないですし、意味が分からないとしか言いようがないですね。
今度は以下の物にはNaniteは使えません。と説明されています。
Skeletal AnimationとMorph Targetsは前から聞いていた通りです。World Position Offsetを使用しているMaterialに対しても使用出来ないのはびっくりです。使用するMaterialによってはNaniteが使えなくなるんですね。Normal Mapはどうなんでしょうか?最後のSpline Meshは何の事を言っているのか分かりません。いや正確に言えばContent Exampleの展示のどこかで見た記憶はあるんですが、何を指しているのかまでは思い出せません。
Skeletal AnimationとMorph Targetsに関しては将来的にはSupport出来るようになるんでしょうか?それともNaniteの構造上、歪みを生じるMeshには元から効かないんでしょうか?その辺が知りたいです。
更に現状のNaniteでは以下の2つに対しても効かないそうです。
まあ、これは近い将来に解決されるみたいなのでどうでも良いです。
<Materials>
以下のMaterialの機能を使用した場合、Nanaiteは使用出来ないそうです。
ほとんど全部じゃねーか。
いやでもそうでもないですか。
Two Sideが使用出来ないのはきついかもしれませんね。木の葉なんかTwo SideとMaskの両方を使用してそうですが、木や草は無理って事ですね。
<Rendering>
色々なRenderingに対してこれらのRenderingにはNaniteは使用できません。とありますがそこに登場しているほとんどのRenderingが初めて聞くものです。
後で色々なRenderingを使用する時になった時に確認する事にします。
<Supported Platforms>
Naniteが使用出来るPlatform一覧です。
やっぱりPS5が入っていますね。
今週のNaniteの勉強はここまでとします。
やっぱり木や草の作成にNaniteは使用出来なそうですね。
9.まとめと感想
今週はRPGの作成が結構進みました。本当のGame Designと単なる空想の違いが分かって来ました。
10.参照(Reference)
[1] CGHOW. (2021, November 22). HLSL Triangle code to UE4 Material nodes Tutorial | Download Files [Video]. YouTube. https://www.youtube.com/watch?v=JUnjDu33Nq8
[2] Epic Games. (n.d.-a). Math Expressions. Unreal Engine Documentation. Retrieved December 19, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Materials/ExpressionReference/Math/#frac
[3] Epic Games. (n.d.-c). Texturing. Unreal Engine Documentation. Retrieved December 19, 2021, from https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Materials/Functions/Reference/Texturing/
[4] CGHOW. (2021b, December 4). Flower Effect in UE4 Niagara Tutorial | Download Files [Video]. YouTube. https://www.youtube.com/watch?v=37g1J8mImjg
[5] Cloward, B. [Ben Cloward]. (2021, December 2). Swizzle & Channel Manipulation - Shader Graph Basics - Episode 25 [Video]. YouTube. https://www.youtube.com/watch?v=hxIl52S-hzM&list=PL78XDi0TS4lEBWa2Hpzg2SRC5njCcKydl&index=25
[6] Epic Games [Unreal Engine]. (2015, September 28). Skeleton Assets: Anim Retargeting Different Skeletons | 03 | v4.8 Tutorial Series | Unreal Engine [Video]. YouTube. https://www.youtube.com/watch?v=xy9aLbZLdeA
[7] Epic Games. (n.d.-b). Nanite Virtualized Geometry. Unreal Engine Documentation. Retrieved December 19, 2021, from https://docs.unrealengine.com/5.0/en-US/RenderingFeatures/Nanite/