---
title: バイキング流UE4活用術 ～BPとお別れするまでの18ヶ月～
tags:  #ue4 #unreal engine 4  
author: [エピック ゲームズ ジャパン](https://convert.docswell.com/user/EpicGamesJapan)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/4VEP441VJ8.jpg?width=480
description: 2017/10/8(日)に行われたUNREAL FEST EAST 2017における株式会社バイキング様の講演「バイキング流UE4活用術 ～BPとお別れするまでの18ヶ月～」で使用された資料です。   https://unrealevent.eventcloudmix.com/     スライドに埋め込まれた動画に関しましては、以下のURLにてご確認ください。   https://youtu.be/15CKcLAWSFU
published: October 12, 17
canonical: https://convert.docswell.com/s/EpicGamesJapan/5Y1QEK-ue4-bp18
---
# Page. 1

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

バイキング流UE4活用術
～BPとお別れするまでの18ヶ月～
株式会社バイキング
瀬田 宗治
奥井 健
芹沢 仁
#ue4fest


# Page. 2

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

株式会社バイキング
多人数の通信対戦アクションゲームをよく作っている会社です
© 2012 SQUARE ENIX CO., LTD. All Rights Reserved.
#ue4fest


# Page. 3

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

芹沢 仁
火事場のプログラマー
サーバー周り、ＵＩ、ツール等幅広く開発を担当
瀬田 宗治
プログラマーグレート
マジシャンズデッドではモーショ
ンセンサーを使ってモノを掴んで
投げたりするギミックを担当
奥井 健
#ue4fest
癒し系プログラマー
「ガンスリンガーストラトス」「マジシャンズデッド」で
カメラやアニメーションシステムを担当


# Page. 4

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

本日の話
• BP出会いから別れまでのストーリー
• BPからC++への移行
• モジュール分割
• プロジェクトの運用
• アニメーション
#ue4fest


# Page. 5

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

「マジシャンズ・デッド」
プロジェクト概要
• 開発人数
プランナー： ６人
プログラマ：１８人
モーション： ８人
デザイナ ：３５人
サウンド ： ２人
• 開発期間
約18ヶ月
• UEのバージョン
4.6～4.12
• 非同期通信3対3オンラインアクションゲーム
• 非接触入力デバイス
#ue4fest


# Page. 6

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

BP出会いから別れまでのストーリー
#ue4fest


# Page. 7

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

初めてのUE4
どうしていいか分からなかったので
ヒストリアさんにサポートをお願いしました
#ue4fest


# Page. 8

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

S氏曰く
「まずはＢＰでロジックを組むといいよ」
「後でボトルネックになったとこをネイティブ化したらいいよ」
#ue4fest


# Page. 9

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

この言葉で私たちは
「時代はBPだ！全部BPで書けば良いんだ！」
とBP信者になりました。
#ue4fest


# Page. 10

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

BPだと同時に編集できない問題は
ActorComponentで分割すれば解決するはず！
とコンポーネント分割を推し進める
#ue4fest


# Page. 11

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

BPでできたActorComponentを継承したBP、
さらにそれを継承したBP、どんどん複雑化していく
部品たち
だんだんプロジェクトも大きくなってきた
アセットも増えてきた
#ue4fest


# Page. 12

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

急に問題が出始める
#ue4fest


# Page. 13

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

• BPインターフェースは検索に引っかからない！
どういうことだ！！
• なんかコンパイルに待たされるようになってきた！
• フレームレートが出ない
• 処理の流れを確認したい、デバッグしよう、うん？
なんか変数の値が見れないぞ？ファンクションライブラリに書
くと見れない？
• やっぱりマージができない！
#ue4fest


# Page. 14

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

• BPインターフェースは検索に引っかからない！
どういうことだ！！ （現在は解決済み）
• なんかコンパイルに待たされるようになってきた！
• フレームレートが出ない
• 処理の流れを確認したい、デバッグしよう、うん？
なんか変数の値が見れないぞ？ファンクションライブラリに書
くと見れない？ （現在は解決済み）
• やっぱりマージができない！
#ue4fest


# Page. 15

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

• なんかコンパイルに待たされるようになってきた！
• フレームレートが出ない
• 処理の流れを確認したい、デバッグしよう、うん？
• やっぱりマージができない！
#ue4fest


# Page. 16

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

コンパイルに待たされるようになってきた！
どうやらBPの被参照数が多いほど
コンパイルに時間がかかる事がわかった
#ue4fest


# Page. 17

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

コンパイルに待たされるようになってきた！
被参照数は以下の要領でどんどん増えていく
• 変数でBPを保持された
• SpawnActorでBPを生成された
• BPが継承された
#ue4fest


# Page. 18

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

コンパイルに待たされるようになってきた！
被参照数は以下の要領でどんどん増えていく
• 変数でBPを保持された
• SpawnActorでBPを生成された
• BPが継承された
→BPを１つ継承すると、継承元の全てのBPク
ラスの被参照数が増える
#ue4fest


# Page. 19

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

コンパイルに待たされるようになってきた！
BpClass1
BpClass2
#ue4fest


# Page. 20

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

コンパイルに待たされるようになってきた！
BpClass1
BpClass3
BpClass2
BpClass3
#ue4fest


# Page. 21

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

コンパイルに待たされるようになってきた！
BpClass1
BpClass3
BpClass2
BpClass3
#ue4fest
派生先の末端まで
非参照として
追加される


# Page. 22

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

コンパイルに待たされるようになってきた！
実際にコンパイル時間を計測
4
8
16
32
:
0.8sec
1.6sec
2.0sec
3.8sec
※Intel(R) Core(TM) i7-5820K 3.30GHz 6コアにて計測
#ue4fest


# Page. 23

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

コンパイルに待たされるようになってきた！
実際にコンパイル時間を計測
4
8
16
32
:
256
0.8sec
1.6sec
2.0sec
3.8sec
33sec
※Intel(R) Core(TM) i7-5820K 3.30GHz 6コアにて計測
#ue4fest


# Page. 24

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

コンパイルに待たされるようになってきた！
マジシャンズ・デッドでは350以上の参照を持つＢＰも！
#ue4fest


# Page. 25

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

コンパイルに待たされるようになってきた！
マジシャンズ・デッドでは350以上の参照を持つＢＰも！
基底クラスをＣ＋＋化する事で改善
Ｃ＋＋の基底クラスを用意
#ue4fest


# Page. 26

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

• なんかコンパイルに待たされるようになってきた！
• フレームレートが出ない
• 処理の流れを確認したい、デバッグしよう、うん？
• やっぱりマージができない！
#ue4fest


# Page. 27

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

フレームレートが出ない
• BPの構造体は値渡し
• 想定外の挙動
#ue4fest


# Page. 28

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

フレームレートが出ない
１０
１０
GetArray、GetArray2がそれぞれ１０個の配列を返す場合
#ue4fest


# Page. 29

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

フレームレートが出ない
GetArrayは111回GetArray2は210回呼ばれる
#ue4fest


# Page. 30

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

フレームレートが出ない
• Pure関数は参照時に実行される
#ue4fest


# Page. 31

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

フレームレートが出ない
• Pure関数は参照時に実行される
• ForEachLoopマクロは要素数の
取得の為、内部で要素数＋１だ
けGetArrayを呼び出している
#ue4fest


# Page. 32

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

フレームレートが出ない
• Pure関数は参照時に実行される
ForEachLoopマクロ内
#ue4fest


# Page. 33

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

フレームレートが出ない
• Pure関数は参照時に実行される
要素毎の処理
要素数比較
ForEachLoopマクロ内
#ue4fest


# Page. 34

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

フレームレートが出ない
• Pure関数は参照時に実行される
• ForEachLoopマクロは要素数の
取得の為、内部で要素数＋１だ
けGetArrayを呼び出している
• ForEachLoopのArray Element
を参照する時も呼び出される
#ue4fest


# Page. 35

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

フレームレートが出ない
１０
１０
11
110
100
100
Pure関数の呼び出し回数
#ue4fest


# Page. 36

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

フレームレートが出ない
１０
１０
11
110
100
100
Pure関数の呼び出し回数
#ue4fest


# Page. 37

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

フレームレートが出ない
GetArray、GetArray2をC++に置き換えた
UFUNCTION(BlueprintPure)
const TArray&lt;FVector&gt;&amp; GetArrayNative() const { return m_array; }
UFUNCTION(BlueprintPure)
const TArray&lt;FVector&gt;&amp; GetArrayNative2() const { return m_array2; }
Pure関数の呼び出し回数
#ue4fest


# Page. 38

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

フレームレートが出ない
GetArray、GetArray2をC++に置き換えた
UFUNCTION(BlueprintPure)
const TArray&lt;FVector&gt;&amp; GetArrayNative() const { return m_array; }
UFUNCTION(BlueprintPure)
const TArray&lt;FVector&gt;&amp; GetArrayNative2() const { return m_array2; }
負荷が軽減！
•GetArray 0.134ms→0.057ms
Pure関数の呼び出し回数
•GetArray2 0.146ms→0.083ms
#ue4fest


# Page. 39

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

• なんかコンパイルに待たされるようになってきた！
• フレームレートが出ない
• 処理の流れを確認したい、デバッグしよう、うん？
• やっぱりマージができない！
#ue4fest


# Page. 40

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

デバッグしよう、うん？
• アタッチでメンバ変数が見づらい
• アタッチでスタックトレース追うのが大変
• スタンドアローンでしか起きない不具合
#ue4fest


# Page. 41

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

デバッグしよう、うん？
• アタッチでメンバ変数が見づらい
• アタッチでスタックトレース追うのが大変
• スタンドアローンでしか起きない不具合
#ue4fest


# Page. 42

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

デバッグしよう、うん？
• アタッチでメンバ変数が見づらい
• アタッチでスタックトレース追うのが大変
• スタンドアローンでしか起きない不具合
#ue4fest


# Page. 43

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

デバッグしよう、うん？
• アタッチでメンバ変数が見づらい
• アタッチでスタックトレース追うのが大変
• スタンドアローンでしか起きない不具合
→結果、ログを残して再発を待つデバッグに
#ue4fest


# Page. 44

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

• なんかコンパイルに待たされるようになってきた！
• フレームレートが出ない
• 処理の流れを確認したい、デバッグしよう、うん？
• やっぱりマージができない！
#ue4fest


# Page. 45

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

みんなBPがいやになってくる
#ue4fest


# Page. 46

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

BP部分のNative化が始まる
#ue4fest


# Page. 47

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

Native化に苦しめられる
#ue4fest


# Page. 48

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

Native化に苦しめられる
•失って気づくBPのやさしさ
•BpEnum、Bp構造体の問題
#ue4fest


# Page. 49

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

Native化に苦しめられる
•失って気づくBPのやさしさ
・nullptrをアクセスする事によるハング
•BpEnum、Bp構造体の問題
#ue4fest


# Page. 50

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

Native化に苦しめられる
•失って気づくBPのやさしさ
・nullptrをアクセスする事によるハング
•BpEnum、Bp構造体の問題
・ Native化しようとしているBpで使用されている全
てのBpEnum、Bp構造体を
C++に変更しないとNative化できない
#ue4fest


# Page. 51

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

結局、全部をNative化することは
できなかった
#ue4fest


# Page. 52

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

マジシャンズデッドでのBPガイドライン
• デザイナが触るBPとプログラマが触るBPをできるだけ分ける
• BPクラスを継承したBPクラスを作らない
• BPクラスは自作のC++クラスを継承させる
• Enum、構造体はC++で定義する
• メンバ変数はC++で用意する
#ue4fest


# Page. 53

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

マジシャンズデッドでのBPガイドライン
• デザイナが触るBPとプログラマが触るBPをできるだけ分ける
→競合対策
• BPクラスを継承したBPクラスを作らない
• BPクラスは自作のC++クラスを継承させる
• Enum、構造体はC++で定義する
→Native化対策
• メンバ変数はC++で用意する
→デバッグ対策
#ue4fest


# Page. 54

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

まとめ
•BP、C++の使い分けを考える
•BPからC++への移行はコストがかかる
#ue4fest


# Page. 55

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

まとめ
•BP、C++の使い分けを考える
・試作などは編集と反映のサイクルを短くできる
・デザイナのUIとして
・複数人で同時にＢＰを触るような規模のプロジェク
トになるとつらい
•BPからC++への移行はコストがかかる
#ue4fest


# Page. 56

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

まとめ
•BP、C++の使い分けを考える
・試作などは編集と反映のサイクルを短くできる
・デザイナのUIとして
・複数人で同時にＢＰを触るような規模のプロジェク
トになるとつらい
•BPからC++への移行はコストがかかる
・移行する可能性があるなら最初からC++で作る
#ue4fest


# Page. 57

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

結論
Blueprintは
恋人
結婚するなら C++
#ue4fest


# Page. 58

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

BPからC++への移行
モジュール分割
UE4プロジェクトの運用
#ue4fest


# Page. 59

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

BPからC++への移行
1. SpawnActorに引数を渡したい場合
2. GC起因の不正アクセス
#ue4fest


# Page. 60

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

SpawnActorに引数を渡したい
#ue4fest


# Page. 61

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

BPの場合
1. Actorを作成
2. BPに変数を作成
3. 変数を選択して
Editable と
Expose on Spawn に
チェックを入れる
#ue4fest


# Page. 62

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

BPの場合
4. SpawnActorFromClassノードでアクタを指定
5. 引数がノードにあらわれるので設定
#ue4fest


# Page. 63

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

C++の場合
1. SpawnActor の代わりに SpawnActorDeferred を使用
2. 変数を書き換えたり、関数呼び出したりする
3. FinishSpawningActorを呼び出す
OnConstruction や BeginPlay が呼ばれる前に値を設定可能
#ue4fest


# Page. 64

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

C++の記述例
UWorld* World = GetWorld();
FTransform Transform(FVector(0.0f, 0.0f, 100.0f));
FVector Speed(10.0f, 0.0f, 0.0f);
auto* MyActor = World-&gt;SpawnActorDeferred&lt;AMyActor&gt;(AMyActor::StaticClass(), Transform);
#ue4fest
MyActor-&gt;bAttack = true;
MyActor-&gt;SetSpeed(Speed);
//攻撃状態で出現
//速度設定
MyActor-&gt;FinishSpawning(Transform);
// OnConstruction,BeginPlayが呼ばれる


# Page. 65

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

GC(ガベージコレクション)起因のクラッシュ
#ue4fest


# Page. 66

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

GC(ガベージコレクション)によるクラッシュ
• 何もしていないのにクラッシュ
• クラッシュのタイミングが不定
• BPで組んでいたときは発生して
いなかった
• 突然ポインタの先が壊れる
GCによるクラッシュの可能性が
あります。
#ue4fest
立っていただけなのにクラッシュ？？


# Page. 67

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

UE4のGC(ガベージコレクション)
• 不要となった UObject を定期的に自動削除する機能
• 不要かどうかの判定は参照ツリーに含まれるかどうか
• GCの対象から外すためには UPROPERTY をつける
UPROPERTY
#ue4fest


# Page. 68

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

参照ツリー
Actor
UPROPERTY
UObject
Actor
UPROPERTY
UObject
root set
参照されていないUObjectはGC対象となる
UObject
#ue4fest


# Page. 69

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

変数に UPROPERTY() をつけて参照を持つ
.h
class GAME_API UMyObject : public UObject
{
}
class GAME_API AMyActor : public AActor
{
UPROPERTY()
UMyObject* MyObject;
};
.cpp
{
MyObject = NewObject&lt;UMyObject&gt;();
}
#ue4fest


# Page. 70

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

参照ツリーに追加されているか注意
• クラスや構造体をメンバに持つ場合にも注意
• メンバを含んだクラスや構造体にも UPROPERTY が必要
• root set から参照がたどれているかを意識する
#ue4fest


# Page. 71

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

参照ツリーから外れているケース
.h
USTRUCT()
struct FMyData
{
UPROPERTY()
UObject* MyObject;
};
// 参照を持っているつもり
UCLASS()
class GAMEMODULE_API AMyActor : public AActor
{
GENERATED_BODY()
FMyData MyData;
};
#ue4fest
// ここで参照が切れている


# Page. 72

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

途中で切れた参照ツリー
参照されていないためGC対象となる
root set
#ue4fest
MyActor
FMyData
UPROPERTY
UMyObject


# Page. 73

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

参照ツリーにつながっているケース
.h
USTRUCT()
struct FMyData
{
UPROPERTY()
UObject* MyObject;
};
// 参照を持つ
UCLASS()
class GAMEMODULE_API AMyActor : public AActor
{
GENERATED_BODY()
UPROPERTY()
FMyData MyData;
};
#ue4fest
// 参照を持つ


# Page. 74

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

参照ツリーに繋がっている
参照されているためGC対象とならない
root set
#ue4fest
MyActor
UPROPERTY
FMyData
UPROPERTY
UMyObject


# Page. 75

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

TArrayに格納する場合も同様
.h
USTRUCT()
struct FMyData
{
UPROPERTY()
UObject* MyObject;
};
// 参照を持つ
UCLASS()
class GAMEMODULE_API AMyActor : public AActor
{
GENERATED_BODY()
UPROPERTY()
// 参照を持つ
TArray&lt;FMyData*&gt; MyData;
};
#ue4fest


# Page. 76

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

参照ツリーを意識しよう！
#ue4fest


# Page. 77

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

モジュール構成
#ue4fest


# Page. 78

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

UE4のモジュール
• エンジンそのものがモジュールの集まりで構成されている
• ゲームも複数のモジュールに分割することができる
#ue4fest


# Page. 79

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

モジュール分割した経緯
• ビルド時間の短縮が見込めるはず
• ソースの依存度を減らしてスッキリ
• ツールやデバッグの機能も分割、リリース時は除外
とにかくやってみたかった！
#ue4fest


# Page. 80

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

ソースの依存度を減らしたい
適当に組むとこうなりがち
オブジェクト
オブジェクト
オブジェクト
#ue4fest


# Page. 81

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

ソースの依存度を減らしたい
こうしたい！
オブジェクト
オブジェクト
#ue4fest
オブジェクト


# Page. 82

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

モジュール単位でのコントロールは可能
基本モジュール
拡張モジュール１
拡張モジュール２
許可されていない方向の参照はビルドエラーにできる！
#ue4fest


# Page. 83

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

モジュールの参照ルール
• モジュール間の依存度を下げるため一方通行の参照を設定
《ルール》
• 各モジュールにレベルを設定
• 下のレベルから上のレベルへの参照は可
• 同じレベル内での水平参照も不可
《注意》
• 相互依存はコンパイル時間に関して問題がある
• 変数の静的初期化で問題を生じる場合がある
#ue4fest


# Page. 84

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

モジュールの参照イメージ
上位のモジュール
参照
#ue4fest
参照
参照
下位のモジュール
参照
中位のモジュール
下位のモジュール


# Page. 85

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

マジシャンズデッドのモジュール構成
参照方向
#ue4fest
レベル
モジュール
L0
EngineModule
L1
SystemModule
L2
NetworkModule, USBIOModule
L3
CommonDataModule, UserDataModule, ResidentModule
L4
ActorModule, ControllerModule, ServerModule
L5
BppGame, BppGameEd
L6
CharacterModule, HudModule
L7
OutGameModule
L8
BattleAIModule, BattleCharacterModule
L9
DebugModule
L10
DevelopEditorModule


# Page. 86

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

メリットは享受できたと思うのですが
#ue4fest


# Page. 87

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

分割しすぎた
#ue4fest


# Page. 88

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

モジュール分割のデメリット
• モジュール間の依存関係が複雑になる
• どのモジュールに作成すべきか考えないといけない
• モジュール間の移動に手間がかかる
#ue4fest


# Page. 89

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

モジュール間を移動すると
クラス や 構造体 を異なる
モジュールに移動
BPの参照が切れて
アセットが壊れる
#ue4fest


# Page. 90

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

モジュール間を移動するには
#ue4fest


# Page. 91

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

ActiveClassRedirects に指定
モジュール間を移動した場合は移動先のモジュールと名前を
DefaultEngine.iniのActiveClassRedirectsに記述する
例
Game/Config/DefaultEngine.ini
[/Script/Engine.Engine]
+ActiveClassRedirects=(OldClassName=“MyClass&quot;,NewClassName=&quot;/Script/BattleModule.MyClass &quot;)
クラス名を変更したときにも使えるので便利！
#ue4fest


# Page. 92

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

モジュール構成の提案
プロジェクト規模にもよりますが
ゲーム部分は数モジュールの分割で十分かも
例）
• System
• Common
• Battle / OutGame
• Primary(ゲームプロジェクト名)
※ ツール、デバッグなどのモジュールは除く
#ue4fest


# Page. 93

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

Systemモジュール
• System
• システム共有の実装（他タイトルでも使用可能）
• アセット参照不可
• 可能なものは出来るだけプラグイン化を検討する
例
描画、アニメーション、サウンド、I/O
ストレージなどの基本機能
• Common
• Battle / OutGame
• プライマリ
#ue4fest


# Page. 94

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

モジュール構成図
System
#ue4fest


# Page. 95

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

Commonモジュール
• System
• Common
• ゲームごとの実装ではあるが、
ゲームを通して共通の処理
• アセット参照可
例
ゲーム共通のアニメーション
• Battle / OutGame
• プライマリ
#ue4fest


# Page. 96

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

モジュール構成図
System
Common
#ue4fest


# Page. 97

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

Battle/OutGameモジュール
• System
• Common
• Battle / OutGame
• バトルとアウトゲームでは必要な機能が異なることが
多いので、それぞれ固有の実装はモジュールを分ける
ようにしてシンプルにする。
• プライマリ
#ue4fest


# Page. 98

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

モジュール構成図
System
Common
Battle
#ue4fest
OutGame


# Page. 99

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

モジュール構成例
• System
• Common
• Battle / OutGame
• Primary
• とりあえず必要なのでこのへんに
• 全てのモジュールにアクセス可能な存在
• なるべく使用しない
#ue4fest


# Page. 100

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

モジュール構成図
System
Common
Battle
OutGame
Primary
#ue4fest


# Page. 101

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

UE4プロジェクトの運用
#ue4fest


# Page. 102

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

作業PCスペック
• OS
• CPU
• メモリ
• グラフィック
• SSD
• HDD
Windows10 Pro 64-bit
Intel Core i7 5820K 3.3GHz
16 GB
NVIDIA GeForce GTX 960
500 GB
2 TB
公式推奨よりもかなりイイ
#ue4fest


# Page. 103

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

オススメはSSD
いまならNVMeのSSDがなおよし
#ue4fest


# Page. 104

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

SSDの使用を推奨
大幅に作業時間が短縮できました
• ビルド時間の短縮
• UE4起動時間の短縮
• アセット読み込み・保存時間の短縮
• いろいろはかどります
#ue4fest


# Page. 105

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

プロジェクト管理
Subversionを使用
• UE4インテグレートがされている
• スタッフの習熟度がPerforceよりも高い
• Gitはbeta版なので見送り
• 無料
#ue4fest


# Page. 106

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

非プログラマの場合
• エディタのソースコントロールを使用
• エディタからコミット
• アセットがコミット対象
メリット
• 手軽でわかりやすい
デメリット
• 参照時にsvnのステータスをサーバに
問い合わせるので動作が重い
(サーバの混雑度合いによる)
#ue4fest


# Page. 107

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

プログラマの場合
• コミット対象
• BPソースファイル
• Cソースファイル
• exe
• dll
• pdb(デバッグに必要)
など
• TortoiseSVNを使用
#ue4fest


# Page. 108

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

プログラマの作業フロー
1. プロジェクト更新
2. Cソースを更新して実装
3. ビルドして実行確認
4. Cソース、モジュールのdll、pdbをコミット
#ue4fest


# Page. 109

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

ちょっと問題が
#ue4fest


# Page. 110

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

dllコミット時にコンフリクトが発生
• Cソースは基本的にはマージされますが、
dllはバイナリのためマージ不可。
• 同じモジュールのCソースを同時に編集した場合
コンフリクトが起きる。
#ue4fest


# Page. 111

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

dllはコミットせず自動で作成！
#ue4fest


# Page. 112

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

Jenkinsによる自動ビルド
• プログラマはソースファイルをコミット
• Jenkinsがコミットを検知してdllを作成
• 作成したdllをコミット
dllのコンフリクトが解決された！
#ue4fest


# Page. 113

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

commit時のdllコンフリクトは解決されたが
#ue4fest


# Page. 114

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

今度はupdate時にdllコンフリクトが発生
#ue4fest


# Page. 115

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

excludeを指定
• プログラマはdllをローカルでビルドするためコンフリクトが発生
• ローカルのものだけを信用すればよいのでリポジトリのdllは不要
• exclude指定することでローカルのみSubversion管理から外す
例
svn update --set-depth exclude BppGame¥Binaries¥Win64¥UE4Editor-SystemModule.dll
#ue4fest


# Page. 116

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

他にも問題が
#ue4fest


# Page. 117

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

プロジェクトの更新時間が長い？
#ue4fest


# Page. 118

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

pdbファイルが原因
• サイズが大きいためストレージとネットワークの帯域を消費し
てしまう。
• 通常は不要だけどデバッグ時に必要なので管理はしたい
Subversion管理せず、シンボルサーバを利用
#ue4fest


# Page. 119

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

Jenkinsに任せていたこと
• dllのビルドと更新
• dllビルドエラーチェック
• パッケージ作成
• 筐体へのインストール＆ゲーム起動
#ue4fest


# Page. 120

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

ビルドエラーが発生した場合
• JenkinsからSlackでプログラマにエラーを通知して知らせる
エラー時とエラー復帰時に通知
#ue4fest


# Page. 121

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

まとめ
•参照ツリーを意識する
•モジュールは分割しすぎない
（無理に分割する必要はない）
•SSDがおすすめ
#ue4fest


# Page. 122

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

アニメーション
1.アニメーションの共有、
2.ステート管理、
3.AnimGraphはどう作ればええの？
#ue4fest


# Page. 123

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

１．アニメーションの共有
• モデルが変わると同じアニメーションが再生できな
い？？
• AnimGraphが共有できない？？
結論
Skeletonを１個にする！
#ue4fest


# Page. 124

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

ドラゴンも一緒
• １つのSkeletonに全キャ
ラの骨がマージされる
（722本あった）
• モデルに存在しない骨は
無視されるので大丈夫！
• 骨の名前がかぶらないよ
うに注意
#ue4fest


# Page. 125

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

とりあえずこれをやれば再生できる１
骨ごとにリターゲットの設定
#ue4fest
キャラ固有骨、顔
Animation
アニメーションで骨の位置を動かす骨
AnimationScale
アニメーションで骨の位置を動かさない骨
Skeleton


# Page. 126

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

とりあえずこれをやれば再生できる２
リターゲットソース
• SkeletonのRetargetManagerで設定
• キャラ固有モーションを作る時に必要（後で説明）
• 登録するモデルはメモリ削減のためマテリアル無し
のモデルにする
#ue4fest
キ
ャ
ラ
モ
デ
ル
へ
の
参
照
が
い
っ
ぱ
い


# Page. 127

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

足が浮く！埋まる！
「骨の構造に問題がある場合１」
• 腰の移動値を入れる骨とRootの間に
骨を追加してはいけない
• ボーンスペースのTrans値を元に倍率
COG
が計算されるので途中に骨があると
（腰の移動値） 正しい倍率でリターゲットされない
これ、ダメ
Root
#ue4fest
• ただし、Rootと同じ位置に追加する
分には大丈夫


# Page. 128

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

足が浮く！埋まる！
「骨の構造に問題がある場合２」
極端な例
• 「ひざ上」と「ひざ下」の比率が
違うと足を曲げた時に高さが変わ
る。左の例は直立している時は同
じ長さだけど曲げるとズレる
• よくあるのが「ハイヒール」
• すこしくらいならIKでごまかす
#ue4fest


# Page. 129

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

足が浮く！埋まる！
キャラ固有モーションとは？
• リターゲットしなくてもいいモーション
• キャラ専用のリグで出力したモーションのこと
この設定を間違えると足が浮いたり埋まったりする
ここでどのキャラ固有なのかを指定
しないといけない
リターゲットマネージャで登録した
名前が出てくる
#ue4fest


# Page. 130

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

足が浮く！埋まる！
この設定、アセットごとに手動で設定しないといけない・・・
そんなんいややー！
#ue4fest


# Page. 131

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

自動化しました
• アニメーションインポートプラグインを作成した
• コンテンツブラウザの右クリックにアイコンを追加
• 特定のキャラのモーションを一括でインポート
• 更新されているかはハッシュ値で比較
• インポートするフォルダ名からリターゲットソース
の値を生成して設定
• Additive設定、Notify、MetaDataなどの設定は
テンプレート（主人公）から自動でコピー
• モンタージュやブレンドスペースの自動生成、
AnimBPのアセットの参照付け替えの自動化
プラグインの作り方：http://historia.co.jp/archives/367
#ue4fest


# Page. 132

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

アセットのロード
• ファイル名でStaticLoadする。キャラごとのアセット名は同じ
例： Pl001/Animation/co0000_Idle
Pl200/Animation/co0000_Idle
• ゲーム起動時に各キャラごとにアニメーションアセットのパス
を生成
• パスの生成ルールは以下の順にファイルの存在チェックをして
優先度の高いものが使われる
#ue4fest
キャラ固有モーション 性別共通
共通


# Page. 133

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

アニメーション使う時
• 標準のPlayAnimationは直接使わなかった
• 引数にアセット設定したらコードを再利用できない
• Idを指定して再生するPlayAnimationを作った
• こうしておくとキャラを新規追加し
てもすぐにゲームでプレイできる
• データがない場合は共通モーション
（主人公のモーション）が再生され
る
#ue4fest


# Page. 134

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

骨の階層を変更しようとすると面倒
対処法
1. 古いモデルを削除
2. 共通スケルトンを開き、TransrationRetargettingの設定をメモ（３
番の手順をするとずれてしまうので）
3. Asset→RemoveUnusedBonesFromSkeletonを実行し、古い骨を
削除
4. 新しい骨のモデルをインポート
5. メモしておいたTransrationRetargettingの設定を見ながらずれてい
る部分を修正
6. リターゲットマネージャでリターゲットソースを再設定
7. 全モーション再インポート
#ue4fest


# Page. 135

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

共通だけど変えたい（´･ω･｀）
• ヤラレは共通モーション
• 武器を持っていると手が不
自然、小物がめり込んじゃ
う
• 部分的に上書きしたい、
データドリブンに・・・
• DyanmicLayerBlendという
ノード実装した
修正前
#ue4fest
修正後


# Page. 136

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

使用したデータ
#ue4fest


# Page. 137

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

２．ステート管理について
• Actionという単位でクラスを作ってそれを切り替えて管理
• ながらアクションが可能なようにMainとSubの２レイヤー
使えるようにした
BeginAction
アクション起動時によばれる
EndAction
アクション終了時によばれる
ActionTick
アクションが起動中のみ毎フレよばれる
LocalActionTick
クライアントのみよばれる版
CheckShiftableAction
指定アクションへの遷移が可能かを定義
#ue4fest


# Page. 138

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

２．ステート管理について
ゲームシステム側のステート
マシンは良いとして
↑これ、AnimBPのステートマシンを使うべきか、
使わざるべきか
#ue4fest


# Page. 139

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

AnimBPステートマシンのメリット・デメリット
■メリット
•通信量が抑えられる
• ゲームシステム側のステートや移動量などすでに同期済みのステート
を参照してアニメーションを切り替える場合
■デメリット
•キャラごとにカスタマイズできない
•ゲームシステムのステートマシンと二重管理になる
•通常行動でモンタージュが使いづらい
#ue4fest


# Page. 140

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

マジシャンズデッドではどうしたか
•マジシャンズデッドでは使わ
なかった
•もっと大人数の通信対戦だっ
たら使ったほうがいいかもし
れない
#ue4fest


# Page. 141

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

ネットワーク同期はアニメーション単位
• アクション遷移はRPCで送って同期する
• アクション個別の処理は基本クライアント
のみLocalActionTickに書く
• アニメーションの再生タイミングをRPCで
同期する
#ue4fest


# Page. 142

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

エフェクトやSe、ヒット判定など同期は？
• 可能な限りAnimNotifyに仕込む
• AnimNotifyとはアニメーション
の特定フレームでイベントを発
生させるための機能です
• →はとある格闘３段目のNotify
#ue4fest


# Page. 143

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

アニメーションの再生タイミング
さえ同期しとけばなんとかなる！
#ue4fest


# Page. 144

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

３.AnimGraph
#ue4fest


# Page. 145

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

#ue4fest


# Page. 146

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

AnimGraph
親指
人差し指
中指
薬指
小指
#ue4fest


# Page. 147

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

AnimGraph
#ue4fest


# Page. 148

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

アニメーションが無い＝歩き
• アニメーションはSlotに流す
• Slotが空だとSourceのブレンドスペース（歩き）が出る
• 攻撃中はエイミングポーズを上半身にブレンド
#ue4fest


# Page. 149

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

補助骨やキャラ固有処理はどこに書く？
• Post Process AnimBPに書くと良い
• UE4.14で実装された。もっと早く欲しかった・・・
• 「SkeletalMeshに設定できる」第２のAnimBP
• ラグドールなど物理の後に実行されるので
補助骨に最適
#ue4fest


# Page. 150

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

AnimBPは
まとめ
Skeletonと結合しているので再利用性
が低くなりがち。でも大丈夫！
Skeletonを１個にすれば乗り切れる！
#ue4fest


# Page. 151

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

おしまい
#ue4fest


# Page. 152

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

ご清聴ありがとうございました
#ue4fest


# Page. 153

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

#ue4fest


