Gaming Life

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

Pythonで二次元ランダムウォーク+matplotlib.animationのgif保存

 大学の講義にてPythonランダムウォークを実装するのに初歩的なところでハマったのでメモ。プログラムは以下の通り。

%matplotlib nbagg

# -*- coding: utf-8 -*-

# モジュールのインポート
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# メイン実行部
# 試行回数nの初期化
n = int(input("試行回数nを入力してください:"))

fig = plt.figure()
ims = []

x = 0.0
y = 0.0
# グラフ描画の準備
xlist = [x]  # x座標
ylist = [y]  # y座標
# ランダムウォーク
for i in range(n):
    x += (random.random() - 0.5) * 2
    y += (random.random() - 0.5) * 2
    xlist.append(x)
    ylist.append(y)
    im = plt.plot(xlist, ylist, marker='o', color = 'r')
    #im = plt.scatter(xlist, ylist, marker='o', color = 'r'
    ims.append(im)
# グラフの表示

ani = animation.ArtistAnimation(fig,ims,interval=100)
ani.save('test1.gif', writer='imagemagick')
plt.show()

f:id:ai_gaminglife:20180629172519g:plain

 引っかかったのは

im = plt.plot(xlist, ylist, marker='o', color = 'r')
#im = plt.scatter(xlist, ylist, marker='o', color = 'r'
ims.append(im)

のところ。今回はplotでアニメーションさせろって条件だったのでこれで上手くいくのだが、matplotlib.scatterでアニメーションさせる時は

ims.append([im])

と明示的にimをリストに変えなければならない模様。逆にplotの時にimをリストとしてappendすると上手く行かない。これはmatplotlib.plotの返り値が最初からリストになっているせい。

おまけ: Win10 × Jupyter Notebookでmatplotlib.animationの結果をgif保存する方法

 おそらく何も設定を変更せずani.save()しても MovieWriter imagemagick unavailable. などと表示され失敗すると思う。これは下記のサイトの指示に従って設定ファイルを変更すれば解決するはず。しかし、ウチの環境では Install-Package imagemagick が上手く動かなかったので こちらのサイト から直接インストーラーをDLした。

cartman0.hatenablog.com

イベントディスパッチャーを使ってUMGの文字を変える

前回の続き。

ai-gaminglife.hatenablog.com

 UMGの詳細パネルからプロパティに関数バインディングすると毎フレーム処理が走ってしまい良くない。今回はその一つの解決法。

イベントディスパッチャーを使って必要な時だけ関数を呼び出す

 今回はThirdPersonCharacterが持つInteger変数をUMGのTextに表示させるということをしてみる。

 UMGのDesigner編集画面でTextを追加。詳細パネルでIs Variableにチェックを入れると"TestTextBlock"をBP上で変数として扱うことが出来る。

f:id:ai_gaminglife:20180625233815p:plain

 ThirdPersonCharacterのBP編集画面を開き、Integer変数、testCountと、イベントディスパッチャー、ED_CountUpdateを追加。ED_CountUpdateの詳細パネルで画像の様にInputsを編集するとIntegerを入力に取るイベントをバインド出来るようになる。

f:id:ai_gaminglife:20180625233821p:plain

 ThirdPersonCharacterでは画像のようにBPを組む。キーボードのUを押すとTestCountがインクリメントされディスパッチャーが発行される単純なもの。

f:id:ai_gaminglife:20180625233829p:plain

 UMGに戻り、画像のような関数、SetTextBlock_Textを用意。

f:id:ai_gaminglife:20180625233837p:plain

 EventGraphでは次の画像の様にBPを組む。ThirdPersonCharacterでディスパッチャーが発行されたらEventCountUpadateが実行され、その中で先程作った関数が呼び出される。

f:id:ai_gaminglife:20180625233845p:plain

 いつもの様にレベルBPでUMGをCreateしAdd to Viewport。

f:id:ai_gaminglife:20180625233853p:plain

 実際動かしてみたのが以下。

f:id:ai_gaminglife:20180625233902g:plain

 TestCountが変更されたときだけディスパッチャーが発行され、UMGを更新することが出来た。

Event Constructの話

 最初、キャラクターのBPのEvent BeginPlayでディスパッチャーをCallしてSetTextBlock_Text関数を呼び出そうとした。

f:id:ai_gaminglife:20180625233946p:plain f:id:ai_gaminglife:20180625233949p:plain

 これでEvent BeginPlayが起きた時にディスパッチャーがCallされ、0で初期化できると思ったのだが……

f:id:ai_gaminglife:20180625234002p:plain

 0で初期化されない。OutputLogを見てみるとUMGのEvent Constructが呼ばれる前にキャラクターBPのEvent BeginPlayが呼ばれている。バインドする前にCallしてしまっているのが原因だった。

f:id:ai_gaminglife:20180625234012p:plain

 色々調べるとEvent ConstructはAdd to Viewportする時に呼ばれるものらしいが。現状これに対する解決策が浮かばなかったのでEventConstructで直接SetTextBlock_Textを呼ぶことで無理やり解決した。

UMGの詳細パネルから関数を作ってバインディングするのは良くない

 今日Twitterで教えてもらい知ったこと。下の記事でも使っているテクニックのUMG要素の制御関数を詳細パネルで作るのは良くない。

ai-gaminglife.hatenablog.com

 それを確かめるのに簡単なテスト。UMGを作成し、Textを配置、そこからバインディングする関数Get Text 0を追加してみる。

f:id:ai_gaminglife:20180624235124p:plain

 関数の実装はこんな感じ。関数が呼ばれるたびにPrint Stringするだけの単純なもの。

f:id:ai_gaminglife:20180624235131p:plain

 作成したUMGをレベルブループリントで追加してPlayしてみると

f:id:ai_gaminglife:20180624235141p:plainf:id:ai_gaminglife:20180624235143p:plain

 関数Get Text 0が毎フレーム呼ばれている!

 これまで何故かこの方法で作成した関数は参照した値が書き換わる時だけ呼び出されるものだと思っていた。よく考えれば毎フレーム呼ばれるのは当然の事。

 Event Tickが毎フレーム呼ばれると非常に処理が重くなるのはぷちコンの時に痛いほど学んだので、最近はCustom EventやPure関数、ディスパッチャーやEvent Begin Playで変数代入など色々工夫するようにしていたのだが思わぬところに落とし穴があった。こんな基本的な事見落としていたなんて……

 というわけでこれからはこの方法を使うのは(基本的には)止めていこう。

Blutilityで遊んでみる(2) UE4.20 コンテンツブラウザ上でアセットの詳細設定を一括で変更する

 以下の記事でボクセルモデルをFBXとして取り込む時、テクスチャの設定を

  • Compression -> Compression Setttingを "UserInterface2D"に変更

  • Texture -> Filterを "Nearest" に変更

  • Level Of Detail -> Texture Groupを "2D Pixels" に変更

の様に変更する必要があることがわかった。しかし毎回この設定を手作業でするのもめんどくさいよなーってことで、Blutilityを使って自動化してみた。

ai-gaminglife.hatenablog.com

実装

 Editor PrefernecesでBlutilityを有効化している事を確認し、Blutilityを作成。今回は親クラスにActorActionUtilityを指定する。これはUE4.20で追加予定の機能で、これを親に指定することでBlutilityをコンテンツブラウザ上から直接実行できるようになる。関数を作成しの画像の様なBPを組む。

f:id:ai_gaminglife:20180611184353p:plain

 Get Selected Assetsで選択したアセットを読み込み、Textureにキャストして設定を書き換える、いたって単純なBP。これでコンテンツブラウザ上で対象のテクスチャを右クリックしScript Actionから呼び出すことができるようになる。

f:id:ai_gaminglife:20180611184403g:plain

 これで設定を変更することができる……のだがここで問題発生。確かに設定は変更されているがBlutility関数「Change Voxel Setting」を実行することでテクスチャのボケが解消されるはずなのにされない。

 この問題はBlutilityを実行後Reimportを押すことで解決する。

f:id:ai_gaminglife:20180611184449g:plain

(GIF画像の為適用されてるのか分かり辛いのはゴメンナサイ…)

 せっかく自動化したのにReimportの手間がかかるのは残念だが現状BP上からReimportを掛ける関数がないようなので仕方ない。全部手作業で変更する手間を考えればよっぽどましと考えるしかない。  

Blutilityで遊んでみる(1) レベルエディタ上でActorのスケールを変更する

 先日UE4.20のPreview1が公開された。で、このverで前々から気になってたBlutilityの機能がちょっと拡張されたらしいのでちょっと遊んでみた。詳しい手順は以下の記事が分かりやすい。

qiita.com

unrealengine.hatenablog.com

anapurna.co.jp

 ざっくり説明するとエディタ上でブループリントを実行できるという機能。UI拡張は出来ないがC++を書かずにある程度の機能拡張ができるというのが魅力。まだまだ実験段階でやれる事は少ないが可能性を感じる。

 とりあえず今回はActorのスケール値を二倍or二分の一にする関数を実装してみる。

実装

 上記の記事に従いBlutilityを使えるようにし、コンテンツブラウザで作成。この時親クラスは 「ActorActionUtility」 とする。

 コンテンツブラウザ上で右クリック->「ブループリントを編集」でブループリントを編集できる。関数「ActorScale 2times」と「ActorScale oneHalf」を作成。

f:id:ai_gaminglife:20180611012629p:plain

 中身はこんな感じ。oneHalfの方は掛ける値を0.5に変更するだけなので省略。特に説明することのない基本的なもの。

 続いてこのBlutilityの対象をActor継承クラスだけに制限するために関数のオーバーライドで「GetSupportedClass」を書き換え。Return NodeにActorを設定する。

f:id:ai_gaminglife:20180611012640p:plain

 このBlutilityはレベルエディタ上でActor継承クラスを選択した状態で右クリック->Scripted Action で使用可能。実際使った様子がこちら。

f:id:ai_gaminglife:20180611012523g:plain

 詳細パネルでScaleを直打ちしたほうが早い気もするが、Actorを複数選択した状態でこのBlutilityを実行すればそれぞれのScale値を基準に二倍してくれるのでその点においては良いかも。ただしUndoが効かないのが難点。  

f:id:ai_gaminglife:20180611012700p:plain

 最初画像下の「Get Selected Assets」を使ってうまくいかなかったのだが、上の「GetSelection Set」に変更したら機能した。この2つの違いはよくわかってない。

 まだまだ実験段階であるが色々できそう。しばらくこれで遊んでみるかも。

MagicaVoxelで作成したモデルをUE4で利用する (2) StaticMesh編

[MagicaVoxelで作成したモデルをUE4で利用する (2) StaticMesh編]

はじめに

 この記事は前回の続きです。前回の記事から見ていただくことをおすすめします。

ai-gaminglife.hatenablog.com

 第二回ではボーンを入れずアニメーションさせない、StaticMeshとして書き出したいときの方法を説明する。完成形は以下の通り。

f:id:ai_gaminglife:20180609152443p:plain f:id:ai_gaminglife:20180609152418p:plain

 頂点数208、ポリゴン数104と十分ゲームに使える少なさ。UVテクスチャも書き出されているのでマスク用テクスチャを作って質感調整などもできる。

 なおこの記事は以前公開した記事と大部分内容が被っている。この後SkeletalMeshとして書き出す解説もする為、繰り返しになるが話をわかりやすくするためこの記事を書いている。

[被ってるブログ]

1.MagicaVoxelでモデルを作成しQubicle用にエクスポートする

 まずはMagicaVoxelでボクセルモデリング。本筋から外れる為MagicaVoxelの使い方の説明はしないが直感的に操作出来るようになっているのでそう難しくないはず。が、UE4に持っていくに当たり注意することが一点。モデルの中心とワールドの中心を揃えなければならない。これをしないと後々面倒なことになる。

f:id:ai_gaminglife:20180609152123p:plain


 モデル全体を移動させるには以下の手順を踏む。

  1. Viewの"Grid","Frame" を選択。これでワールドにグリッド線が表示される。

  2. EditパネルからSelect -> Allを選択。

  3. BrushパネルのPaintの下にある十字矢印マークを選択。モデルを移動させることが出来る。

f:id:ai_gaminglife:20180609152136g:plain

 本当に真ん中か不安になったらMirrorをONにし、PaintやAttachしてみて試してみるといい。


 モデルの中心を揃えたらエクスポート。今回はQubicle独自形式の.qbで書き出す。

 右下のExportから"qb"を選択し、任意の場所に保存する。これでモデルをQubicleに持っていくことが出来る。

2.Qubicleで調整する

 Qubicleを起動。初期画面左下のファイルのアイコンをクリックし、先程エクスポートした.qbファイルを選択する。

f:id:ai_gaminglife:20180609152159p:plain

 .qbファイルを開くとこの様に中心と向きがずれている。

f:id:ai_gaminglife:20180609152207p:plain

 というわけでこれを直す。左クリックでオブジェクトを選択し、Transfromタブから"Flip Z"を選択。これでオブジェクトを正しい方向に向かせることが出来る。

f:id:ai_gaminglife:20180609152216p:plain

 続けてモデル中心から出ている赤矢印、青矢印をつかみ、x,z座標を動かして中心を本来のものに揃える。

f:id:ai_gaminglife:20180609152224p:plain

 続いて最終的にfbxとして書き出す時に頂点数を減らす為にメッシュを切り分ける。オブジェクトをダブルクリックしボクセル編集モードに移行。

f:id:ai_gaminglife:20180609152232p:plain

 Mキーをクリックし、"Rectangular Select Tool"ツールを選択。マウス左ボタンのドラックランドドロップで範囲を選び、Modifyタブの"Split off"を選択する。これでメッシュを切り分けることができた。今回は頭だけを切り分ける。

f:id:ai_gaminglife:20180609152246p:plainf:id:ai_gaminglife:20180609152250p:plain


 Rectangular Select Toolで選択しやすいようにカメラを正面に向けたりしたい。そんなときはCamera -> Perpendiculer View -> Frontを選択すればよい。


 左上にある左向き矢印アイコンを押すと元の画面に戻ることができる。

3.fbxファイルとして書き出す

 元の画面に戻ったらShiftキーを押しながら左クリックでオブジェクトを複数選択する。

 Fileタブから"Export FBX"を選択すると画像の様なウィンドウが出る。

f:id:ai_gaminglife:20180609152320p:plain

 ここでどの様な設定で書き出すか色々変更することが出来る。が、今回は画像の通り初期設定のままで書き出してもOK。OKボタンを押して任意の場所に.fbxファイルを保存する

4.Blenderで調整し書き出す

 Blenderを起動。最初に表示されている立方体を右クリック選択してdeleteしたらファイル->インポートで先程書き出したfbxをインポートする。

 切り分けたパーツをそのままエクスポートすると別メッシュとして認識されるのでメッシュを結合しなければならない。ということでオブジェクトモードのままShift右クリックで全てのメッシュを選択、Ctrl+Jでオブジェクトを結合する。

 続いてピボットポイントを変更する。今のままでは変な位置にピボットポイントがあるので原点をピボットポイントに変更する。

 まずShift+Sキーで「カーソル → 原点」を選択。3Dカーソルを原点に移動させる。続いて先程結合したメッシュを選択した状態で、画面左下(オブジェクトモードと表示されているところの隣)のオブジェクトからトランスフォーム->原点を3Dカーソルに移動を選択。これでピボットポイントを3Dカーソルの位置=原点に変更できる。

f:id:ai_gaminglife:20180609152328p:plain

 次にトランスフォーム値をリセットする。メッシュを選択した状態でCtrl+Aキーを押し、「回転と拡縮」、「位置」をクリック。これでトランスフォーム値をリセットできる。

f:id:ai_gaminglife:20180609152335p:plain

 最後にもう一つ。Qubicleで書き出したUVテクスチャは解像度が足りず、影がおかしな付き方をしてしまう。そこでBlender上で新たにライトマップ用のUVテクスチャを用意する。

 メッシュを選択した状態でプロパティパネルのデータを選択。UVマップの右側のプラスボタンを押し、新たに用意されたUVMapの右側にあるカメラアイコンを選択。

f:id:ai_gaminglife:20180609152343p:plain

 Tabキーを押し編集モードに移動。Aキーを押してメッシュの全ての頂点を選択したらUキー->ライトマップパックを選択して画像の設定でOKを押す。

f:id:ai_gaminglife:20180609152351p:plain

 これでBlender上での調整終了。このままfbxとして書き出す。

 メッシュを選択した状態でファイル->エクスポート->FBXを選択。画像のように設定。

f:id:ai_gaminglife:20180609152401p:plainf:id:ai_gaminglife:20180609152402p:plain

名前をつけたらFBXをエクスポートをクリック。これでUE4にインポートする準備が整った。

UE4にモデルをインポートする

 UE4を起動。コンテンツブラウザのインポートから画像の様な設定でモデルを取り込む。

f:id:ai_gaminglife:20180609152409p:plain

 自動でテクスチャとマテリアルを持った3Dモデルが取り込まれたはず。

 続いてライトマップの設定を変更。コンテンツブラウザでStaticMeshをダブルクリック。DetailパネルのGeneral Settingから

  • Lightmap Resolution を128に変更
  • LightMap CoordinateIndex を1に変更

 これで影の問題は解決したが見て分かる通りテクスチャがボケボケになっている。というわけで最後にこの問題を解決しよう。

 コンテンツブラウザで取り込んだテクスチャをダブルクリック。詳細パネルで以下の様に設定する。

  • Compression -> Compression Setttingを "UserInterface2D"に変更

  • Texture -> Filterを "Nearest" に変更

  • Level Of Detail -> Texture Groupを "2D Pixels" に変更

 この状態で保存する。

f:id:ai_gaminglife:20180609152418p:plain

 これで望み通りのモデルがUE4に取り込むことが出来た。

MagicaVoxelで作成したモデルをUE4で利用する (1) 導入編

はじめに

 当ブログの現状のメインコインテンツ(?)であるMagicaVoxelで作ったモデルをUE4に持っていくワークフローの研究がようやく一定の成果を上げられたので、数回に分けて公開していこうと思う。目標は以下の通り。

  • MagicaVoxelでStaticMesh用モデルを作成してUE4にFBXとしてインポートする。条件はモバイル開発でも問題なく使えるように極力頂点数を減らす、取り回ししやすいようにUVテクスチャを作成する。

  • MagicaVoxelでSkeletalMesh用モデルを作成してBlenderでボーンを入れ、アニメーションを付ける。これをUE4にインポートし動かす。

 私はBlenderについては超がつく初心者の為、特にアニメーション周りは非効率な手法を使っている自覚がある。他に良い方法があればTwitterやコメントで教えていただけると助かります。

この記事の対象者

  • UE4でMagicavoxelで作ったボクセルモデルを使いたい

  • BlenderでMagicavoxelで作ったボクセルモデルをアニメーションさせたい

  • MagicaVoxelで作成したモデルにMinecraft風のカクカクしたアニメーションをつけたい。

 この記事はUnityユーザーを対象としていません。が、これから紹介する手法は、かなり変わった、自分が調べた範囲では日本語ブログで一切紹介されていない手法の為、もしかしたら何かの参考になるかも知れない。VRChatでボクセルモデルを動かしたいだけの方はそれについて書かれた専門の記事を読まれることを推奨する。

完成形

 Blender上でアニメーションさせている画面。

f:id:ai_gaminglife:20180606002119g:plain

必要ソフト

 StaticMeshとして書き出す際もBlenderを通す事を推奨。

  • Qubicle

 このワークフローの肝。Steamで2000円程度で購入可能。

  • Qubicle Mesh Module

 Qubicleの有料DLC。2480円。詳細は後述。

MagicaVoxel -> Blender -> UE4 の問題点

 当記事ではすでにQubicleを使わないこのワークフローを色々実験している。色々試しはしたが、UE4でボクセルモデルを使うのであれば、この手法はおすすめしない。詳細は省くが理由は以下の通り。

  • MagicaVoxelのobjエクスポートは頂点色を取ってマテリアルを作成する。UVテクスチャが生成されないので取扱いが面倒。

  • 複雑なモデルをobjエクスポートすると頂点数が爆発的に増える。

  • plyエクスポート -> Blenderで頂点数削減 + UV展開して頂点色を焼き込むという手法があるが、テクスチャ矩形がズレ、正しいマテリアルを生成出来ない。

Qubicleについて

 これらの問題を解決するのがQubicleとQubicle Mesh Module。このソフトはMagicaVoxelと双璧を成すボクセルモデリングソフトで、こちらを使って開発されたゲームも存在する。

cgworld.jp

 しかしながら、個人の感想であるがQubicleは使いにくい。MagicaVoxelより制作できるモデルのサイズが大きいという利点もあるがそれを差し置いてもMagicaVoxelでモデリングする事をおすすめする。幸いMagicaVoxelとQubicle間のやり取りは容易なのでここで心配する必要はない。

 QubicleとMagicaVoxelの差異についてはこちらの記事が詳しい。

imoue.hatenablog.com

 で、Qubicleを使う理由だが、Mesh Moduleを導入することで

  • 自動でズレのないUV展開、テクスチャ生成までやってくれる。

  • MagicaVoxelのobjエクスポート以上に頂点数を減らしてFBX or objエクスポート出来る

  • ボクセルモデルを腕、頭、体、足……と切り分けることが出来る。(Qubicle標準機能)これを使うことで更に頂点数を減らすことが出来る。

 というわけでMagicaVoxelで作ったモデルをQubicleで調整し、Blenderで更に調整するとより使い勝手のよいモデルを作れる。

 次回はStaticMesh用にUE4に書き出す手法を紹介する。

 続き

ai-gaminglife.hatenablog.com