[UE4]Material Instance の Static Switch Parameter を 変更する関数・ノードを作る方法について

# はじめに
[EditorScripting機能を使って、外部からMaterial Instanceのパラメータを確認・変更する方法について](https://qiita.com/EGJ-Kaz_Okada/private/0bf77ac5f920715e515b) の記事にて、「Material Instanceのパラメータを確認・設定する方法」について紹介しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363889/ebfd7800-41a4-32e9-680c-97046518165a.png)

- Get
    - UMaterialEditingLibrary::GetMaterialInstanceScalarParameterValue
    - UMaterialEditingLibrary::GetMaterialInstanceTextureParameterValue
    - UMaterialEditingLibrary::GetMaterialInstanceVectorParameterValue
    - UMaterialEditingLibrary::GetMaterialInstanceStaticSwitchParameterValue

- Set
    - UMaterialEditingLibrary::SetMaterialInstanceScalarParameterValue
    - UMaterialEditingLibrary::SetMaterialInstanceTextureParameterValue
    - UMaterialEditingLibrary::SetMaterialInstanceVectorParameterValue

しかし、よくよく見ると… **StaticSwitchParameter を変更するために必要な SetMaterialInstanceStaticSwitchParameterValue がありません！**こりゃ困った！

ということで作ってみました。残念ながらC++が必要になります。

検証環境：UE4.25.3

# SetMaterialInstanceStaticSwitchParameterValue の作り方
早速ですがC++コードです。今回は説明のために極力シンプルにしてますが、実運用するときは EditorOnly にするなどの対応が必要かと思います。

```MyBlueprintFunctionLibrary.h
#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"

UCLASS()
class ●●●●●_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	UFUNCTION(BlueprintCallable)
	static void SetMaterialInstanceStaticSwitchParameterValue(UMaterialInstance* Instance, FName ParameterName, bool Value);
}
```

```MyBlueprintFunctionLibrary.cpp
#include "MyBlueprintFunctionLibrary.h"
#include "Materials/MaterialInstance.h"

void UMyBlueprintFunctionLibrary::SetMaterialInstanceStaticSwitchParameterValue(UMaterialInstance* Instance, FName ParameterName, bool Value)
{
	FStaticParameterSet StaticParameters = Instance->GetStaticParameters();
	for (auto& SwitchParameter : StaticParameters.StaticSwitchParameters)
	{
		if (SwitchParameter.ParameterInfo.Name == ParameterName)
		{
			SwitchParameter.Value = Value;
			break;;
		}
	}
	Instance->UpdateStaticPermutation(StaticParameters);
}
```
実装するにあたって参考にした箇所
`Engine\Source\Editor\UnrealEd\Private\PreviewMaterial.cpp` の `CopyToSourceInstance` 関数 と `SetSourceInstance` 関数


出来上がり！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363889/9c072f80-93c7-1faa-2612-29b49215a8ff.png)

そして、[EditorScripting機能を使って、外部からMaterial Instanceのパラメータを確認・変更する方法について](https://qiita.com/EGJ-Kaz_Okada/private/0bf77ac5f920715e515b) で紹介した `Update Material Instance`, `Rebuild Material Instance Editors` を併用することで…

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">マテリアルインスタンス の Static Switch Parameter を Set する関数・ノードがなかったので追加してみた。良い感じにできたのでQiitaに書きまする <a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;ref_src=twsrc%5Etfw">#UE4Study</a> <a href="https://t.co/muQ3vIg0ca">pic.twitter.com/muQ3vIg0ca</a></p>&mdash; おかず (@pafuhana1213) <a href="https://twitter.com/pafuhana1213/status/1288778106220748802?ref_src=twsrc%5Etfw">July 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 余談( override について )
ちなみに、今回作成したノードは **Overrideが有効になっているStatic Switch Parameter しかパラメータ変更できません。** なぜなら、`Instance->GetStaticParameters();` には Override が有効になっているパラメータしか含まれていないためです。

コレに関しては…さまざまな資料で念入りに注意されている通り、**Static Switch Parameter の override の運用は十分に注意する必要がある** ので下手に対応しない方が良いと思ってそのままにしています。

[大規模タイトルにおけるエフェクトマテリアル運用](https://www.slideshare.net/EpicGamesJapan/sqex-ue4dd)
[マテリアルの注意すべきこと！～テクスチャロードとSwitch～](https://www.slideshare.net/com044/ue4switch)
[マテリアルとマテリアルインスタンスの仕組みと問題点の共有](https://www.slideshare.net/EpicGamesJapan/epic-games-japan-ue4dd)

もし force override 的なフラグをノードに追加したい場合は…UpdateStaticPermutationを実行しているコード部分を参考に実装していくことになると思います。

おしまい