目次
※この記事で使用している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にアップされています。
サンプルプロジェクト