シヴァのブログ

UnityやUE4や趣味とかいろいろ...

第5回ue4ハンズオンセミナー

第5回ue4ハンズオンセミナーで、
Unreal Engineの簡単なゲーム開発を学んできました。
セミナーでPC忘れましたけど。

内容は忘れないようにメモ。
以下が、スライド。

www.slideshare.net

ツイッタ―:#ue4study

基本的にこの記事に書くことは、
「ゲームの作り方」ではなく、
・知らなかったこと
・気になったこと
・あとで思い出したいこと
・スライドの追加説明
などです。
ゲームを開発したい人はスライドを見て下さい。

プロジェクト作成

『デスクトップ/コンソール』→『モバイル/タブレット
『ハイエンド』→『スケーラブルな3D・2D』

・ハイエンドとスケーラブルな3D・2Dの違いについて
以下の2つが主な違いとなる。
①Motino BlurとAuto Exposureの有無
②Anti-Aliasing Methodが「None」か「Temporal AA」になるか

f:id:shivaT:20150706121324p:plain


・Motino Blur(モーションブラー)について
カメラで撮影したとき、動く物体がブレる現象のこと。
※Motino Blurについて詳しくは以下のサイトへdocs.unrealengine.com

・Auto Exposure(または、Eye Adaptation)について
暗闇から光の強い空間にでると目が少しずつ慣れて、周辺が見やすくなるという現象のこと。
※Auto Exposureについて詳しくは以下のサイトへdocs.unrealengine.com


・Anti-Aliasing(アンチエイリアス)について
描画されているものが微妙に尖っていたり、
ジャギジャギがでているものに対して滑らかに見えるように処理を加えること。
※Anti-Aliasingについて詳しくは以下のサイトへdocs.unrealengine.com
または、www.4gamer.net

アンチエイリアスの比較

FPSの表示方法

f:id:shivaT:20150710010634p:plain

ノード名(英語または日本語)の変更について

UE4.8よりノード名が英語と日本語が選択できるようになったとのこと。
メニューから『エディタの環境設定』→『地域&言語』→『Use Localized Graph Editor Nodes and Pins』のチェックを外す。
f:id:shivaT:20150706140337p:plain

マウス入力をタッチ扱いにしない方法

『デスクトップ/コンソール』→『モバイル/タブレット』にした場合、
マウス入力がタッチ扱い』になっている。
メニューから『編集』→『プロジェクト設定』→ 『インプット』→ 『Use Mouse for Touch』のチェックを外す。
これで入力が『デスクトップ/コンソール』を選んだ時と同様のものになる。
f:id:shivaT:20150706123500p:plain

影を消す方法

オブジェクトを消したときに残る影は、
「ビルド」することで消すことができる。
ビルド前
f:id:shivaT:20150706121423p:plain
ビルド後
f:id:shivaT:20150706121654p:plain

画面が緑色になってしまう対処方法

アウトライナから「SphereReflectionCapture」を削除する。

変更前 変更後
f:id:shivaT:20150706224934p:plain f:id:shivaT:20150706224942p:plain

FPSが上がっているのは、「動作が重い対処方法」をした後のため。

※SphereReflectionCaptureについて詳しくは以下のサイトへdocs.unrealengine.com

動作が重い対処方法

FPSが10以下になってしまい、画面が緑色になってしまうので、対処する。
(とりあえず軽くなればいいという方向け)
ツールバーから『設定』の中にある、
『描画レベルをプレビュー』→『モバイル/HTML5』 を選択する。

・利点
描画が一気に軽くなる。
・欠点
モバイル品質に なってしまうために動的影がなくなる。
一部マテリアルの互換がなくなってしまうため、たまに見た目がおかしくなってしまう。

変更前 変更後
f:id:shivaT:20150706210904p:plain f:id:shivaT:20150706210913p:plain

武器の弾作成

『ParticleSystem』コンポーネント
『ProjectileMovement』コンポーネント

・「コンポーネント」について
コンポーネントとは既に1つ以上の機能を持った、
ブループリントクラスに追加できる汎用パーツのこと。
コンポーネントについて詳しくは以下のサイトへdocs.unrealengine.com

※ParticleSystemについて詳しくは以下のサイトへdocs.unrealengine.com

・「Projectile」について
自身が持つ向きを方向ベクトルとして、
生まれた瞬間に設定された速度で飛び出していくということ。
そのため、
「ProjectileMovement」=「発射物の移動」
となる。
※ProjectileMovementについて詳しくは以下のサイトへdocs.unrealengine.com

ノードのコメントの付ける方法

コメントなし コメントあり
f:id:shivaT:20150706231706p:plain f:id:shivaT:20150706231731p:plain

※ノードのコメントについて詳しくは以下のサイトへdocs.unrealengine.com

マテリアルの項目がないときの対処方法

コンパイルしたら、表示されるようになる。

マテリアルが反映されないときの対処方法

一度、ウィンドウを閉じてから開き直すと反映されている。

炎(Particle)が表示されないときの対処方法

ツールバーの「設定」→「エンジンの拡張機能設定」
レンダリングの品質を選択できる。
(品質は「低」から「Epic」まで選択出来る。Epicが最高画質)
「エディタパフォーマンスをモニタリングしますか?」のチェックを外す。
f:id:shivaT:20150710005332p:plain

エンジンの拡張機能について

レンダリングの品質を簡単に変更できる。

敵側の当たり判定について

f:id:shivaT:20150707005033p:plain
・「OnComponentBeginOverlap(CapsuleComponent)」について
CapsuleComponent(つまりEnemyCharacter)と何かが重なると、
その実行ピン(白いピン)につながるノードを実行するイベントノードのこと。
(Beginは重なった瞬間、Endは離れた瞬間)

・「Cast to PlayerShotWeapon」について
このブループリント(EnemyCharacterのブループリント)にはないアクタ(この場合、PlayerShotWeapon)のための変数や関数を呼び出して使用する時に使うもの。

・「Spawn Emitter at Location」について
Spawn Emitter at Location(指定した位置にエミッタを出現させる) 関数。
エミッタは、パーティクル(粒子状のもの)を発生させるもの。
Emitter Template のドロップダウンメニューから「P_Explosion」を選んでいるため、
爆発のエフェクトが得られる。

・「Get Actor Location」について
Get Actor Locationは、アクタの位置を取得する関数。
Target(対象)が「self」になっているため、
このブループリントの主である「EnemyCharacter」が対象となる。
つまり、
「EnemyCharacter」の位置を取得して、
その位置を「Spawn Emitter at Location」に供給している。

・「Set Life Span」について
Set Life Span関数を使用することによって、アクタ(Target)に生存期間を設定することができる。
設定期間が終わると、Destroy()がアクタ上に自動的に呼び出される。
また、
「設定期間が終わるとDestroy()がアクタ上に自動的に呼び出される」というようなランタイムシステムは、
アクタの最初の位置と回転を設定する必要がある。
そのため、
「Get Actor Location」でアクタの位置を取得している。
つまり、
「Set Life Span」は、EnemyCharacter(Target)を0.2秒後に破壊する。

※アクタについて詳しくは以下のサイトへdocs.unrealengine.com

※ランタイム ライフサイクルについて詳しくは以下のサイトへdocs.unrealengine.com
または、docs.unrealengine.com

アクタのライフサイクルのイメージは、
ロードされ、存在し、やがてレベルにアンロードされ、破壊されるもの。

ナビゲーションメッシュについて

アクタに通ることができるところを示すもの。
「p」キーで表示切替。
※ナビゲーションメッシュについて詳しくは以下のサイトへdocs.unrealengine.com

「ビヘイビアツリー」について

行動(振る舞い)をツリー構造上に配置して、
流れが複雑になりがちなAIをスッキリとさせることができるようになる。
ビヘイビアツリーは以下の要素で構成されている。
・コンポジット(Composite
・タスク(Task)
・デコレーター(Decorator)
・サービス(Service)
・ルート(Root)
・ブラックボード(Blackboard)

※ビヘイビアツリーについて詳しくは以下のサイトへdocs.unrealengine.com

AIControllerからビヘイビアツリーを起動

f:id:shivaT:20150707031811p:plain

・「Event Begin Play」について
イベントを開始するためのノードのこと。
アクタがワールド内で破壊されると、このイベントが実行されます。

・「Run Behavior Tree」について
BTAssetで設定したビヘイビアツリー(EnemyBT)が使えるようになる。

ブラックボードについて

各ノード間で受け渡しが可能な変数を保持するためのデータアセット。
キャラクターのターゲットとなるアクターや座標などを保持することができ、
タスクなどの各ノードに受け渡すことができる。
つまり、
AIにとっての記憶領域(メモリー)にあたる部分のこと。
今回のキー(TargetPoint)は、AIが移動する際に使用する移動対象地点となる。

タスクについて

実際にキャラクターに対して処理を行うノード。
このノードによってキャラクターを指定の場所へ動かしたり、止めたりできる。
つまり、このタスクを分割し、
再利用性を高めていけば様々な状況に対応するAIが作れる。
※タスクについて詳しくは以下のサイトへdocs.unrealengine.com

タスクの中身作成

f:id:shivaT:20150707050803p:plain

・「Event Recieve Execute」と「Finish Execute」について
「Event Recieve Execute」は、このTaskに入った際に1度だけ呼び出される。
「Event Recieve Execute」がスタートイベントになり、
「Finish Execute」で終了となる。
また、
「Finish Execute」の「Success」フラグをチェックを入れると、
Blackboardに書き込みが完了するまで「Finish Execute」が呼ばれない。
完了すると「Success」を返し、次のタスクへ遷移する。
タスクはその繰り返し。

・「Get Actor Location」について
「PlayerCharacter」の位置を取得して、
その位置を「Set Blackboard Value as Vector」に供給している。

・「Set Blackboard Value as Vector」について
Key(TargetPoint)に、Value(PlayerCharacterの位置)をBlackboardに書き込む。

ルートについて

ビヘイビアツリーの実行開始ノードのこと。
各ビヘイビアツリーに必ず一つのみ存在し、
ツリー構造での根ノードに当たる。親ノードを持たない。

コンポジットについて

SelectorノードやSequenceノードなど、
ツリー構造でのブランチの実行ルートを制御するノードのこと。
タスクを繋げる。
※コンポジットについて詳しくは以下のサイトへdocs.unrealengine.com

ビヘイビアツリーの完成

f:id:shivaT:20150707062528p:plain

以下の①~③を繰り返す。
①「FindTarget」ノード:「PlayerCharacter」の位置をBlackboardの変数(TargetPoint)に書き込む
②「Move To」ノード:Blackboardの変数(TargetPoint)の地点へ移動
③「Wait」ノード:5秒間待機

・「Move To」ノードについて
「Move To」ノードは、Character Movementコンポーネントのあるポーンを、
NavMeshを使ってベクターブラックボードキーへ移動させる。

・「Wait」ノードについて
ビヘイビアツリーは、待ち時間が終わるまで、このノード上で待機する。

※Taskノードについて詳しくは以下のサイトへdocs.unrealengine.com

プレーヤーのライフを作成

f:id:shivaT:20150707190611p:plain

・「Cast to ThirdPersonCharactor」について
この Cast To は、Objectピンに供給されるオブジェクトを「PlayerCharacter」という型にキャストする。
つまり、
この「Object」が「PlayerCharacter」という特定の型であるかどうかを、まずチェックする。
そうではない場合は、Cast Failed(キャストの失敗)となる。

うまく行くと(PlayerCharacter型であると)、As ThirdPersonCharactorというピンから ThirdPersonCharactorの変数やプロパティや関数にアクセスすることができる。今回の場合、変数「Life Point」を使用。PlayerCharacter型であることが確認できたら「ReturnNode」する。

・「ReturnNode」について
「Return Value」に「Life Point」変数の値を渡す。

※レベルブループリントについて詳しくは以下のサイトへdocs.unrealengine.com
または、
ニコニコ動画で分かりやすい説明があった。
Unreal Engine 4 でゲームを作る Part3 レベルブループリント ‐ ニコニコ動画:GINZA

ウィジェットをゲーム上に追加

f:id:shivaT:20150707194739p:plain

・「Create GameUI_C Widget」について
Class セクションで指定されている「Game UI」を呼び出す。
Owning Player は、それが適用される Player Controller で、ブランクはデフォルトの Player Controller になる。
Return Value は、結果として得られるもの。
※Create Widgetについて詳しくは以下のサイトへdocs.unrealengine.com

・「Add to Viewport」について
画面上に「Game UI」を描画する。

タックルでダメージを与えられる処理

f:id:shivaT:20150707200628p:plain

スコア管理用のブループリントを使用可能にする

メニューから、『プロジェクト設定』を開きます→『マップ&モード』→『Game State Class』を選択する。
リストにある『MyGameState』を選択するとゲーム中に使用可能になる。
f:id:shivaT:20150707201324p:plain

スコア作成

f:id:shivaT:20150707204205p:plain

・「To Text(int)」について
Scoreの値がテキスト化される。
テキスト化されたScoreをValueに格納

敵を倒したらスコアを足す処理

f:id:shivaT:20150707210210p:plain

『EnemyCharacer』のブループリントの全体図

f:id:shivaT:20150707210854p:plain

敵をランダムで出現させる処理

f:id:shivaT:20150707213857p:plain

・「Random Float in Range」について
今回の場合、2秒から5秒のランダムの値を生成する。

・「Delay」について
待機させる。

・「Spawn AIFromClass」について
AIを持つ敵キャラクターを生成させる。
・Pawn Class:出現させるキャラ
・Behavior Tree:キャラのAIの処理
・Location,Rotation:出現地点(今回の場合、Targetがselfのため『EnemySpawnPoint』を設置した場所)

ゲームオーバー画面の作成

ライフがなくなると「GameOver!!」が表示され、入力ができなくなる。

・可視状態の設定
普段は文字は見えないようにするために、
『Visibility』を『Hidden』に変更する。
f:id:shivaT:20150707215816p:plain

・可視状態の制御
f:id:shivaT:20150707225234p:plain

・「Branch」について
処理を分岐させる。

・「Disable Input」について
プレイヤーは入力を無効化する。

リセット機能

『R』キーを入力するとゲームをリセットさせる。
f:id:shivaT:20150707230404p:plain

・「Open Level」について
ファイル(ThirdPersonExampleMap)を再度開く処理。
そのため、
スタート地点、敵の出現数、スコア、ライフポイントすべてがリセットされる。
※レベルについて詳しくは以下のサイトへdocs.unrealengine.com

ゲーム完成

f:id:shivaT:20150707231038p:plain


一通り分からないところを確認できた。
流れをある程度理解できたので、個人的に何か作成しようと思う。

メモ終わり。