Gaming Life

一日24時間、ゲームは10時間

MagicaVoxelで作成した3DモデルをBlender経由でUE4に持っていく方法・改良版2

注)今回紹介する方法もモデル次第では問題が発生する可能性があります。

前回までの振り返り

 二回に渡りMagicaVoxelで制作したモデルをBlender経由でFBXを作成する方法を模索中。前回までの方法では影の付き方が変になってしまっていた。

ai-gaminglife.hatenablog.com

ai-gaminglife.hatenablog.com

改良版・UE4にボクセルモデルをインポートする方法

  1. この手法ではMagicaVoxelで制作したモデルをPly形式で書き出す。

  2. Blenderにplyでインポートする。

  3. 編集モードに切り替え。「A」キーを二回押して全ての頂点を選択したらツールシェルフ -> 重複頂点を削除を選択。

f:id:ai_gaminglife:20180118135831p:plain

  1. データ -> UVマップの右側にある + をクリック。これで新しくUV情報を持つことができる。

f:id:ai_gaminglife:20180222180341p:plain

  1. 「U」キー -> スマートUV展開を選択。島の余白を1.00に設定する。

  2. fbx形式でエクスポートする。

  3. UE4にモデルをインポートする。この時 Vertex Color Import Option を Replace に設定する

f:id:ai_gaminglife:20180222180359p:plain

  1. UE4上でマテリアル「M_VColor」を新たに追加する。マテリアルノードは以下のように設定。

f:id:ai_gaminglife:20180222180411p:plain

  1. インポートしたモデルのマテリアルを「M_VColor」に切り替える。

  2. LightMap Resolutionを256に設定。

f:id:ai_gaminglife:20180222180422p:plain

 完成!

f:id:ai_gaminglife:20180222180432p:plain

UE4 ForLoopwithBreakの改造(デクリメントとDelayを実装)

 超小ネタ。以前の記事で「For Loop With Delay」マクロを自作したが、

ai-gaminglife.hatenablog.com

これに加えてBreakとデクリメントでループを回す必要がある場面に遭遇したので「For Loop With Break and Delay Decrement」マクロを自作した。

f:id:ai_gaminglife:20180219161704p:plain

 ForLoopをグラフに配置してダブルクリックするとStandardMacrosのBPを見ることができる。今回はそれを見ながら実装した。StandardMacrosには他にも FlipFlopやDoOnceといったFlow Control系のマクロ、一部のMathマクロの中身が見ることができる。一度見ておくといいのかも。

MagicaVoxelで作成した3DモデルをBlender経由でUE4に持っていく方法・決定版(にしたかった)

 前回の記事 ではply形式でexportし、スマートUV展開して頂点カラーを焼き込んでテクスチャを作成、そのテクスチャとfbxで書き出したモデルを取り込むという手法を紹介したが、この方法では色とUV座標がズレが生じ、色の位置がずれてしまう問題が発生していた。

ai-gaminglife.hatenablog.com

 消化不良のまま前回記事を書いた後に大学のテストがありずっと解決できずにいたが、テストも終わり、漸く(とりあえずの)解決策が見つかったので紹介する。

Blenderでの設定方法(決定版にしたかった)

 今回はMagicaVoxelで作成したモデルを obj形式でexport する。

 前回記事同様にBlenderにImportしてライティングとサイズを調整する。

サイズ調整の方法
UE4.18.2時点ではBlender上での1mはUE4では100mになっている。これはシーン設定の単位プリセット、長さをメートル法に、単位の倍率を0.01にすることでBlender上での大きさとUE上での大きさを揃えることができる
f:id:ai_gaminglife:20180212164316p:plain

 作業し易いように3Dビューを左上の三角を左にスライドし、2画面にする。続けて左画面の左下にあるアイコンを押し、表示を「3Dビュー」から「UV画像エディタ」に切り替える。

f:id:ai_gaminglife:20180212164328p:plain

 「+新規」を押し、「Lightmap」と名付ける。

 f:id:ai_gaminglife:20180212164343p:plain

 モデルを選択し、オブジェクトデータ→UVマップの+を選択。新たに作られたUVMap_001の右側にあるカメラマークを選択状態にする。

f:id:ai_gaminglife:20180212164410p:plain

 tabを押して編集モードに切り替え。Aキーを二回押してモデルの頂点を全て選択する。

 左画面にLightMapが表示されていることを確認してから(真っ黒の正方形が表示されていればいい。されていなければ「画像」のすぐ右側にあるアイコンを選んでLightMapに切り替える)Uキー→スマートUV展開と進み、島の余白を0.05程度にして実行。

f:id:ai_gaminglife:20180212164427p:plain

UE4にインポートする

 前回同様fbx形式でエクスポートする。終わったらfbxをUE4にImportする。この際、Generate Lightmap UVsにチェックが入っていることを確認する。

 自動生成されるマテリアルの名前が必ずpaletteになっているはずなので適切な名前に書き換える。こうしないと同じフォルダにボクセルモデルをインポートする時マテリアルが上書きされてしまう。

 このようにインポートしたモデルは色のズレもなく、Light Buildしても真っ黒にならず影がつくはず。

f:id:ai_gaminglife:20180212164440p:plain

 おわり。

解決できなかった問題点

 上の画像を見てもらうと分かる通り、気味の悪い影の付き方をしている。「Movable」に設定した時の影(下画像)は違和感がないのだが、Staticなのに何でもかんでもMovableに設定するのもよろしくない。Staticに設定したときもMovableと同じ影の付き方に出来れば良いのだが……

f:id:ai_gaminglife:20180212164452p:plain

(02/22追記)改良版を公開しました。

ai-gaminglife.hatenablog.com

MagicaVoxelで作成した3DモデルをBlender経由でUE4に持っていく方法

 最近MagicaVoxelというボクセルモデリング(3Dドットモデリング)ツールで3Dモデルを制作している。Minecraft感覚でモデルを製作でき、BlenderやMayaと言ったDCCツールよりはるかに覚えることが少ないため、絵が全く描けない自分でも使いはじめて3時間で下部画像程度のクオリティのモデルを制作することが出来た。

 だがこのモデルをBlender経由でUE4にFBX形式でImportするのにかなり苦労してしまった(Blenderの使い方を理解していないせいであるのだが)。色々な人の力を借り、四苦八苦しながらなんとか出来た。そこそこの作業量が多く、すぐやり方を忘れてしまいそうなので、ブログにメモを残しておく。なお、この記事は こちらのブログ をかなり参考にしている。

 最も単純な方法

obj形式でexportしBlenderに取り込む

 MagicaVoxelで作成したモデルをobj形式でexportする

f:id:ai_gaminglife:20180118135634p:plain

 Blenderを開き、初期状態で配置されている立方体を削除する

 先程exportしたモデルをimportする。

f:id:ai_gaminglife:20180118135648p:plain

調整

 alt+Zでテクスチャを表示する……のだがこのままだと真っ暗になってしまう。

f:id:ai_gaminglife:20180118135717p:plain

 原因はライトの位置。右上でLampを選択し、3Dビューでモデルに光が当たるようにうまく配置する。

f:id:ai_gaminglife:20180118135729p:plain

 このままのサイズだとロクに使えないのでSキーを押しサイズ調整。調整が終了したらCtrl+Aを押し回転と拡縮を適用する。こうすることで今の回転を(0,0,0)に、拡大縮小を(1,1,1)にすることができる。

UE4にexportする

 ファイルからエクスポート->fbxを選択、設定は変更せず名前を付けて保存する。

f:id:ai_gaminglife:20180118135741p:plain

 UE4に移動、コンテンツブラウザに先程書き出したFBXをドラックアンドドロップでImportする。設定を変更せずに「Import All」を押すとモデルとテクスチャとマテリアルが自動生成される。

 完成。

問題点

  • 複雑なモデルの場合ポリゴン数が莫大に増える

f:id:ai_gaminglife:20180118135752p:plain

 今回使用した単純な人型位なら問題ないが上の写真くらいになると、ポリゴン数が約14000。流石にこれじゃロクにFPSがでない。

  • 後から質感の調整を掛けるのが難しい

 この方法でImportするとテクスチャにMagicaVoxelで使用したPaletteの色を左から帯状に並べたものが選ばれている。このままでは後からある部分だけ金属っぽい質感にしたいと言ったことが難しく取り扱いにくい。

  • Lightingがうまくいかない

 この方法ではLightingMapを持たないため、Staticだと影が焼き付き真っ黒になってしまう。Movableにすれば解決するのだがなんでもかんでもMovableにするのは問題。

問題点を解消した手法(ply形式でexportする)

Blenderに書き出し

 その後の最適化の都合でMagicalVoxelで作成したモデルを頂点カラーがついている形式であるply形式でexportする。

 Blenderを開き、初期状態で配置されている立方体を削除する。

 先程exportしたplyモデルをimportする。

調整

 alt+Zでテクスチャを表示。ランプの位置を3Dビューでモデルに光が当たるようにうまく配置する。

 Sキーを押しサイズ調整。調整が終了したらCtrl+Aを押し回転と拡縮を適用する。

頂点数を減らす

 編集モードに切り替えツールシェルフにある「重複頂点を削除」を押せば、重複している頂点を削除することができる。これでもまだ余計な頂点が存在するがその作業は後で。

f:id:ai_gaminglife:20180118135831p:plain

UV展開しテクスチャを作成する

 続けて「U」キー → 「スマートUV投影」を実行。

 画面上部「スクリーンレイアウトを選択」から、UV Editingを選択する。

f:id:ai_gaminglife:20180118135842p:plain

 UV展開されたテクスチャが左画面に表示される。左下の「新規」を押して、新たにテクスチャを作成。名前は適当に決めておく。

 スクリーンレイアウトをDefaultに戻す。プロパティウインドウ内、「レンダー」タブ内のベイクパネルを開く。ベイクモードを頂点色に変更し、ベイクボタンを押す。

f:id:ai_gaminglife:20180118135855p:plain

UV Editingレイアウトに戻ると、先程作成したテクスチャに頂点カラーが焼きこまれていることが分かる。

f:id:ai_gaminglife:20180118135906p:plain

 このテクスチャをUE4のマテリアルで貼り付けるので個別にpngで書き出しておかねばならない。UV Editingレイアウトの左下にある画像を選択。「画像を別名保存」を押すとpngで保存することができる。

 これで頂点カラーは必要なくなった為、削除する。

 編集モードで全ての頂点を選択してから、Spaceキーを押し検索バーに「頂点色を削除」と入力。実行することで頂点の色を削除することができる。

f:id:ai_gaminglife:20180118135915p:plain

頂点数を更に減らし最適化する

 「ポリゴン数削減」モディファイアを追加。

f:id:ai_gaminglife:20180118135925p:plain

 平面を選択し、適用。消してほしくない頂点が削除される場合もあるので要注意。

 可能ならここから手動で更に必要ない頂点を削除していく。

FBX Export

 File->Export->FBXを選択。設定は変更する必要はないはず。任意の名前を付け保存する。

UE4でテクスチャを貼り付ける

 ドラックアンドドロップで作成したテクスチャとFBXをImportする(設定は変更しなくて良いはず)。

 取り込んだpngテクスチャを右クリックし「Create Material」を選択。自動でマテリアルが作成される。

 作成したマテリアルをStaticMeshに適用すれば完成。面倒な作業だがここまでやれば描画負荷も高くなく、ライティングもうまくいっているはず。

f:id:ai_gaminglife:20180118140450p:plain

SkeletalMeshとしてImportする場合

 SkeletalMeshとしてImportするとどういうわけか全体的に丸い質感になってしまう。そうなった時場合は以下のようにImport Settingを変更してReimportすると治るはず。

f:id:ai_gaminglife:20180118140516p:plain

まだ残る問題点

  • 角を見ると他の場所の色がぼんやり滲んでしまっている。遠目で見ても気づくレベルでこれはよろしくない。

f:id:ai_gaminglife:20180118140538p:plain

 これはUV展開する際、自動で生成したため、ベイクした色矩形とUV座標が僅かにずれてしまうことに起因している。調べると、とりあえずの解決方法を発見した。

1. スマートUV展開をする際、「島の余白」を0.05に設定する。

2. 頂点色をベイクする際余白を1pxに設定する。

 これで解決。遠目で見ればこれで全く問題なさそう。

f:id:ai_gaminglife:20180118140853p:plain

 としたいところだが大きく拡大してみてみるとまだ多少のズレが認められる。

f:id:ai_gaminglife:20180118140907p:plain

 これを直す手段は分からなかった。これが自動でUV展開する限界か。Blenderに詳しい方に聞くと、「スクリプトを組めば解決するかも……」との話だが自分には出来ないので誰かやってください。

 以上。UnityにはVoxel Importerなるものがあるらしいが…UE4にもください。

(02/22追記)これらの問題を解決した改良版を公開しました。

ai-gaminglife.hatenablog.com

ai-gaminglife.hatenablog.com

 

TwinStickShooterテンプレートを使ってゲームを作った

 ここ数回のブログでちょっとずつ見せてはいたが漸くゲームが完成した。実質初めて自力で完成させたゲーム。

 見て分かる通り全く面白くないゲームだが一本通して作ることで、今まで良く分かっていなかったUE4の機能を色々勉強することができた。面白さはさておき、「遊べるゲーム」を一本作ってみるのは本当に勉強になると感じた。やらなければ始まらない。

遊び方

<基本ルール>

  • 操作はTwinStickShooterテンプレートそのまま。敵を全滅させると勝利。

  • 攻撃するにはエネルギーを消費し、ゼロになると回復するまで攻撃できなくなる。

  • 敵は数%の確率でHP回復アイテムもしくは3Way攻撃アイテムをドロップする。

  • 3Way攻撃アイテムを拾うと暫くのあいだ弾を同時に3個平行に飛ばせるようになる。

<敵キャラの行動パターン>

  1. 決まりきったポイントを巡回を巡回、プレイヤーを視界に入れるとその場で停止し視界から消えるまで攻撃し続ける

  2. ある範囲(BoxTrigger)をランダムに動き回る。プレイヤーを視界に入れるとプレイヤーのいる方向にいつまでもついていき攻撃し続ける

  3. ゲーム開始時から攻撃しながらプレイヤーの方向に進み続ける

 2と3のAIはビヘイビアツリーのSingle parallelノードを使って実装した。そのうちこれの記事書くかも。

反省

  • 3種類の敵エネミーを作るのにそれぞれCharacterを継承させて作ってしまったので、同じタスク(例えばプレイヤーの方向に向かって攻撃する)を実装するのにわざわざコピーして別のタスクを作り、Castノードを置き換えて…みたいな面倒なことをしてしまった。インターフェースやら親クラスを作っておけば多分こんなことをしなくても良かったと思う。しかしどうやればいいのかよく分かっていない(今必死に調べている…)。

  • ControllerとCharacterと発射する弾と機能の切り分けが下手くそで開発終盤どこに実装したか混乱してしまった。

  • 企画段階で練り込みが甘くあまりに面白くないゲームができてしまった。

まとめ

 何はともあれゲームを完成させることができてよかった。

UE4 UE4で偏りを持った乱数(正規乱数)を生成して敵AIのエイムを適度に散らしてみる

 マケプレのセールで買ったアセットが4.18未対応で泣いた。

 ブループリントで乱数を生成するには、Rand Float in Range 等を使う。で、この ブログ を見ると分かる通り、帰ってくる乱数は例えば1-10までの整数乱数を生成するとだいたいどの数字も同じ確率で出現する。これを一様分布に従う一様乱数って言ったりする。まあ読んで字の如くなので難しくはない。

 しかし一様乱数だけしかBPで使えないってのは不便。例えばコマンド式のRPGドラクエみたいな)でダメージ計算する時、計算結果に乱数を乗じて実際敵に与えるダメージに幅を持たせるといったことをするがこの時乗じる乱数が一様乱数だとどうも違和感が出てしまう。他にも敵キャラが自分に向けて銃で遠くから攻撃する場合、毎回正確にプレイヤーに弾が飛んできたらたまったもんじゃないので乱数を使って照準のズレをもたせたくなる。この場合も一様乱数を使うと外す確率も当たる確率も同じになってしまい、プレイヤーはこれなら殆ど弾飛んでこないし特攻しても大丈夫だろう、と思われかねない(勿論この心理を逆についてプレイヤーとの距離が閾値を超えたら乱数のレンジを狭めエイム精度を大幅に上げるみたいなことも有りだろうが)。

 というわけでゲームで使う乱数はある程度偏りを持っていてほしいとなるのである。それもある値が頻繁に出現する乱数が。

 で作り方。

f:id:ai_gaminglife:20171220212510p:plain

 Float型乱数を5個取ってきてその平均をとるだけ。これでMaxとMinのちょうど真ん中の値(Max100,Min-100なら0)付近が頻繁に出現し、MaxとMinに近づくほどその値の出現頻度が低い乱数が生成できる。

 これを応用してTwinStickShooterテンプレートの敵キャラAI(制作の様子は 過去ブログ 参照)。

f:id:ai_gaminglife:20171220212620p:plain

 このエネミーはプレイヤーの位置と自身の位置を取得してベクトル減算して攻撃の単位方向ベクトルを得ているのだが、この時使用するプレイヤーの位置ベクトルを「Break Vector」し、X座標の値だけ「GaussRandomFloatInRange」で取得した乱数(エイムの振れ幅)を足してベクトルに戻している。こうすることでエネミーの攻撃を「違和感なく」散らすことができた。


 UE4での偏った乱数の生成方法の話はおしまい。以下ちょっとしたなんでこうなるかの理論の話と本当に偏った乱数を生成できるのかExcelで実験する話なので興味のない方は読み飛ばして頂いて構いません。

なんで偏った乱数になるのか

 ここで擬似的に生成している乱数というのは正規分布に従う乱数、正規乱数と言われるもので、なぜこうなるか説明するには中心極限定理やら大数の法則の話をしなきゃならない。更にいうともっと正確な(厳密に正確ではない。PCで作る乱数はあくまで擬似的なもので真に正しい乱数は作れない)正規乱数を作るには一様乱数から正規乱数を取得できる Box-Muller法(wikipedia) を使ったほうがいいのだがlogやらcosやら出てくるのでBPで実装するのはよろしくない。こんな面倒なことをしなくてもC++の乱数ライブラリstd::random で正規乱数が生成できるらしいが現時点で筆者がC++を書けないのでこのやり方は説明できない(このせいでUE4ソースコードから乱数生成アルゴリズム読み解こうとしたのにさっぱりわからなかった。いつかリベンジしたい)。

 中心極限定理はざっくり言えば

X が平均 μ,標準偏差 σ のある分布に従うならば,大きさ n の無作為標本に基づく標本平均 は,n が無限に大きくなるとき,平均μ,標準偏差 σ/√n の正規分布に近づく。

 とのこと。わかり辛い。ようはある分布に従ってるサンプルを幾つか取ってきて得た平均を並べると正規分布っぽくなりますよって話。ここでは一様分布に従う乱数を5個取ってきて得た平均が正規分布に従っているように見えることを利用して正規乱数を得ていたのである。

Excelで検証

 UE4で検証した方が良いのだろうがBPで実装する時間がないのですぐできるExcelで検証してみた。

○ Rand()で生成した乱数10000個のヒストグラム

f:id:ai_gaminglife:20171220212645p:plain

○ ( Rand() + Rand() + Rand() + Rand() + Rand() ) / 5で生成した乱数10000個のヒストグラム

f:id:ai_gaminglife:20171220212657p:plain

 確かに正規分布特有の釣鐘型のヒストグラムが得られている。

あとがき

 まだまだUE4を触りだして間もないがBPは偉大だ。しかしやはりC++は知っていると便利。いつか勉強したい(するのだろうか)。

 ちなみに以前乱数について簡単なスライドを作成して公開したので寒いネタのオンパレードですが興味のある方は是非見て下さい。

ai-gaminglife.hatenablog.com

UE4 特定のStaticMeshをナビメッシュの計算対象外にする

 小ネタ。日本語情報が見当たらなかったのでブログに残しておく。

ai-gaminglife.hatenablog.com

 極め本22章23章でLevelに配置した TargetPoint を永遠に巡回するみたいなAIがあるが(上記過去記事参照)、StaticMesh コンポーネントを持った Pawn を件のAIで制御すると動きがおかしくなった。

 (録画ミスでラジオの音源入ってるけど許して)

 それもそのはず。StaticMesh は NavMesh の計算対象なので初期位置に TargetPoint を置くとそこは Actor が入れない場所になってしまい AI Move To が失敗してしまうから。

 これは StaticMesh コンポーネントの Colision -> Can Ever Affect Navigation のチェックを外せばいいだけ。こうすると

f:id:ai_gaminglife:20171217231104p:plain

 問題解決。


 UE4で制作しているというアークの新作格闘ゲームドラゴンボールファイターズの新PVが発表されましたが、あれは本当に同じエンジンを使っているのだろうか……当然専用ツールやエンジン改造をしてるでしょうがそれでも信じられない。レイヤーズストーリーゼロといい日本のゲーム会社からUE4で制作されたセルアニメ風の映像が沢山登場していて今後も楽しみ。和ゲーで育ってた人間なのでここ2年くらいの和ゲー大躍進が嬉しい。