※この記事で使用しているUnrealのVersionは04.26.1です。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト

ConstructionScriptについて レベル【★★】

最近ConstructionScriptについて様々な場所から質問が寄せられることがあるため、まとめたものをここに記したいと思います。

ConstructionScriptとは、Actorを継承したBlueprintで使用することができるBlueprintImplementableEventな関数です。
つまり、Blueprintでのみ処理を書くことのできる関数です。

以下公式説明

コンストラクション スクリプト

Actorを継承したBlueprintには、デフォルトでConstructionScript関数が生成されています。

ConstructionScriptの一番の特徴はやはり、非実行時にも処理が走ることだと思います。

どういうことかと言いますと、例えばActorを継承したBlueprintのクラスにIntegerの変数を持たせ、「Instance Editable」にチェックを入れます。

この変数をConstructionScriptでSet関数でDefault値以外にSetします。

そしてこのBlueprintをコンパイルしてレベル上に配置すると、プレイインをせずともConstructionScriptが配置された瞬間に処理され、変数の値がConstructionScriptで記載した通りの値に上書きされます。

とても便利ですね。

具体的な使用例は以下をご覧ください。

[UE4] コンストラクションスクリプトでお手軽にプロシージャルなアクターを作る

ConstructionScriptを使った事例自体はほかにもたくさん紹介されているので、ここではConstructionScriptを使う上での注意点をまとめました。

ConstructionScriptを使用する上で気を付けること レベル【★★】

〇ConstructionScriptの処理タイミングについて

最初に説明した通り、ConstructionScriptはEditor上やプレイ中などさまざまなタイミングで実行されます。

1.アクターの実態(Instance)が生成されたとき(Spawnされたとき)

Runtimeでの挙動で、ActorがSpawnされたときに処理が走ります。
(EditorとPackageどちらでも)

2.Editor上でアクター、またはアクターに紐づくコンポーネントのプロパティ等を変更したとき

EditorOnlyな挙動で、Actorのプロパティ等が変更されたときやアクターを移動させたときに処理が走ります。

3.Editor上で元のBlueprintClassをコンパイルしたとき

元のBlueprintClassをコンパイルすると、レベル上においてあるInstanceも再度作り直されるためConstructionScriptが走ります。

4.Editor上でレベルを開いたとき

Editor上でレベルを開いたときにもConstructionScriptの処理が走ります。

5.Editor上でプレイインしたレベル以外に対してOpenLevelをしてレベルを移動したとき

例えば、「PL_MapA」というレベルをEditorで開きプレイインした後に、「Open Level」で「PL_MapB」というレベルへマップ遷移した場合に、遷移後のマップ内のアクターのConstructionScriptの処理が走ります。

ちなみに、OpenLevelで開いたレベルのサブレベルに紐づいている場合は、たとえUnload状態のものでもConstructionScriptは実行されているようでした。

6.Cook時

Editor上では、レベルが総じてレベルが開かれたタイミングでConstructionScriptが処理されているようですが、パッケージになると話が違うようです。レベルに静的に置かれているアクターのConstructionScriptは、Cook時に実行されているようです。

↓詳しい説明は以下ツイートを参照(スミオ様より)

上記のようにパッケージとエディターでは処理タイミングが異なるため注意が必要になります。

〇ConstructionScriptでのProperty変更

最初にConstructionScriptの使い方を説明したように、ConstructionScriptでPropertyの値を変更した場合、その後ConstructionScriptの処理を消したとしても、既に処理がされているアクターのPropertyは元には戻らないので注意が必要です。

〇ConstructionScriptでのAddComponent

ConstructionScriptのプロパティの変更の結果はConstructionScriptを外しても保持されていましたが、「Add Component」をConstructionScriptで処理してComponentを追加した場合、ComponentはConstructionScriptが実行されるたびに破棄されてしまうため、処理を外すとComponentの追加はなかったことになります。

これは、アクタークラスが明示的に、ConstructionScriptで追加したComponentを破棄しているのでそうなっているようです。
(UActorComponentの「CreationMethod」というプロパティで、そのComponentがどのように生成されたかを保持しているようです。
→「UserConstructionScript」だと、ConstructionScriptでAddしたもの扱いになる)

・CreationMethod確認

Classの方で追加したTextComponent:SimpleConstructionScript
AddComponentで追加したTextComponent:UserConstructionScript

なので、プロシージャルメッシュを作成する場合などに、ConstructionScriptが実行されるたびにComponentが増えたりはしません。

〇ConstructionScriptでのSpawnActor

ConstructionScriptでは、SpawnActorのノードが使えません。

↓以下参考

ConstructionScriptから別のアクターをスポーン出来ない

一応関数内に「SpawnActor」ノードを配置して、それをConstructionScriptノードで呼び出すことはできます。が、SpawnActorの処理はWarningが吐き出されて処理がされません。

↓実験

↓結果

LogSpawn: Warning: SpawnActor failed because we are running a ConstructionScript (BP_Test_C)

というエラーログが出て失敗しました。

※詳しくはLevelActor.cppを参照

ActorはSpawnできませんが、Componentの生成はできるので「ChildActorComponent」を使うことで、疑似的にSpawnを行うことができるようです。

以下参考ツイート

あとは、「CallInEditor」な関数orCustomeventを使用することでもActorのSpawnは行うことができます。

↓結果

このように、ConstructionScriptには様々な特徴がありますね。

〇ちなみに

ConstructionScriptをEditor上では機能しないようにすることもできます。

エンジンフォルダにあるConfigフォルダ内の「BaseEngine.ini」を開き、[Kismet]カテゴリにある「bTurnOffEditorConstructionScript=false」となっている部分を「bTurnOffEditorConstructionScript=true」に変えるだけです。

※Engine側のConfigの変更なので、ご利用はご計画的に。

また、C++ではConstructionScriptに変わって「virtual void OnConstruction();」という仮想関数をオーバーライドすることでConstructionScriptのタイミングでの処理を実装できますが、こちらは上記のConfigをいじっても処理をさせないことはできません。

簡単な内容になりましたが以上になります。

※この記事で使用しているUnrealのVersionは04.26.1です。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です