UnrealPythonでActorを生成する
UnrealEngine4でPythonを使ってアクターをスポーンする処理を書いたので。
確認バージョンは4.22です。
今回EditorAssetLibraryとEditorLevelLibraryを使用するのでPythonのプラグインの他に「Editor Scripting Utilities」を有効にします。
ざっと呼んでみた感じ EditorLevelLibrary の spawn_actor_from_object 関数でアクターを生成できるみたいなので
実験用にこんな感じのコードを書きました。
import unreal asset = unreal.EditorAssetLibrary.load_asset("StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'") if asset: for x in range(10): for y in range(10): location = unreal.Vector() location.x = x * 100 location.y = y * 100 location.z = 300 rotation = unreal.Rotator() spawnActor = unreal.EditorLevelLibrary.spawn_actor_from_object(asset, location, rotation)
実行結果
意図したとおりに SM_Chair が100個生成されました。
Library系は下記のように調べればある程度良い感じの物が探せます。
api.unrealengine.com
はじめてのUnrealPython
UnrealEngine4でPythonが使えると聞いたのでとりあえず挨拶しておく
確認バージョンは4.22です。
helpを見た感じlog(str)でログ出力できるみたいなので
api.unrealengine.com
Pyファイルを作成してコードを書く
「file->ExecutePythonScript」で作成したPyファイルを指定すると実行
やったぜ
当たり前ですが、cmdに手打ちしても同じ結果が得られるので一回手打ちかコピペでcmdから実行した後に「↑->Enter」するとイテレーション早くて楽です
ちなみにCmdのところをクリックするとPythonに切り替えられるのでその状態で「unreal.log("HelloWorld")」と打っても挨拶出来ます
visual studio で開いているファイルを vim で開く方法
最近UE4を触っているとvisual studioを触る機会が多くなってきました。
その際にvisual studioで今開いてるファイルをvimでも開く方法がないかと調べてみたところ外部ツールに設定することで出来るようです。
code.msdn.microsoft.com
設定手順は以下。
外部ツールを作成
visual studio上でAlt+t、Alt+e、Alt+aの順番に押して新規外部ツールを作成して、下記の内容を追加
タイトル | Vim |
コマンド | vim.exeへのパス |
引数 | --remote-send " |
初期ディレクトリ | $(ItemDir) |
ショートカット設定
visual studio上でAlt+t、Alt+c、Alt+kの順番に押してキーボードショートカット設定まで行って設定した外部ツールを任意のキーに割り当てる(僕の場合はAlt+F1)
これで終了です。
ちなみに上記設定だと先にvimを起動していないと正常に動作しないです。
もしvisual studio上でvimを立ち上げたいと思っている方がいるならば引数の部分を「+$(CurLine) $(ItemPath)」にすればファイル、行を指定してvimが開きます。
ではではよいvimライフを!!
プロパティ メタデータ指定子のメモ
UPROPERTYのmeta指定子の使用時の挙動などを備忘録も兼ねて書きます。
※この記事で検証していることは実際にそのmeta指定子の処理を見に行ったわけではないです。
本記事で公式ドキュメントの記載とは違う動きをしている箇所がいくつかありますが、それがバグか筆者の使い方が間違えているのかの判断は各自検証してからしていただくようお願いします。(もし間違えてたら優しく教えてください!)
- AllowAbstract
- AllowedClasses
- AllowPreserveRatio
- ArrayClamp
- BlueprintCompilerGeneratedDefaults
- ClampMin、ClampMax
- ConfigHierarchyEditable
- ContentDir
- DisplayName
- DisplayThumbnail
- EditCondition
- EditFixedOrder
- ExactClass
- ExposeFunctionCategories
- ExposeOnSpawn
- FilePathFilter
- HideAlphaChannel
- HideViewOptions
- InlineEditConditionToggle
- LongPackageName
- MakeEditWidget
AllowAbstract
Subclass と SoftClass のプロパティで使用され、クラスピッカーで抽象クラス型を表示するかを指定することが出来ます。
たとえば:
UCLASS(Abstract,ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) class TANKMYPROJECT_API UMyAbstractActorComponent : public UActorComponent { GENERATED_BODY() public: // Sets default values for this component's properties UMyAbstractActorComponent(); protected: // Called when the game starts virtual void BeginPlay() override; public: // Called every frame virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; };
UCLASS() class TANKMYPROJECT_API UMyActorComponent : public UMyAbstractActorComponent { GENERATED_BODY() };
※1
UPROPERTY(EditAnywhere) TSubclassOf<class UMyAbstractActorComponent> Subclass_A; UPROPERTY(EditAnywhere, meta = (AllowAbstract)) TSubclassOf<class UMyAbstractActorComponent> Subclass_B;
class UMyAbstractActorComponent はUCLASSにAbstractを追加して抽象クラスにしています。
これを※1のように定義した場合結果は以下のようになります。
AllowedClasses
FSoftObjectPath プロパティで使われ、アセットピッカーに表示されるクラスを制限することが出来ます。
UPROPERTY(EditAnywhere, meta = (AllowedClasses = "World")) FSoftObjectPath World; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "Texture")) FSoftObjectPath Texture; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "Material")) FSoftObjectPath Material; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "Font")) FSoftObjectPath Font; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "DataTable")) FSoftObjectPath DataTable; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "MaterialInterface")) FSoftObjectPath MaterialInterface; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "World,DataTable")) FSoftObjectPath WorldAndDataTable;
こんな感じ
WorldAndDataTableもばっちし
ただAllowedClassesは自作のクラスや、一部クラスのには効かないみたいです。(4.22環境)
UPROPERTY(EditAnywhere, meta = (AllowedClasses = "ActorComponent"))
FSoftObjectPath ActorComponent;
AllowPreserveRatio
このプロパティを [Details (詳細)] パネルに表示するときに、ratio のロックが追加されます。
ロックすると、現在のxyzスケール値に基づいて均等に拡大縮小されるため、拡大縮小してもオブジェクトは各方向にその形状を維持します。
例:
UPROPERTY(EditAnywhere, meta = (AllowPreserveRatio)) FVector Vector3 {}; UPROPERTY(EditAnywhere) FVector DefaultVector {};
ArrayClamp
エディタ上で入力する値を 0 と配列のプロパティの名前の長さにクランプします。
配列サイズが0の場合は-1が入るようです。
UPROPERTY(EditAnywhere, meta = (ArrayClamp = "Array")) int32 Index{}; UPROPERTY(EditAnywhere) TArray<int> Array{};
UEC++のお気持ちを理解しようとUPROPERTYのメタデータ指定子見てる。
— 上谷@タイムマシン求 (@kamitani_08) 2019年4月23日
なにこれめっちゃ便利 pic.twitter.com/U1mFSpMlhx
ただ上記動画からもわかるようにArrayの要素数を変更した際にはIndexのClamp処理が行われず、エラーや警告も発生しないことに注意してください。
BlueprintCompilerGeneratedDefaults
Subclass と SoftClass のプロパティで使用されます。クラス ピッカーで Blueprint クラスのみを表示するかを示します。>公式より
ClampMin、ClampMax
どちらも float と integer のプロパティに使用され、ClampMin はプロパティに入力可能な最小値、ClampMax は最大値を指定します。
たとえば:
UPROPERTY(EditAnywhere, meta = (ClampMin = 5, ClampMax = 10)) int Index{5};
こうすればIndex変更時にClampMin から ClampMaxまでの値にClampされます。
もちろんClampMin と ClampMax は単体でも使用可能です。
ConfigHierarchyEditable
このプロパティは、 config (.ini) ファイルにシリアル化されて、 config 階層のどこにでも設定することができます。>公式より
ContentDir
FDirectoryPath プロパティによって使用されます。このパスは、Content フォルダ内のスレート スタイルのディレクトリ ピッカーを使って選ぶことができます。>公式より
つまりこうゆう事
UPROPERTY(EditAnywhere, meta = (ContentDir)) FDirectoryPath Directory_A; UPROPERTY(EditAnywhere) FDirectoryPath Directory_B;
Directory_Bの方だとエクスプローラーで指定する形になります。
DisplayName
エディタでの表示名を指定できます。
UPROPERTY(EditAnywhere, meta = (DisplayName="Index")) int hogehoge{1234}; UPROPERTY(EditAnywhere) int TestTest{};
DisplayThumbnail
プロパティがアセット タイプであることを示し、選択したアセットのサムネイルを表示します。>公式より
たとえば:
UPROPERTY(EditAnywhere, meta = (DisplayThumbnail = "true")) UTexture2D* PaintTexture_A; UPROPERTY(EditAnywhere ,meta = (DisplayThumbnail = "false")) UTexture2D* PaintTexture_B;
上記のようなコードを書くとこうなる。
ちなみにデフォルトは(DisplayThumbnail = "true")の状態みたいです
EditCondition
このプロパティの編集を無効にするかどうかを示すために使うブール プロパティに名前を付けます。プロパティ名の前に "!" を付けるとテストが反転します。>公式より
たとえば:
UPROPERTY(EditAnywhere) bool bUseConstantValue{}; UPROPERTY(EditAnywhere, meta = (EditCondition = bUseConstantValue)) float ConstantValue{};
上記のようなコードを書いた際には下記のように「bUseConstantValue == false」の際には ConstantValue は編集できなくなっているのがわかります。
EditFixedOrder
ドラッグすることで配列の要素の順番が変わるのを防ぎます>公式より
UPROPERTY(EditAnywhere, meta = (EditFixedOrder)) TArray<int> Array_A; UPROPERTY(EditAnywhere) TArray<int> Array_B;
ExactClass
AllowedClasses と合わせて FSoftObjectPath プロパティで使用されます。AllowedClasses で指定されているものと同じクラスだけを使用可能か、サブクラスも有効であるかを示します。>公式より
ちなみに:
UPROPERTY(EditAnywhere, meta = (AllowedClasses = "SkeletalMesh")) FSoftObjectPath SkeletalMesh_A; UPROPERTY(EditAnywhere, meta = (AllowedClasses = "SkeletalMesh", ExactClass = "false")) FSoftObjectPath SkeletalMesh_B;
上記SkeletalMesh_AはSkeletalMesh_Bで宣言した時と同じ処理になります。
ExposeFunctionCategories
ブループリント エディタで関数リストを構築するときに関数を公開するカテゴリのリストを指定します。>公式より
たとえばこうゆう事です。
UPROPERTY( VisibleAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories = "Components|SkeletalMesh")) class USkeletalMeshComponent* SkeletalMeshComponent_A; UPROPERTY(VisibleAnywhere, BlueprintReadOnly) class USkeletalMeshComponent* SkeletalMeshComponent_B;
ただ今回検証した感じだと「関数を公開するカテゴリのリストを指定」しているかは関係ないみたいです。(4.22)
UPROPERTY( VisibleAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories = "Components|SkeletalMesh")) class USkeletalMeshComponent* SkeletalMeshComponent_A; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories = "")) class USkeletalMeshComponent* SkeletalMeshComponent_B; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories)) class USkeletalMeshComponent* SkeletalMeshComponent_C;
ExposeOnSpawn
このクラスのタイプで Spawn Actor ノードでこのプロパティを公開するかを指定します。>公式より
たとえばこうなります。
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn)) int Num_A{}; UPROPERTY(EditAnywhere, BlueprintReadWrite) int Num_B{};
FilePathFilter
FFilePath プロパティによって使用されます。ファイル ピッカーで表示するパス フィルタを示します。共通の値として、"uasset" と "umap" 値を含みますが、他にも使える値があります。>公式より
たとえば:
UPROPERTY(EditAnywhere, Category = Automation, meta = (FilePathFilter = "uasset")) FFilePath FilePath_uasset; UPROPERTY(EditAnywhere, Category = Automation, meta = (FilePathFilter = "umap")) FFilePath FilePath_umap; UPROPERTY(EditAnywhere, Category = Automation, meta = (FilePathFilter = "*")) FFilePath FilePath_asterisk;
ここが変わります。(図はFilePath_uassetを選択した際の表示)
HideAlphaChannel
FColor プロパティと FLinearColor プロパティで使用されます。詳細で、プロパティウィジェットを表示するときに Alpha プロパティが非表示になることを示します。>公式より
たとえば:
UPROPERTY(EditAnywhere) FColor Color_A {}; UPROPERTY(EditAnywhere, meta = (HideAlphaChannel)) FColor Color_B {};
上記コードだとこうなります。
カラーピッカーでもAlpha プロパティが表示になっていることも確認。
HideViewOptions
Subclass と SoftClass のプロパティで使用されます。クラスピッカーで表示オプションを変更する機能を隠します。>公式より
UPROPERTY(EditAnywhere, meta = (HideViewOptions)) FSoftClassPath SoftClass_A; UPROPERTY(EditAnywhere) FSoftClassPath SoftClass_B;
InlineEditConditionToggle
他のプロパティで切り替わり、単独では表示されない編集条件として、ブール プロパティはインラインでのみ表示されることを表します。>公式より
たとえば:
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (InlineEditConditionToggle, ExposeOnSpawn)) bool bFlag_A{}; UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bFlag_B{};
このように書くとbFlag_Aは詳細には表示されません
GetSetは通常通りに行えます。
LongPackageName
FDirectoryPath プロパティによって使用されます。パスを長いパッケージ名に変換します。>公式より
どうやらパスを絶対か相対か切り替えることが出来ます。
たとえば:
UPROPERTY(EditAnywhere) FDirectoryPath DirectoryPath_A; UPROPERTY(EditAnywhere , meta = (LongPackageName)) FDirectoryPath DirectoryPath_B;
あれ?
代入時に変換しているのかな?
変わらない....
LongPackageNameは機能していないのか...?(誰か教えて!!!
MakeEditWidget
Transform プロパティ、Rotator プロパティ、または Transforms、Rotators の配列で使用されます。移動可能なウィジェットとしてプロパティがビューポートに公開されることを示します。>公式より
これを指定することによってビューポート上にプロパティが表示されるようになります。
UE4 Textウィジェットの行間を調整する方法
既にTwitterでepicな猫の人がTextウィジェットの行間を調整する方法を紹介していたのだけど個人的な備忘録も兼ねて。
Textウィジェットの行間の調整は「Line Height Percentage」で可能。
おかずさんが言ってたやつ pic.twitter.com/dXuR0i9dP6
— 上谷@タイムマシン求 (@kamitani_08) 2019年3月13日
UE4 NiagaraModuleScriptの中にNiagaraModuleScriptを入れることが出来るのかを検証してみた結果出来なかった話
※この記事はUE4.21.1の物です
NiagaraModuleを作成していくうちに基底の親Moduleを継承した子Moduleという機能が欲しくなり、作れないか調べてみました。
結論から言うと現状Moduleの中にModuleを入れる事は出来ますがまったくと言って良いほど意味がありません、それにかなり使いづらいのでおススメもしません。
・おススメしない理由その1
Moduleパラメータの再帰的検索がされず、中で呼び出しているModuleにModuleパラメータが入っていた場合でもSelectedEmittersウィンドウには表示されません。
※ModuleWithModuleTestの中で呼び出しているModuleでModule.Color_001を設定しています。
正直これがやりたかったので出来ないのはマジでつらいです...
・おススメしない理由その2
そもそもこれ関数にしたほうがまだ楽なのでは???
・出来ること
Moduleパラメータでの編集は出来ないが、パラメータを参照し、値を書き換えることは可能
依存関係を作って入力と処理を分ければもしかするといい使い方があるかもしれない
(Moduleの依存関係の作り方についてはshiotani君がわかりやすくまとめてくれているのでそちらを参照してください)
saltcanyon.hatenablog.com
実際にやってみた
NiagaraModuleScriptを二つ作成し、名前を「Color_001UpdateTest」と「ModuleWithModuleTest」に変更
Color_001UpdateTestの方から編集します。
MapGetにLinearColorを追加し「 Particles.Color_001」とリネーム、MapSetにParticles.Colorを追加しそれをつなぎます。
変化がわかるようにParticles.Color_001の値をR=1,G=0,B=0,A=1に変更します。
次にModuleWithModuleTestを編集します。
先ほど作成したColor_001UpdateTestを追加します。
確認
先ほど作成したModule確認用にエミッターを作成します。
テンプレートのSimpleSpriteBurstを作成。
今回も前回同様、作成するModuleで色を設定するので不要になるColorModuleを削除。
今こんな感じ
ParticleUpdateにModuleWithModuleTestを追加
パーティクルの色はこんな感じ
次に色を外部から操作出来るようにします。
エミッター側のパラメータにLinerColorを作成し「Particles.Color_001」とリネーム
ModuleWithModuleTestの上でParticles.Color_001の値をR=0,G=0,B=1,A=1に変更します。
変更した色がパーティクルに反映されました。
まとめ
このようにModuleが使用できないだけでパラメータの参照は出来るのでまだ使い道があるかなと思ったのですが、
調べてみるとNiagaraFunctionScriptでも同じことが出来るみたいです。
今後のアップデートでもしかすると再帰的なModuleパラメータの検索が実装されるかもしれませんが、今のところ基底Moduleみたいな事は出来ず、処理をまとめたい場合はNiagaraFunctionScriptでまとめるか諦めてコピペするしかなさそうです。
ところでこのModuleの処理は仕様なのかそうでないのかを判断できる場所って今のところあるんですかね?
もし知っている方がいらしたらコメントとかで教えていただけるとありがたいです。
【Niagara】自作したModuleのパラメータにデフォルトでDynamicInputを設定する方法
※この記事はUE4.21の物です。
Moduleを作成している際に地味にハマったのでメモ
やりたいことはこんな感じ
このDynamicInputさん達を毎回決まっているのにイチイチ設定するのがめんどくさいので、Module作成時にデフォルトで設定したい。
というわけで早速作成してみる。
[準備]
まずModule確認用にエミッターを作成します。
テンプレートのSimpleSpriteBurstを作成。
Moduleで変更された色の確認をしたいのでMaxLoopCountの値を0に変更
今回作成するModuleで色を設定するので不要になるColorModuleを削除。
今こんな感じ
次にNiagaraModuleScriptを作成し、SelectedEmittersウィンドウからパーティクルの色を変えられるようにするため、
LinearColorを作成し「Module.Color」にリネームしてMapSetに繋げ、追加された変数の名前を「Particles.Color」にリネームする。
次に行うModuleが変更を適用しているかの確認用にModule.ColorのRの値を100に設定する。
ParticleUpdateに作成したModuleを追加。
この時点でのパーティクルの色はこんな感じ
設定した色が出てるのが確認できますね。
このColorパラメータにDynamicInputを設定していきます。
[ここから本番]
最初にBeginDefaultsノードを追加してその先にDynamicInputの「SplitLinearColor」を追加してModule.Colorに繋げます。
この時作成されたModule.R、Module.G、Module.B、Module.AがSplitLinearColorで分割後のパラメータです。
これでSplitLinearColorが設定できました。
次は分割したRとAに変更を加えます。
MapSetを作成してModule.R、Module.Aを追加します。
追加したパラメータのModuleの部分をSplitLinearColorに変更します。
先ほどと同様にRに100、Aに1を入れて同じ色が出ているか確認します。
※Emitter画面に戻った際にModuleで行った変更が反映されないことがあります。
その際は下記画像にある黄色矢印のボタンを押すとModuleに設定されているデフォルトの状態に戻すことが出来るのでそれを押して更新しましょう。
次に同じ要領でR要素にSineを設定していきます。
最後にB要素にSineを設定します。
自分はここで少しハマったのですが、
Sineを追加する際に元からあるノードをコピペして持ってくると同じ名前のSineノードが作成されます。
このノード、リネームもできないしこの状態だと各Sineに別々のパラメータを入れることが出来なくて少し悩ました。
解決方法としては素直に左クリックからSineを追加するとSine001が作成されて区別することが出来ます。