【UE5】グローバルな値をDataAssetで管理してみる
Static変数のようなグローバルな値の参照方法を求めて
どこからでもアクセスできるグローバルな値というとGameInstanceが思い浮かびます。
ですが、GameInstanceに変数が集中するのが嫌だったり、そもそもBPのObjectクラスではGetGameInstanceを呼ぶことができなかったり、何かしらの理由でグローバルな値の保管をGameInstanceで行いたくない場合、DataAssetという手もアリなんじゃないかと思いました...。
DataAssetをグローバル変数の代わりとして使ってみる
DataAssetはオブジェクト参照が可能な変数を設定できます。ゲーム中に生成されたアクターもセットできるということです。
DataAssetにObjectクラスの変数を用意し、その変数にGameInstanceだったり、Pawnだったりの参照をセットすれば、そのDataAsset経由で、ObjectクラスからだってGameInstance等へのアクセスが可能になります。
実装例
GameInstanceをDataAssetから取り出す例
-
データアセットを作ったら、データアセット自体に変数を作ります。
GameInstanceだろうが、PlayerControllerだろうが、どんな値でもセットできるObject型にします。
-
次にDataAssetにGameInstanceの参照をセットします。
テキトーにプレイヤーコントローラー上でセットしています。
プレイヤーコントローラーにはDataAssetを取得する変数を用意してあります。 -
ObjectクラスからGameInstanceを取得してみます。
このObjectクラスにはDataAssetを取得する変数を用意してあります。
変数XXXはObject型なのでGameInstanceクラスにキャストします。
これでObjectクラスからGameInstanceの取得が可能になりました。
レベル遷移後も値を保持したい
結論
GameInstanceの力を借りないと不可能でした。
以下の2パターンはレベル遷移時にDataAssetが値を保持できなかったパターンと保持できたパターンです。
1. アクタークラスの変数にのみDataAssetがセットされている場合
DataAssetの参照はアクターのみが保持しているとします。
Pawnやアクターの参照をDataAssetに保持してもレベル遷移時に参照が消されてしまいます。レベルが破棄されるので、アクターも破棄されるのでわかります。ですが、DataAssetに設定したIntやFloat等の値も初期値に戻ってしまいます。
レベル破棄のタイミングでDataAssetも破棄されているような動きです。
アクターやレベルに紐づくクラスからしか参照されていないDataAssetは、レベル破棄のタイミングで一緒に破棄されているのでしょうか?
2. GameInstanceの変数にもDataAssetがセットされている場合
この場合、レベル遷移後もDataAssetに設定された値を保持してくれます。さすがにレベルに紐づくアクターやオブジェクトクラスの参照は破棄されてしまいます。DataAsset内でオブジェクトクラスを生成すればレベル遷移後も参照の保持は可能なようです。
レベル遷移後も値を保持したい場合、結局GameInstanceは必要だったようです...。
参照用のDataAsset
Map変数を作って、GameplayTagとObjectを紐づけることもできます。
DataAssetなので、Managerクラス参照用、レベルに配置したActor参照用等、小分けにしても良いのかな?と思ったり。
DataAssetの注意事項
エディター上でゲームを終了しても値が保存されたままになっている
例えばDataAssetの変数に配列(デフォルト要素数0)を用意し、ゲーム中に配列の要素数を増やした場合、エディター上ではゲーム終了後もDataAssetの配列の要素数は増えたままです。
エディターを再起動するとDataAssetの配列の要素数はデフォルト値の0に戻っています。
Discussion