---
title: BPの参照連鎖を断つ手法
tags:  #ゲーム開発 #ue4  
author: [株式会社ヘキサドライブ](https://convert.docswell.com/user/hexadrive)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/GJ5YKZVXJ4.jpg?width=480
description: これは、社内勉強会で使われたスライドです。  Unreal Engineを扱う上で避けては通れない、ハード参照が連鎖する問題とその対処法を扱います。  参照連鎖に気づくのは開発が本格化してからが多いのですが、経験しないと問題の存在に気づけないという厄介さがあります。  本資料は、その予防接種としてBlueprintを扱う方に読んで頂きたい内容です。  スポットライトが当たりにくいテーマですが、トラブルを未然に防ぎプロジェクトを成功させる手助けになれば幸いです。
published: October 30, 20
canonical: https://convert.docswell.com/s/hexadrive/ZQ8EGN-2020-10-30-114000
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/GJ5YKZVXJ4.jpg)

株式会社ヘキサドライブ
堀井 陽介


# Page. 2

![Page Image](https://bcdn.docswell.com/page/9E2GWR3QER.jpg)

目次
1
UEにおける参照とは？
2
参照が生成される理由
3
抽象に依存させよう
4
分割して疎結合とせよ
5
量産コンテンツ管理


# Page. 3

![Page Image](https://bcdn.docswell.com/page/D7YVLD1Y7M.jpg)

Part 1.
UEにおける
参照とは？
❖ 参照の意義を知る
❖ UE特有の参照の問題を知る


# Page. 4

![Page Image](https://bcdn.docswell.com/page/VENM462RJ8.jpg)

1
UEにおける参照とは？
UEにおける参照について
◆
依存しているアセットを一緒にロードしてくれ
る、親切なシステム
◆
不適切な参照はロード時間とメモリ使用量
に深刻な影響


# Page. 5

![Page Image](https://bcdn.docswell.com/page/Y79NQL1Z73.jpg)

1
UEにおける参照とは？
参照の素晴らしさ
マネキンのBPをロードすると
マネキンの、
⚫
⚫
⚫
⚫
⚫
メッシュ
マテリアル
テクスチャ
スケルトン
アニメーションBP
も同時にロードしてくれる


# Page. 6

![Page Image](https://bcdn.docswell.com/page/G78KGX3YJD.jpg)

1
UEにおける参照とは？
参照の恐ろしさ
開発初期から参照関係を
適切にコントロールできていない場合、
いつのまにか数百数千のアセットが
相互依存する事態に発展しがち


# Page. 7

![Page Image](https://bcdn.docswell.com/page/L7LZG8V9ER.jpg)

1
UEにおける参照とは？
数百数千のアセットの相互依存が出来上がる原理
a) アセット同士が相互に依存
b) アセットが連鎖的に依存
＞＞これが繰り返され数千アセットがひとかたまりに


# Page. 8

![Page Image](https://bcdn.docswell.com/page/4EMVQ6GVEW.jpg)

1
UEにおける参照とは？
相互依存が困る例
相互依存すると各BPクラスを個別にロードできなくなる
＞＞例：緑の敵しか出ないレベルなのに、赤の敵もロードされている！


# Page. 9

![Page Image](https://bcdn.docswell.com/page/PER28PZW79.jpg)

1
UEにおける参照とは？
相互依存が困る例
エディタの起動が遅くなる
このアセットの適切ではない相互依存は、
ほぼBPクラス同士で起こる
そして、作り方に問題を抱えている事が多い


# Page. 10

![Page Image](https://bcdn.docswell.com/page/P7XD839VJX.jpg)

1
UEにおける参照とは？
まとめ
◆
UEの参照は、依存アセットを一緒にロードしてくれる、親切なシステム
◆
作り方を間違えると、一緒にロードしたくないアセット同士が依存
＞＞不適切な参照のほとんどは、BPクラス同士で起こる
◆
参照は連鎖する
＞＞数千アセットが連なることも


# Page. 11

![Page Image](https://bcdn.docswell.com/page/37KXKYP5JD.jpg)

Part 2.
参照が
生成される理由


# Page. 12

![Page Image](https://bcdn.docswell.com/page/LJ35Z9X175.jpg)

２
参照が生成される理由
他のBPクラスの型情報が必要な操作は参照を生成する
キャスト
変数型
引数や戻り値の
型
関数呼び出しの
引数


# Page. 13

![Page Image](https://bcdn.docswell.com/page/8JDDRG2KJG.jpg)

Part 3.
抽象に
依存させよう
❖ 依存を制御する術を知る


# Page. 14

![Page Image](https://bcdn.docswell.com/page/VEPXW313J8.jpg)

３
抽象に依存させよう
参照を切るとは？
真の問題は、参照の連鎖
参照が連鎖すると、しばしば
本質的に相互を必要としてないアセット同士が結びつく
よって、不要な参照連鎖を起こさせない事が必要


# Page. 15

![Page Image](https://bcdn.docswell.com/page/27VL84YNEQ.jpg)

３
抽象に依存させよう
単方向の依存でも悩ましい例
◆
WBP_PlayerInfoに参照を追加すると、 WBP_PlayerInfoの総参照数が増加
◆
BP_PlayerCharacterに参照を追加すると、
BP_PlayerCharacterとWBP_PlayerInfoの総参照数が増加
◆
BP_Swordに参照を追加すると、
BP_SwordとBP_PlayerCharacterとWBP_PlayerInfoの総参照数が増加
11
7
3


# Page. 16

![Page Image](https://bcdn.docswell.com/page/5JGX51957L.jpg)

３
抽象に依存させよう
抽象に依存し、依存を切った図
？
？


# Page. 17

![Page Image](https://bcdn.docswell.com/page/47Q8ZDWLEP.jpg)

３
抽象に依存させよう
それぞれ抽象に依存すると参照アセットが波及しない
4
5
4


# Page. 18

![Page Image](https://bcdn.docswell.com/page/KE423ZK571.jpg)

３
抽象に依存させよう
BPクラスを抽象化する手段
C++の親クラス
◆ BPI（ブループリントインターフェース）
◆ 手ぶらの親クラス
◆ アクタータグ
◆
https://www.youtube.com/watch?v=0YMS2wnykbc
Blueprints In-depth - Part 2 | Unreal Fest Europe 2019 | Unreal Engine
で解説されている（日本語字幕あり）


# Page. 19

![Page Image](https://bcdn.docswell.com/page/L71M1RX2JG.jpg)

３
抽象に依存させよう
それぞれの手段の抽象を実現するクラス
クライアントとなるアセットにより抽象度の高いクラスを見てもらい、自身は見せない
抽象度高
抽象度低
両者の関係
クライアントに参
照させたい型
クライアントに参
照させない型
C++親クラス
C++クラス(親)
BPクラス(子)
継承
BPI
BPI
BPクラス
BPI実装
手ぶらの親クラス
BPクラス(親)
BPクラス(子)
継承
アクタータグ
AActor
BPクラス
実は継承
導入する手段


# Page. 20

![Page Image](https://bcdn.docswell.com/page/G7W381N272.jpg)

３
抽象に依存させよう
C++の親クラスを抽象化に用いる
AActorを直接継承せず
実装は空でもC++で親クラスを作っておく
クライアントにC++型を参照させることで
BP型への参照を回避できる


# Page. 21

![Page Image](https://bcdn.docswell.com/page/4JZV8P3473.jpg)

３
抽象に依存させよう
C++クラス型の参照はタダ
C++クラス型へのキャストは
アセット参照が増えない
BPクラスのように
.uassetではないため
BPクラスへのキャストの代わりに
C++クラスへのキャストで
済むか検討する癖をつけると良い


# Page. 22

![Page Image](https://bcdn.docswell.com/page/YE65PMXGJV.jpg)

３
抽象に依存させよう
C++のクラスにキャストして参照を回避できそうなもの
ACppCharacterBase::IsAliveはC++で実装されている点に注目
IsAliveを呼ぶために、BP_PlayerCharacterにキャストする必要は無い
より抽象度の高いCppPlayerCharacterにキャストすべき


# Page. 23

![Page Image](https://bcdn.docswell.com/page/GE5YKZXXE4.jpg)

３
抽象に依存させよう
BPIを抽象化に用いる
実装がBPに行われている時に有効


# Page. 24

![Page Image](https://bcdn.docswell.com/page/972GWRXQ7R.jpg)

３
抽象に依存させよう
BPIを導入するとよさそうな例
BP_GameModeを参照する
いくつかのBPが左に見える
これらは、BP_GameModeの
機能にアクセスしたいだけ
しかし結果として
BP_GameModeが参照する
アセット全てを間接的に参照


# Page. 25

![Page Image](https://bcdn.docswell.com/page/DJYVLD8YJM.jpg)

３
抽象に依存させよう
BPIを導入するとよさそうな例
BPI導入
BP_GameModeを参照していた
BPクラス達は
代わりにBPI_GameModeを
参照するように
BP_GameModeの時のように
右に続く参照の線が
無いことに注目


# Page. 26

![Page Image](https://bcdn.docswell.com/page/V7NM46QRE8.jpg)

３
抽象に依存させよう
BPI使用時の注意点
BPIも型情報を持つと参照が追加されるので注意！
引数や戻り値でBPクラス型を使うと参照が追加される。


# Page. 27

![Page Image](https://bcdn.docswell.com/page/YJ9NQLDZJ3.jpg)

３
抽象に依存させよう
手ぶらの親クラスを使って参照を減らす方法
末端のBPクラス（オレンジ色）にのみ
アセット（リソースやBPクラス型）
をもたせると参照の連鎖を切れる
中間のBPクラス（白色）はアセットを参照させない
クライアント（型の利用者）は
なるべく抽象度の高いクラスを見るようにする
(→オレンジ色はなるべく
参照しないように！ ）


# Page. 28

![Page Image](https://bcdn.docswell.com/page/GJ8KGX5YED.jpg)

３
抽象に依存させよう
手ぶらの親クラスの作り方
リソースやクラス型を可能な限り持たせない
親は手ぶらにし、子にリソースを
継承の末端の子クラスにリソースやクラス型を設定


# Page. 29

![Page Image](https://bcdn.docswell.com/page/LJLZG8Y97R.jpg)

３
抽象に依存させよう
アクタタグを使うことで、BPクラス型を参照しない
◆
アクタの種類判別にタグを使うとBPクラス型への参照を一切持つ必要がない
◆
タグはC++のAActorで定義されている


# Page. 30

![Page Image](https://bcdn.docswell.com/page/47MVQ6NV7W.jpg)

３
抽象に依存させよう
タグを利用して参照を回避する例
敵の数を返す関数実装例
上の例はBP_EnemyCharacter BP型を参照してしまう
下の例はC++型とタグを組み合わせ、BP型を参照せず同じ事を実現


# Page. 31

![Page Image](https://bcdn.docswell.com/page/P7R28PDWJ9.jpg)

３
抽象に依存させよう
まとめ
◆
クライアント（型の利用者）にはなるべく抽象度の高いクラスを参照させる
◆
アセット(グラフィックリソース等)はなるべく抽象度の低いクラスから参照させる
◆
抽象度を高める武器
⚫
C++の親クラス
⚫
BPI（ブループリントインターフェース）
⚫
手ぶらの親クラス
⚫
アクタータグ


# Page. 32

![Page Image](https://bcdn.docswell.com/page/PJXD831VEX.jpg)

Part 4.
分割して
疎結合とせよ
❖ BPを機能で分割すると参照数削減になる理由


# Page. 33

![Page Image](https://bcdn.docswell.com/page/3JKXKY25ED.jpg)

４
分割して疎結合とせよ
こんなアセットを見たことはありませんか？


# Page. 34

![Page Image](https://bcdn.docswell.com/page/LE35Z941J5.jpg)

４
分割して疎結合とせよ
参照のタコ足化
沢山のアセットに参照され、沢山を参照するアセットは
多数のアセットを相互に絡める元凶に
以下を継承するBPクラスは特にタコ足化しやすい
⚫
GameMode
⚫
PlayerController
⚫
GameState
⚫
GameInstance
⚫
ACharacter


# Page. 35

![Page Image](https://bcdn.docswell.com/page/8EDDRGQKEG.jpg)

４
分割して疎結合とせよ
例：神GameMode
GameModeが例えば以下を管轄していたとする
⚫
音楽再生
⚫
スコア管理
⚫
敵群衆制御
⚫
...
すると、これら１つを使うBPは
GameModeが持つ参照全てを参照
機能を分割するだけで参照数を減らせる見込みが高い


# Page. 36

![Page Image](https://bcdn.docswell.com/page/V7PXW3L3E8.jpg)

４
分割して疎結合とせよ
システム分割前
19
5
18
19
6
19
4


# Page. 37

![Page Image](https://bcdn.docswell.com/page/2JVL84QN7Q.jpg)

４
分割して疎結合とせよ
システム分割後
7
6
8
7
6
6
5
4
5


# Page. 38

![Page Image](https://bcdn.docswell.com/page/5EGX51W5JL.jpg)

４
分割して疎結合とせよ
Blueprint Function Libraryのタコ足化に注意
例えば、各型のオブジェクト型を返す関数ライブラリを作ってしまった場合
BP_MyFunctionLibraryは
以下を参照してしまう
●
●
●
●
●
BP_PlayerCharacer
BP_PlayerController
BP_EnemyCharacter
BP_GameMode
ABP_Player


# Page. 39

![Page Image](https://bcdn.docswell.com/page/4JQ8ZD3L7P.jpg)

４
分割して疎結合とせよ
システム分割前


# Page. 40

![Page Image](https://bcdn.docswell.com/page/K7423Z15J1.jpg)

４
分割して疎結合とせよ
BlueprintFunctionLibraryの潜在的危険
「ライブラリ」ゆえに、様々なBPクラスから参照される
BP_MyFunctionLibraryはアセット！
ライブラリ自体が参照を持つのは慎重に
解決策：
●
●
●
BPクラスへの参照を持たせない
関数ごとに別のBlueprintFunctionLibraryに分割する
BlueprintFunctionLibraryはC++だけで実装することにする


# Page. 41

![Page Image](https://bcdn.docswell.com/page/LJ1M1RG2EG.jpg)

４
分割して疎結合とせよ
コンポーネントのすすめ
実装をコンポーネントに逃がすと疎結合化しやすい
アクタの型を知らなくてもコンポーネントにアクセスできる


# Page. 42

![Page Image](https://bcdn.docswell.com/page/GJW381K2J2.jpg)

４
分割して疎結合とせよ
まとめ
◆
参照のタコ足化に警戒
神クラスは機能分割
⚫ BlueprintFunctionLibraryがBP型を参照する事に警戒
⚫
◆
コンポーネントは疎結合に役立つ


# Page. 43

![Page Image](https://bcdn.docswell.com/page/4EZV8PZ4J3.jpg)

Part 5.
量産コンテンツ管理
❖ アビリティ、アニメーション、アイテム...
キャラクタに参照させない作り方


# Page. 44

![Page Image](https://bcdn.docswell.com/page/Y765PMZGEV.jpg)

5
量産コンテンツ管理
量産コンテンツの参照切り離し
キャラクタが量産コンテンツを参照しないように注意
（例：アイテム、アビリティ、アニメーション）
Gameplay Ability や、
Animation Montage は役に立つ
必要なエフェクト、サウンド、
アニメーションへの参照を保持してくれる
キャラクタから
それらを直接参照する必要がなくなる


# Page. 45

![Page Image](https://bcdn.docswell.com/page/G75YKZWX74.jpg)

5
量産コンテンツ管理
ABP疎結合のすすめ
ABP（Animation Blueprint）は疎結合に保ちやすい
◆
ABPは「下請け」に徹すると、他のBPクラス型を参照しないようにしやすい
◆
ステートマシンよりAnimation Montage
＞＞AMから再生するアニメーションはABPが知る必要がない
＞＞ステートマシンに置いたアニメーションはABPが参照してしまう
AnimNotifyが入り始めるとアニメーションは肥大化しがちだが、
AMにAnimNotifyを置くようにすると、ABPは身軽に保てる


# Page. 46

![Page Image](https://bcdn.docswell.com/page/9J2GWRQQJR.jpg)

5
量産コンテンツ管理
量産コンテンツを管理するデータテーブルからはソフトリファレンス


# Page. 47

![Page Image](https://bcdn.docswell.com/page/DEYVLDWYEM.jpg)

5
量産コンテンツ管理
アセットを参照するデータテーブルの扱い
データテーブルが量産データ管理用なら
アセットはソフトリファレンスで持つ
(データアセットも同様）
ポイント
◆
データテーブルを直接参照するBPクラスを最小限にしておく
＞＞コントロールしやすい様に
◆
ソフトリファレンスは、自前のロードシステムが必要


# Page. 48

![Page Image](https://bcdn.docswell.com/page/VJNM469R78.jpg)

5
量産コンテンツ管理
まとめ
◆
量産コンテンツをキャラクタが直接持たないように
◆
Gameplay Abilityや、 Animation Montageなど
独立してアセット化できるものに量産コンテンツを結びつける
◆
データテーブルで量産コンテンツを管理するならソフトリファレンスも視野に
※ アニメーション、エフェクト、サウンド、アイテム、武具が量産コンテンツの一例


# Page. 49

![Page Image](https://bcdn.docswell.com/page/YE9NQL2ZE3.jpg)

全体のまとめ


# Page. 50

![Page Image](https://bcdn.docswell.com/page/GE8KGXMY7D.jpg)

参照連鎖を断つ手法
全体のまとめ
◆
BPクラス同士は抽象に依存させると参照連鎖を切れる
⚫
◆
C++親、BPI、手ぶらの親、アクタタグ
分割して疎結合に
多機能すぎるクラスを分割するだけで総参照数を削減を見込める
⚫ コンポーネントは疎結合化に役立つ
⚫
◆
量産コンテンツをキャラに持たせない
Gameplay Ability、Animation Montageに持たせる
⚫ アセットを持つデータテーブルは一箇所で管理
＞＞ソフトリファレンス化も視野に
⚫


# Page. 51

![Page Image](https://bcdn.docswell.com/page/LELZG839JR.jpg)

「
Reference ViewerとSize Mapは便利なので、
時々眺めてくれると嬉しいです。
多くの人が関心を持つことで参照連鎖は解消できます。
この資料がその一助になれば幸いです。
ご清聴ありがとうございました！
」


