UE4 ボーンのTransform制御について

# 概要
スケルタルメッシュの特定ボーンに対するトランスフォーム制御の方法についてのメモ書きです。


## 更新履歴
| 日付 | 内容 |
|:----|:-----|
|2020/01/31| アニムグラフからの制御について内容追記 |

## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.22

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

[ボーンのトランスフォーム](https://docs.unrealengine.com/ja/Engine/Animation/NodeReference/SkeletalControls/TransformBone/index.html)
[UE4 特定のボーン（Transform）に対して「位置」「回転」「スケール」を変更する（Transform(Modify)Bone）](http://kagring.blog.fc2.com/blog-entry-305.html)
[[UE4]Transform skeletal bone in C++](https://dawnarc.com/2019/01/ue4transform-skeletal-bone-in-c-/)
[UE4 キャラクターの顔を特定の位置に向ける・Transform の向きを Blueprint で制御する（Look At）](http://kagring.blog.fc2.com/blog-entry-304.html)


# アニメ―ションBPのアニムグラフから制御する
ステートマシンのポーズから変換し直接制御します。
以下BPコード例です。
![bone_trans_BP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/be9ed683-6cdb-da6d-3ca1-9dbb965ba00f.png)


[ボーンをトランスフォーム(修正)する]のノードを選択し、[Bone to Modify]の項目を制御するボーン名を指定し、[Rotation]の[Rotation Mode]を[Add To Existing]に変更します。（座標やスケールを制御する場合はそれぞれ[Translation]や[Scale]を設定します。）
![bonemodifye_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/2602e06c-5f50-a316-2a33-99484a02c374.png)

BPのノードに修正する値を設定します。

以下、結果です。
![bone_trans_Result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/e41bcccb-3398-49ac-6d02-fc28c544c45e.png)

首[neck_01]に対し、回転[-50.0, 0.0, 60.0]が適用されています。


車のタイヤなどの継続的変化するものは別途変数を用意してイベントグラフの[Blueprint Update Animation]イベントなどから更新して適用すると良いと思います。
![Tire_sample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/e96dd645-d653-91e1-cd84-1da916484a15.jpeg)

[ボーンをトランスフォーム（修正）する] -> [詳細] -> [Rotation] -> [Rotation Mode]を[Add to Existing]に設定します。


# PoseableMeshComponentを使う
ボーン情報をまとめて格納ができるコンポーネントPoseableMeshComponentを使ってみます。

PoseableMeshComponentを追加します。
![poseablecomponent.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/d406b3f6-a5e8-1ab9-3e1d-458c10b4d793.jpeg)

対象のスケルタルメッシュを設定します。
![poseable_setting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/47bd4633-1d8a-e011-b7d3-a18d7a2d4714.jpeg)

[Head]ボーンに対し、スケールを入れてみる例です。
一旦、PoseableMeshへSkeletalMeshのボーン情報をコピーしています。
![poseable_BP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/80840586-8e59-912a-c7db-85abbdf4cbd7.png)

元のスケルタルメッシュとポーズメッシュが表示され、ポーズのほうがスケール適用されて表示されます。

## C++コードについて
ボーン名で座標/回転/スケールの設定、取得メソッドがあるようです。

```cpp:PoseableMeshComponent.h
// トランスフォーム設定
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
void SetBoneTransformByName(FName BoneName, const FTransform& InTransform, EBoneSpaces::Type BoneSpace);

// 座標設定
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
void SetBoneLocationByName(FName BoneName, FVector InLocation, EBoneSpaces::Type BoneSpace);

// 回転設定
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
void SetBoneRotationByName(FName BoneName, FRotator InRotation, EBoneSpaces::Type BoneSpace);

// スケール設定
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
void SetBoneScaleByName(FName BoneName, FVector InScale3D, EBoneSpaces::Type BoneSpace);

// トランスフォーム取得
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh") 
FTransform GetBoneTransformByName(FName BoneName, EBoneSpaces::Type BoneSpace);

// 座標取得
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
FVector GetBoneLocationByName(FName BoneName, EBoneSpaces::Type BoneSpace);

// 回転取得
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
FRotator GetBoneRotationByName(FName BoneName, EBoneSpaces::Type BoneSpace);

// スケール取得
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
FVector GetBoneScaleByName(FName BoneName, EBoneSpaces::Type BoneSpace);

// リセット
UFUNCTION(BlueprintCallable, Category="Components|PoseableMesh")
void ResetBoneTransformByName(FName BoneName);
```

# Look At ノードを使う
アニメ―ションBPにて注視用にボーンの制御ができるようです。

![LookAt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/746e375d-74d6-613e-7320-ee09a5c951aa.png)

注視座標[Look At Location]へ[Bone to Bodify]で設定したボーン[Neck]が向けられる例です。[Axis]の調整が必要な場合があります。


# Blend Bone By Channel ノードを使う
アニメ―ションBPにてボーンの制御値を他のアニメ―ションから持って来られるようです。

![blendbone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/e47d8b72-5c13-41c6-f4fa-3c4d03f98326.png)

[A]のアニメーションの[Head]に[B]のアニメ―ションの[Head]ボーンのTransform値を適用しています。
制御が難しいかもしれませんが、一部のボーンの制御値を外部データ化できるので使いどころはあると思います。


# まとめ
スロットアニメ―ションなどでブレンドスペースが使えない場合のボーン制御方法をいくつか調べましたが、自然に動くように制御しようと思うととても難しいです。