こちらのリンク集にも載せてありましたが、日本語の記事が見当たらなかったので、書いてみました。
ブループリントに公開するとリネームできない!?
C++ で作ったクラス、関数などがブループリントなどのアセット内で使用されていると、その名前がアセット内に保存される仕組みになっています。では、既に使われているクラスや関数の名前を変更すると、どうなってしまうでしょうか?
試してみましょう。
まず、C++ で AMyActor というアクターを作って、レベルに配置します。
レベルを保存した後、AMyActor を AMyActor2 にリネームします。
そして、先程保存したレベルを開いてみると……
なんと、先程配置したはずのアクターが消えてます!
この他にも、レベルブループリントでこのアクターを参照してたら、以下のような警告が出たり……
この型のアクターを継承したブループリントのアセットを開こうとすると、以下のようなダイアログが表示されてアセットが開けなかったり……
など、名前の変更により様々な問題が発生してしまいます。
名前の変更にはリダイレクター!!
では、一度名前を決めたらもう変更は出来ないのか?というと、変更する方法はあります。
それは、**「名前に対するリダイレクター」**を作ることです。
**「リダイレクター」とは、アセットを移動、もしくはリネームした際に作られる「アセットがどこに移動したのかを示すファイル」**のことです。リダイレクターの詳しい説明はヒストリアさんのこちらのページや過去に書いたこちらの記事に載っています。
アセットのリダイレクターはアセットファイルで、かつ自動で生成されていましたが、C++ の名前に対するリダイレクターは、ファイルではなくゲームプロジェクトの DefaultEngine.ini に手動で記述する形になっています。1
では、試しに DefaultEngine.ini を開いて、先程の AMyActor2 にリネームするためのリダイレクターを書いてみましょう。
リダイレクターを記述する際は、以下のルールを守る必要があります。
- [/Script/Engine.Engine] セクション内に記述する。
- クラス、関数など、リネーム対象にあったリダイレクターを定義する。
(今回は、クラス名のリネームということで**「ActiveClassRedirects」**を使用。
) - クラス名や構造体名の A や U などのプレフィックスは除外する。
- 名前をダブルクォーテーションで括る。
これらを守って書いたものが以下のものになります。
[/Script/Engine.Engine]
+ActiveClassRedirects=(OldClassName="MyActor",NewClassName="MyActor2")
これを記述した状態で先程のアセットを開くと、問題なく開けることがわかります。
名前に対するリダイレクターには種類がある
これでもうリネームしても大丈夫!!と思われるかもしれませんが、実はまだ大丈夫ではないです。
というのも、今回行ったのは**「クラス名」のリネームで、「関数名」や「変数名」**などの他のリネームはこの方法では出来ないからです。
では、どうすればいいのか?というと、実はエンジンの BaseEngine.ini を見るとわかったりします。
この「名前に対するリダイレクター」はエンジン側でも当然使われていて、それが BaseEngine.ini に大量に記述されています。なので、BaseEngine.ini を見れば「変数の時はどうすればいいか?」「関数の時はどうすればいいか?」がわかります。
以下に、BaseEngine.ini で使われていたリダイレクターをまとめました。2
数が多くて検証するのに時間がかかるので、ここではリダイレクター名とその対象、記述例を載せておきます。
リダイレクター名 | 対象 | 記述例 |
---|---|---|
ActiveClassRedirects | クラス名 or 列挙型名 or オブジェクト名 | +ActiveClassRedirects=(OldClassName="GameInfo",NewClassName="/Script/Engine.GameMode") +ActiveClassRedirects=(OldClassName="ELockedAxis", NewClassName="EDOFMode") +ActiveClassRedirects=(OldClassName="PointLightComponent",OldSubobjName="PointLightComponent0",NewSubobjName="LightComponent0") |
ActiveStructRedirects | 構造体名 | +ActiveStructRedirects=(OldStructName="AnimNode_BlendSpace",NewStructName="AnimNode_BlendSpacePlayer") |
TaggedPropertyRedirects | メンバ変数名 | +TaggedPropertyRedirects=(ClassName="MeshComponent",OldPropertyName="Materials",NewPropertyName="OverrideMaterials") |
EnumRedirects | 列挙型の要素名 | +EnumRedirects=(EnumName="EDOFMode",OldEnumEntry="EDOFMode::X",NewEnumEntry="EDOFMode::YZPlane") |
K2FieldRedirects | メンバ関数名 | +K2FieldRedirects=(OldFieldName="SceneComponent.AttachTo",NewFieldName="SceneComponent.K2_AttachTo") |
K2ParamRedirects | 関数の引数名 | +K2ParamRedirects=(NodeName="/Script/BlueprintGraph.K2Node_CallFunction", OldParamName="SkeletalMeshComponent.SetAnimInstanceClass.NewBlueprint", NewParamName="NewClass") |
ActiveGameNameRedirects | モジュール名 | +ActiveGameNameRedirects=(OldGameName="/Script/MovieSceneCoreTypes", NewGameName="/Script/MovieSceneTracks") |
一度リネームしたものをもう一回リネームしたい場合は?
では、先程リネームした AMyActor2 を今度は AMyActor3 にリネームしたい場合はどうすればどうすればいいでしょうか?
実際にやってみたところ、こうなりました。
[/Script/Engine.Engine]
+ActiveClassRedirects=(OldClassName="MyActor",NewClassName="MyActor3")
+ActiveClassRedirects=(OldClassName="MyActor2",NewClassName="MyActor3")
なぜ、AMyActror のリダイレクターを残しているのか?というと、一度でもアセットを開いて保存しない限りはアセットの中には AMyActor の名前が残りっぱなしになっているからです。「必ず保存されている」という保証があれば必要ないですが、保証できないのであれば残しておいたほうがいいかと思います。