UE4 PhysicalMaterialの設定と取得についてのメモ

# 概要
UnrealEngine の 物理マテリアル(PhysicalMaterial) の設定と取得についてのメモです。
単純なコリジョン(SimpleCollision)と複雑なコリジョン(ComplexCollision)のケースがあるようです。

## 更新履歴
| 日付 | 内容 |
|:----|:-----|
|2021/02/26| サーフェイス型の追加設定について追記 |

## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.22

## 参考
以下を参考にさせて頂きました、ありがとうございます。
[物理マテリアルのユーザーガイド](https://docs.unrealengine.com/ja/Engine/Physics/PhysicalMaterials/PhysMatUserGuide/index.html)
[ueHow - HitResult](http://uehow.web.fc2.com/Contents/Jpn/UE4/BluePrint/NodeReference_Collision/BreakHitResult.html)
[UE4における大規模背景制作事例（コリジョン編） ](https://www.slideshare.net/EpicGamesJapan/ue4-138425097)

# 物理マテリアル
コンテンツブラウザから[フィジックス] -> [物理マテリアル]で作成できます。
![PhysicsMaterialAsset.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/625a9dbd-1c7d-9e61-eea5-744d58ca505d.jpeg)


## 物理マテリアルの取得 - ライントレースでのブロックヒット取得
ライントレースを使ってコリジョンを調べます。結果が HitResultに返ってきます。
他のトレース系もほぼ一緒だと思われます。

![LineTraceBP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/dabe3d58-dc74-9803-0a27-91641cd9feaa.png)

C++コードだと以下の様になります。

```cpp:
FVector _St;
FVector _Ed;
FHitResult HitResult;
TArray<AActor*> ActorsToIgnore;

// _Stから_EdまでのライントレースをしてぶつかったSimpleCollisionを取得する
UKismetSystemLibrary::LineTraceSingle(GetWorld(), _St, _Ed,	UEngineTypes::ConvertToTraceType(ECollisionChannel::ECC_Visibility),
false, ActorsToIgnore, EDrawDebugTrace::None, _HitResult, true);

```

HitResultは以下のようなメンバを持ち、PhysMat にて物理マテリアルを取得できます。
![HitResult_Detail.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/9710a669-7224-f123-b716-760eb6315a10.jpeg)

C++コードだと以下の様になります。

```cpp:
// 物理マテリアルを取得する例
auto _PhysMat = _HitResult.PhysMaterial;
if (_PhysMat != nullptr) {
 // アセット名を表示
 UE_LOG(LogTemp, Log, TEXT("%s"), *_PhysMat->GetName());
}
```

# 物理マテリアルの設定
## SimpleCollision用の設定
単純なコリジョンの場合は、コンポーネントの [Collision] -> [Phys Material Override] に物理マテリアルを設定することで取得ができます。
空欄の場合に取得をするとエンジンの DefaultPhysicalMateral が返ってくるようです。

![SimpleCollisionSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/072e3fbe-9c08-2a3a-3016-a0309a22fd7c.png)

スタティックメッシュに設定する場合、[Simple Collison Physical Material]に設定します。
![SimpleCollisionSetting_Mesh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/c92f7f23-9bd6-197e-26ad-f5cd19bb7a80.png)


## ComplexCollision用の設定
複雑なコリジョンの場合はマテリアルの[Physical Material] -> [Phys Material] に設定します。

![MaterialSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/ce36f975-9ebe-0ada-ea75-94deb174357c.png)

この場合、HitResultを取得するためのトレースも ComplexCollisionに対して行わないと取得できません。
（LineTraceSingle()の場合は、第5引数 bTraceComplex を true にする）


## [Return Material on Move]設定について
コリジョンの設定[Return Material on Move]についてですが、このチェックを入れないと HitResult で PhysicalMaterial を取得できないかと思ったのですが、床などのスタティックなものについてはチェック不要のようです。

![ReturnMaterialOnMove.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/f0c6e367-9a85-00b1-0b14-54cbaa5aaec0.jpeg)



# PhysicalMaterialクラスの継承について
物理マテリアルクラスを継承して、必要なメンバを追加できます。

以下、float を１つ追加しているだけのコード例です。

```cpp:MyPhysicalMaterial.h
#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/Object.h"
#include "Engine/EngineTypes.h"
#include "EngineDefines.h"
#include "PhysxUserData.h"
#include "Vehicles/TireType.h"
#include "PhysicsEngine/PhysicsSettingsEnums.h"
#include "Physics/PhysicsInterfaceCore.h"
#include "PhysicalMaterials/PhysicalMaterial.h"
#include "MyPhysicalMaterial.generated.h"

class UPhysicalMaterial;

UCLASS(BlueprintType, Blueprintable, CollapseCategories, HideCategories = Object)
class TEST_API UMyPhysicalMaterial : public UPhysicalMaterial
{
	GENERATED_UCLASS_BODY()

public:
	// 追加パラメータ
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "AddParam")
	float		AddParam;

};

```

cppはコンストラクタで追加パラメータを初期化してあるだけです。

```cpp:MyPhysicalMaterial.cpp
// コンストラクタ
UMyPhysicalMaterial::UMyPhysicalMaterial(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	Friction = 1.0f;
	AddParam = 1.5f;
}

```

物理マテリアル作成時に継承したMyPhysicalMaterialクラスが選択できるようになります。
![MyPhysicalMaterial.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/3dfcd4d0-d9d0-234f-7d02-90541f8de6a7.png)


# 物理設定について
## サーフェイス型の追加設定
[プロジェクト設定] -> [エンジン/物理] -> [Physical Surface]
にてカスタムのサーフェイス型を設定することができます。

![MyPhysucalSurface.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/b25f1345-ee1c-786e-5671-f22d9c9c37c4.jpeg)

ここで設定したサーフェイス型が物理マテリアルアセットの`フィジカルプロパティ`の`SurfaceType`として設定ができるようになります。

![PMSetting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/8c6184f2-5568-f0a2-229c-8e9975403a22.jpeg)



# まとめ
コリジョンの形状によって設定がかわるため、最初うまく情報が取得できず混乱しました。まとめてみると理解ができます。
あとは物理マテリアルの設定がされているかどうかを簡単に確認できるような手法が欲しい所です。（ビューの表示切り替え辺りでできるように）