[UE4] ブロック崩しを作る #3 C++

# はじめに
この記事は [[UE4] ブロック崩しを作る #2 バーとブロック](https://qiita.com/jamaican/items/9730ef4c97ffed2783e4) の続きの記事になります。
前回 BP（ブループリント）のイベントグラフで組んだところを、今回は C++ で作り直してみます。

# 完成ゲーム
![cap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/e08dcd4c-0bf4-2f36-8eb0-8620b7243f48.gif)

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

# 目次
[ブロック用のC++クラスを作成](#ブロック用のcクラスを作成)
[ブロックの破壊処理をC++で作る](#ブロックの破壊処理をcで作る)
[ブロックに Static Mesh をセット](#ブロックに-static-mesh-をセット)
[ブロックを配置](#ブロックを配置)
[次回](#次回)

# ブロック用のC++クラスを作成
前回のプロジェクトを流用します。
このプロジェクトは作成時に Project Settings で Blueprint を選択しましたが 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)
Actor を選択して Next をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/460fdc4a-79b6-bffe-bdbb-d20119e6d1bc.png)
Name を「BlockActor」に変更
Create Class をクリック（ここで Visual Studio のプロジェクト等が作成されるので時間がかかります。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/21371f56-ee3f-996f-95f3-e1bd7058b64c.png)
Visual Studio が起動し BlockActor.h と BlockActor.cpp が作成されているのが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/06405111-7c14-ff00-6cd5-bc6e24909347.png)

# ブロックの破壊処理をC++で作る
前回 BP の「Event Hit」と「DestroyActor」で作ったブロック破壊処理を、今回は C++ で作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/47e837a2-d3da-b275-b81d-3c22dfa6d7d5.png)

BP と同様に下記のような関数を ABlockActorクラス に追加したいところですが同名の関数は存在しないようです。

```C++:BlockActor.cpp
void ABlockActor::EventHit()
{
	DestroyActor();
}
```

## ブループリント Event Hit 相当の関数を探す

BP の Event Hit に相当する C++ の関数を探します。
探す方法は下記の方法がよさそうです。

https://zenn.dev/posita33/articles/8dd51074f1915a

Event Hit のツールチップに書かれている文字を確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/0671cd34-df30-2e14-d9e5-731cdfa4ec89.png)

Visual Studio で Ctrl + Shift + F で検索ウィンドウを開く
"Event when this actor bumps into" でソリューション全体を検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/f4ed96aa-7a73-ccc5-5440-03dd424218fe.png)

AActorクラス の２つの関数が検索に引っかかりました。

```C++:Actor.h
	/** 
	 * Event when this actor bumps into a blocking object, or blocks another actor that bumps into it.
	 * This could happen due to things like Character movement, using Set Location with 'sweep' enabled, or physics simulation.
	 * For events when objects overlap (e.g. walking into a trigger) see the 'Overlap' event.
	 *
	 * @note For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled.
	 * @note When receiving a hit from another object's movement (bSelfMoved is false), the directions of 'Hit.Normal' and 'Hit.ImpactNormal'
	 * will be adjusted to indicate force from the other object against this object.
	 */
	virtual void NotifyHit(class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit);
	/** 
	 * Event when this actor bumps into a blocking object, or blocks another actor that bumps into it.
	 * This could happen due to things like Character movement, using Set Location with 'sweep' enabled, or physics simulation.
	 * For events when objects overlap (e.g. walking into a trigger) see the 'Overlap' event.
	 *
	 * @note For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled.
	 * @note When receiving a hit from another object's movement (bSelfMoved is false), the directions of 'Hit.Normal' and 'Hit.ImpactNormal'
	 * will be adjusted to indicate force from the other object against this object.
	 * @note NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions.
	 */
	UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "Hit"), Category="Collision")
	void ReceiveHit(class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit);
```

Actor.cpp を確認すると ReceiveHit() は NotifyHit() から呼ばれているだけのようです。

```C++:Actor.cpp
void AActor::NotifyHit(class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	// call BP handler
	ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
}
```

また ReceiveHit() の方は BlueprintImplementableEvent がついており、どうもC++で実装する事が出来なさそうです。
なので Event Hit の代わりには **NotifyHit()** を使う事にします。

https://qiita.com/herorinusu/items/7b396f93bc7f9fc54152

## ブループリント DestroyActor 相当の関数を探す

同様に BP の DestroyActor に相当する C++ の関数も探します。

DestroyActor のツールチップを確認し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/6b3d4511-0d00-cf02-e723-74c4d0476f79.png)

"Destroy the actor" でソリューションを全検索すると、下記の関数が AActorクラス の中に見つかります。

```C++:Actor.h
	/** Destroy the actor */
	UFUNCTION(BlueprintCallable, Category="Utilities", meta=(Keywords = "Delete", DisplayName = "DestroyActor", ScriptName = "DestroyActor"))
	virtual void K2_DestroyActor();
```

## ABlockActorクラス にブロック破壊処理を追加

BlockActor.h と BlockActor.cpp に下記のように関数を追加します。
これで ABlockActorクラス に BP と同じブロック破壊処理を追加することが出来ました。

```C++:BlockActor.h
class BREAK_BLOCK_API ABlockActor : public AActor
{
	:
public:	
	virtual void NotifyHit(class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit) override;
};
```

```C++:BlockActor.cpp
void ABlockActor::NotifyHit(UPrimitiveComponent* MyComp, AActor* Other, UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
	K2_DestroyActor();
}
```

# ブロックに Static Mesh をセット

ブロックに Static Mesh をセットします。C++でセットする事も出来ますが、見た目に関わる部分なので BP でセットします。
BPで編集するために BlockActor を元にした新規 BP Class を作成します。

Content Browser から 「C++ Classes」→「Break_Block」を開く 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/866f8dd2-45ad-b69b-6ccf-545f39496493.png)

※「C++ Classes」が表示されていない場合は、View Options から「Show C++ Classes」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/303a352e-4e15-06cc-829a-b4e345f304d2.png)

BlockActor を右クリックして「Create Blueprint class based on BlockActor」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/d1ae31de-e66a-789e-e7b9-440146e912b8.png)

Name を「BP_BlockCpp」として「Create Blueprint Class」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/8d1c1bac-cd27-86c5-49d6-409d3f30b750.png)

BP_BlockCpp が作成されました。
ここから先は以前にブロックの BP を作成した時とおなじです。

* BP_BlockCpp をダブルクリックで BP編集画面 を開く
* +Add Component ボタンをクリックし「StaticMesh」を追加
* 追加した Static Mesh を選択して、Details から Static Mesh を「Cube」変更
* 同じく Static Mesh の Details から Materials を「BasicShapeMaterial」に設定

# ブロックを配置
BP_BlockCpp をゲームに配置します

* すでに配置済の BP_Block ... BP_Block10 を Delete します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/e8bb0388-eb5c-a9f6-65de-9d56c62c98a9.png)

* 代わりに BP_BlockCpp を 10個 配置して BP_Block と同じ座標をセットします

``` :BP_BlockCpp...BP_BlockCpp10
Location (0.0, -350.0, 850.0)
Location (0.0, -175.0, 850.0)
Location (0.0, 0.0, 850.0)
Location (0.0, 175.0, 850.0)
Location (0.0, 350.0, 700.0)
Location (0.0, -350.0, 700.0)
Location (0.0, -175.0, 700.0)
Location (0.0, 0.0, 700.0)
Location (0.0, 175.0, 700.0)
Location (0.0, 350.0, 700.0)
``` 

プレイで確認すると BP で組んだ時と同じようにブロックが破壊されています
![cap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39286/e08dcd4c-0bf4-2f36-8eb0-8620b7243f48.gif)

# 次回
BP で作成していたブロックの破壊を C++ で実装し直すことが出来ました。
次回はバーの移動を、BP から C++ で実装し直します。
その際に UE4 のフレームワークに則り Plater Controller を使って実装いたします。
[[UE4] ブロック崩しを作る #4 PlayerController (C++)](https://qiita.com/jamaican/items/1e968afd31825249c70b)