Gaming Life

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

Python リストの最後を取得する

 len()とかを使うのもありだが簡単に取得する方法があったのでメモ。

list = [ 'A', 'B', 'C', 'D', 'E']
print(list[-1])     #リストの最後の要素を表示する
print(list[-2])     #リストの最後から2番目の要素を表示する

 最近大学の実習でPythonを使っているがC++と随分書き方が違い戸惑う…… const参照渡しとかないのかなあ。

UE4 メッシュの一部の色だけをパラメータで切り替えられるマテリアルを作る

unrealengine.hatenablog.com

 上記のブログ等で物体全体の色をパラメータで切り替えるなどは紹介されているが一部だけの色を切り替えるみたいなものは見つけられなかったのでそれを自前で実装した。マテリアル全体の構成は以下の通り。

 ちなみに今回、マテリアルはSubstancePainterで作成した。

f:id:ai_gaminglife:20180704015038p:plain

テクスチャの色域を指定してマスクテクスチャを作る

f:id:ai_gaminglife:20180704015051p:plain

 Photoshop等でマスクテクスチャを用意するのが最も簡単だろうが今回はマテリアルエディタ内でマスクテクスチャを作ってみる。

 抜き取りたい色を "Const3Vector"で用意。それを "Distance"のBに繋ぐ。

 このままではグレーの部分が出てしまうのでifノードを使って0と1でくっきり分ける。これで紫部分をくり抜けるマスクテクスチャを作ることが出来る。

一部分だけ色を変更したテクスチャを作る

f:id:ai_gaminglife:20180704015100p:plain

 "JumpColor"という3Vectorパラメータを作成。この色で紫部分を塗りつぶす。

 生成したマスクテクスチャと"JumpColor"を掛け合わせ、反転させたマスクテクスチャと元々のBaseColorテクスチャを掛け合わせたものを足すことで一部だけを"JumpColor"で塗りつぶすことが出来る。

Switchでもとの色と塗り替えた色を切り替える

f:id:ai_gaminglife:20180704015108p:plain

 Static Boolパラメータ、"IsJump"を用意。これをSwitchノードのValueに繋ぎ、Trueに"JumpColor"で一部を塗りつぶしたテクスチャを、Falseに元々のテクスチャを繋ぐ。

 これでIsJumpの切り替えで一部の色だけを切り替えるマテリアルが作れた。

f:id:ai_gaminglife:20180704015116p:plainf:id:ai_gaminglife:20180704015120p:plain

(続き)

ai-gaminglife.hatenablog.com

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つの違いはよくわかってない。

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