[UE4] ブロック崩しを作る #4 PlayerController (C++)

# はじめに
この記事は [[UE4] ブロック崩しを作る #3 C++](https://qiita.com/jamaican/items/6303fe259bbf92a7c4ed) の続きになります。
前回は「ブロックの破壊処理」を C++ で作りましたが、今回は「バーの移動」を C++ で実装します。

また、バーの移動には UE4 の **PlayerController** を使って実装します。
UE4 には Frame Work としての作りがあり、プレイヤの入力は PlayerController という場所で処理するのがよいようです。
キーボードの入力を PlayerController で受け取り、PlayerController が バー（Pawn）に指示を出してバーの移動が行われるという流れです。

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Framework/Controller/PlayerController/

# 完成ゲーム
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/11ee755d-1bdf-9c4c-9015-0039da4b86db.gif)

# 環境
Windows 10
Unreal Engine 4.27.1
エディタ言語 英語

# 目次
[バーの Pawn(C++) を作成](#バーの-pawnc-を作成)
[バーの移動処理をC++で実装](#バーの移動処理をcで実装)
[バーに Static Mesh をセット](#バーに-static-mesh-をセット)
[PlayerController(C++) を作成](#playercontrollerc-を作成)
[キー入力の登録](#キー入力の登録)
[PlayerController(C++) を実装](#playercontrollerc-を実装)
[「Pawn」と「Player Controller」を Project にセットする](#pawnとplayer-controllerを-project-にセットする)
[バーを配置](#バーを配置)
[カメラを配置](#カメラを配置)
[次回](#次回)


# バーの Pawn(C++) を作成
前回のプロジェクトを流用します。
前回はバーを「Actor」で作成しましたが、今回は Player Controller から操作させるため「Pawn」で作成します。
また Pawn の処理も c++ で作成する事にします。

上部メニューの「File」から「New C++ Class ...」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/9615e438-d136-e703-d73f-c649bcf93493.png)

「Pawn」を選択して、「Next」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/f3a5b6b4-183d-eeea-e607-5a4c41c523ba.png)

Nameを「PawnBar」として、「Create Class」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/9579302f-e07f-60fe-c979-3fb28e0400b2.png)

Visual Studio が起動して Project に PawnBar.h と PawnBar.cpp が追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/aa7858a9-9f90-d63c-f34d-d873358b2851.png)


# バーの移動処理をC++で実装

バーの移動処理を APawnBarクラスに実装します。

* バーの移動用の関数 **MoveY()** を追加します
  * この関数は、後ほど作成する Player Controller から呼ばれるようになります

```C++:PawnBar.h
class BREAK_BLOCK_API APawnBar: public APawn
{
	GENERATED_BODY()
    :

public:	
	void MoveY(float val);
};
```

```C++:PawnBar.cpp
void APawnBar::MoveY(float val)
{
	FVector vec = FVector(0.0f, val * 10.0f, 0.0f);
	AddActorLocalOffset(vec, true);
}
```

# バーに Static Mesh をセット
バーに Static Mesh をセットします。[第3回](https://qiita.com/jamaican/items/6303fe259bbf92a7c4ed#%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%AB-static-mesh-%E3%82%92%E3%82%BB%E3%83%83%E3%83%88)でブロックに Static Mesh をセットしたのと同じ様に、PawnBar の BP を作成します。

* Content Browser から 「C++ Classes」→「Break_Block」を開く
* 「PawnBar」を右クリックして「Create Blueprint class based on BlockActor」を選択
* Name を「BP_PawnBar」として「Create Blueprint Class」をクリック
* 開かれた BP_PawnBar の BP編集画面で
  * +Add Component ボタンをクリックし「StaticMesh」を追加
  * 追加した Static Mesh を選択して、Details から Static Mesh を「Cube」変更
  * 長方形になるよう StaticMesh の Details から Transform を下記のように変更
  * 同じく Static Mesh の Details から Materials を「BasicShapeMaterial」に設定

```:BP_PawnBar/StaticMesh/Transform
  Rotation (0°, 0°, 90°)
  Scale (2.0, 1.0, 0.5)
```

これでバーのPawnの作成は完了です。

# PlayerController(C++) を作成

続いて Player Controller を作成します

* 上部メニューの「File」から「New C++ Class ...」を選択
*  「Player Controller」を選択して「Next」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/a5612c68-f46f-3ff4-4373-5d44d0c9e73b.png)
Name を「PlaterController_BB」として「Create Class」をクリック
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/946b4ff8-1612-c79d-aad8-436c573c0a6b.png)

Visual Studio を Reload すると PlaterController_BB.h と .cpp が追加されています。

# キー入力の登録
以前は Actor で直接キーボード入力を拾っていましたが、今回は直接キーボード入力を見るのではなく、事前に Project に 矢印キーは「MoveY」という入力だという事を登録しておき、Player Controller では「MoveY」の入力の有無を確認するようにします。こうする事で将来ゲームパッドでもバーを動かしたくなった時に、ゲームパッドの左右入力も「MoveY」として登録するだけで、ゲームパッドでも操作できるようになります。

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Input/

上部メニューの「Edit」から「Project Setting」を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/a9cc340b-17fe-50f9-806f-7286ee862a1c.png)

表示されたウィンドウの右メニューから「Engine」→「Input」を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/9a6d89e5-5262-b16c-e017-e66d33f7514a.png)

* Axis Mappings の + をクリックし、名前を「MoveY」にします
* None になっている箇所をクリックし、Keyboard → Left を選択し、Scale を -1.0 にします
* MoveY の + をクリックし、None を Keyboard → Right にして、Scale を 1.0 にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/66fcdc70-5239-4495-b358-6ca9ee141d42.png)

これでキーボード左右の入力をプログラム側で「MoveY」の入力として受け取れるようになりました。

# PlayerController(C++) を実装
Visual Studio に戻って PlayerController_BB.h を下記のように実装します。

* **コンストラクタ** を追加
* 操作する Pawn のポインタを保存する **APawnBar* m_pAPawnBar** を追加
* 操作する Pawn を開始時に保存するため **BeginPlay()** を override
* 「MoveY」の入力をバインドするために **SetupInputComponent()** を override
* 「MoveY」の入力を処理をする **void Move_YAxis(float axisValue)** を追加

```c++:PlayerController_BB.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "PawnBar.h" // xx.generated.h の前に宣言する
#include "PlayerControllerBB.generated.h"

UCLASS()
class BREAK_BLOCK_API APlayerController_BB : public APlayerController
{
	GENERATED_BODY()
public:
	APlayerController_BB();

protected:
	APawnBar* m_pAPawnBar;

protected:
	virtual void BeginPlay() override;
	virtual void SetupInputComponent() override;

	void Move_YAxis(float axisValue);
};
```

続いて PlayerController_BB.cpp を下記のように実装します。

```c++:PlayerController_BB.cpp
#include "PlayerController_BB.h"

APlayerController_BB::APlayerController_BB()
	: APlayerController()
	, m_pAPawnBar(nullptr)
{
	
}

void APlayerController_BB::BeginPlay()
{
    Super::BeginPlay();
    APawn* pPawn = GetPawn();
    ensure(pPawn != nullptr);
    m_pAPawnBar = Cast<APawnBar>(pPawn);
    ensure(m_pAPawnBar != nullptr);
}

void APlayerController_BB::SetupInputComponent()
{
	Super::SetupInputComponent();
	InputComponent->BindAxis("MoveY", this, &APlayerController_BB::Move_YAxis);
}

void APlayerController_BB::Move_YAxis(float axisValue)
{
    check(m_pAPawnBar != nullptr);
    m_pAPawnBar->MoveY(axisValue);
}
```

プログラムはこれで全部書けたので Build します。
Visual Studio の BreakBlockプロジェクトを右クリックしてビルドを行いエラーが無い事を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/d25962ad-0ab8-9984-1db5-1e0f67683b29.png)

# 「Pawn」と「Player Controller」を Project にセットする

作成した Pawn と Player Controller で使えるようにするためには下記の手順が必要になります

* [新規で「GameMode」を作成する](#新規でgamemodeを作成する)
* [作成した「GameMode」を使うように設定する](#作成したgamemodeを使うように設定する)
* [設定した「GameMode」に「Pawn」と「Player Controller」を設定する](#設定したgamemodeにpawnとplayer-controllerを設定する)

## 新規で「GameMode」を作成する

Content内右クリックから新規「Blueprint Class」の作成
開いたウィンドウから「GameModeBase」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/d8a890a2-447d-0593-8977-70c3cc29896c.png)

作成された GameMode を「GameMode_BB」にリネーム
これで GameMode は作成できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/d5de5f67-da94-f7bc-c8c8-82b3adf09c25.png)


## 作成した「GameMode」を使うように設定する

上部メニューの「Window」から「World Settings」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/00157c99-6ab6-4308-cde6-4ee7fb27b585.png)

開かれた World Settings ウィンドウで、「GameMode Override」の項目を「GameMode_BB」に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/92cc6445-7795-e453-ffe3-2acdaf524691.png)

## 設定した「GameMode」に「Pawn」と「Player Controller」を設定する
同じく World Settings ウィンドウで

* Default Pawn Classを「BP_PawnBar」に変更
* Player Controller Classを「PlayerController_BB」に変更

これでゲーム起動時に PlayerController として「PlayerController_BB」が使われるようになり、「PlayerController_BB」で GetPawn() を行うと「BP_PawnBar」が取得できるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/9b58b1ba-1e00-bf6b-dbe1-0bdbca746ce1.png)

# バーを配置

すでに World Outliner に配置されている「BP_Bar」を削除します。
代わりに「BP_PawnBar」をドラッグドロップで配置...と思うかもしれませんが、すでに GameMode の Default Pawn Class に「BP_PawnBar」を登録したので、「BP_PawnBar」はゲーム起動に配置されるようになります。
では、ゲーム内のどこに配置されるかというと、World Outliner にある「Player Start」の位置です。
なので「Player Start」の位置を (0.0, 0.0, 150.0) に変更します。(元々バーがあった位置）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/8369d514-1e00-deed-f4f1-955cc55cc9c9.png)

これで Play をするとカメラの位置がおかしくなります。
カメラが Player Start の位置を見るようになっているためです。
FPSなどではプレーヤーにカメラがついてくるのでこの様な形でいいのですが、ブロック崩しなので全体を見渡すカメラになるように変更します。

# カメラを配置

新規カメラを作成します。
Place Actors から「All Classes」→「Camera」を選択して、プレビュー画面にドラッグドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/7058bcc6-2cca-1d3a-6539-ff5506c134f3.png)

World Outliner に「CameraActor」が追加されています。
「CameraActor」の位置を (-1300.0, 0.0, 600.0) にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/47e89dc7-2251-c655-243a-03e2762c49af.png)

こちらのカメラが優先で使われるように Auto Active for Player を「Player 0」に変更します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/89016c90-7e51-df60-a91d-9a5f0b3a6761.png)

Play するカメラの位置が以前と同じようになります。
また矢印キーによるバーの移動も確認することができました。
(バーの移動が AddActorLocalOffset になったのが移動がスムーズになりました)
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/11ee755d-1bdf-9c4c-9015-0039da4b86db.gif)

# 次回
これで BP で作成していた ブロック と バー を C++ で作成し直すことができました。
次回は C++ のデバッグについてまとめたいと思います。
[[UE4] ブロック崩しを作る #5 Debug (C++)](https://qiita.com/jamaican/items/3eed3698942f6944d305)