UE4 Dynamic Material Instanceについてのメモ

# 概要
UnrealEngine のダイナミックマテリアルインスタンスとマテリアルパラメータについてのメモ


## 更新履歴
| 日付 | 内容 |
|:----|:-----|
|2020/04/18| マテリアルパラメータの取得、テスクチャパラメータについて追記|

## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.24

## 参考
以下を参考にさせて頂きました、ありがとうございます。

[UE4公式:マテリアル パラメータの作成方法](https://docs.unrealengine.com/ja/Engine/Rendering/Materials/HowTo/Making_Parameters/index.html)
[UE4公式:インスタンス化マテリアル](https://docs.unrealengine.com/ja/Engine/Rendering/Materials/MaterialInstances/index.html)
[UE4でダイナミックマテリアルインスタンスをやってみた](https://peta.okechan.net/blog/archives/3880)
[UE4 マテリアルを使って点滅ダメージリアクションを実装する](http://unrealengine.hatenablog.com/entry/2015/07/12/220000)
[UE4/C++: メッシュのマテリアルやテクスチャーをC++コードで制御する方法](https://usagi.hatenablog.jp/entry/2017/07/26/115603)
[UE4/C++: "UMaterialInstance::GetVectorParameterValue" の仕様変更と"Material Layers"](https://usagi.hatenablog.jp/entry/2018/03/31/021300)


# マテリアルにパラメータを設定する
マテリアルを開いてエディターの [パラメータ]->[ScalarParameter]や[VectorParameter]を選択して適用したいパラメータに設定します。他の計算（テクスチャカラーとの加算など）は別途行います。

![Material_AddParam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/3735fdba-25fd-a56f-af10-f5b1856cefbd.jpeg)

![SetMaterial_AddParam2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/fca8d4a1-0d10-d643-528b-d72c311623b5.jpeg)




# BPでのアクセス

## ダイナミックマテリアルインスタンスを作成
メッシュからダイナミックマテリアルインスタンスを作成し、変数 `MID`に保持します。コンストラクタや BeginPlay で行います。

![createdynamicmaterialinstance.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/7ff7faab-a8dd-cf35-aecc-c93199fe27d2.jpeg)


## パラメータを入れる
保持した変数 `MID`に対し、パラメータを設定します。スカラーパラメータとベクターパラメータを入れています。

![SetMIDParam_BP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/0e0840b9-d13d-d79f-fa5c-8c54dd93088f.jpeg)

テクスチャパラメータを入れる場合は以下の様になります。`Value`にテクスチャアセットを指定します。
![SetTextureParameterValue.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/cce98284-6bc3-9da7-1693-d53e98694351.jpeg)



# C++でのアクセス

## ダイナミックマテリアルインスタンスを作成
対象のメッシュに設定されているマテリアルスロットからダイナミックマテリアルインスタンスを作成します。
以下コード例。

```cpp:MyAnimInstance.cpp
#include "Materials/MaterialInstanceDynamic.h"

void UMyAnimInstance::NativeBeginPlay()
{
	class UMaterialInstanceDynamic* _MID = nullptr;
	// スロット名からインデックスに
	int32 _SlotIndex = GetSkeletalMeshComponent()->GetMaterialIndex(TEXT("SlotName"));

	// ダイナミックマテリアルインスタンスを作成
	_MID = GetSkeletalMeshComponent()->CreateDynamicMaterialInstance(_SlotIndex);
	
	// 作成したダイナミックマテリアルインスタンスを保持
	MID = _MID;
}
```


## パラメータを入れる
作成したダイナミックマテリアルインスタンスにパラメータを設定します。
以下コード例

```cpp:MyAnimInstance.cpp

class UMaterialInstanceDynamic* _MID;	// 設定対象のマテリアルインスタンス
if(_MID){
	// MIDのスカラーパラメータを設定する
	_MID->SetScalarParameterValue(TEXT("Speed"), 2.0f);

	// MIDのベクターパラメータを設定する
	_MID->SetVectorParameterValue(TEXT("Color"), FLinearColor(1.0f, 0.0f, 0.0f));
}

```

## パラメータの消去
外部設定をしたパラメータをクリアします。パラメータ別で消すようなものはないようです。

```cpp:.cpp
class UMaterialInstanceDynamic* _MID;	// 対象のマテリアルインスタンス

if(_MID){
	// 設定したパラメータを全部クリアする
	_MID->ClearParameterValues();
}

```



# マテリアルパラメータの取得
![ParamGroup.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/5af15d5b-f036-f069-ada4-79c0146ae6eb.jpeg)


スカラーパラメータ、ベクターパラメータ、テクスチャパラメータなどマテリアルが持っているパラメータについて以下C++コード例。

## マテリアルのスカラーパラメータ名を取得する

```cpp:.cpp

for (const FSkeletalMaterial& _Mt : _SkeletalMesh->Materials) {
	TArray<FMaterialParameterInfo> _ParamInfo;
	TArray<FGuid> _ParamIds;
	_Mt.MaterialInterface->GetAllScalarParameterInfo(_ParamInfo, _ParamIds);

	// スカラーパラメータを全部表示
	for (int _Lp=0;_Lp<_ParamInfo.Num();_Lp++){
		UE_LOG(LogTemp, Log, TEXT("%s"), *_ParamInfo[_Lp].Name.ToString());
	}
}

```


## マテリアルの特定スカラーパラメータ値を取得する

```cpp:.cpp
// スケルタルメッシュのマテリアルパラメータ "TestParam" を取得する
for (const FSkeletalMaterial& _Mt : _SkeletalMesh->Materials) {
	float _Buff = 0.0f;
	bool _Ret = _Mt.MaterialInterface->GetScalarParameterValue(FName("TestParam"), _Buff);
	
	if(_Ret){
		// マテリアル名とパラメータ値を表示
		UE_LOG(LogTemp, Log, TEXT("%s, %f"), *_Mt.MaterialSlotName.ToString(), _Buff);
	}
}

```

## テクスチャパラメータを設定する
設定するテクスチャは別途ロードしないとなりません。

```cpp:.cpp
class UMaterialInstanceDynamic* _MID;	// 対象のマテリアルインスタンス
UTexture* _Tex = nullptr;

_Tex = GetTexture();	// ロード済テクスチャを設定する
_MID->SetTextureParameterValue(TEXT("TexParam"), _Tex);
```


# まとめ
マテリアルの制御はいろいろあり複雑です。