はじめに
StateTreeのParameterはStateTreeComponentで初期値を設定することができ、

TaskやConditionなどで紐づけ(Binding)して利用することが可能です。

また、StateTree全体だけでなく、State毎にParameterを追加・設定することが可能です。

しかし、UE5.5時点では、「実行中にParameterの値変更すること」は C++側でしかできません。
今後のアップデートでBPからも変更可能になる可能性は高いとは思いますが、ひとまず本記事では C++ を使って Parameterを変更する方法について紹介します!
FStateTreePropertyRef を使えば Parameter を変更できる!
結論から言えば、FStateTreePropertyRef を使うことでStateTree全体・State の Parameterを変更することができます。
例えば、Bool型のParameterを反転するStateTree Taskの場合は以下のように実装します。
// FStateTreeTask_ToggleBoolPropertyが実行中に扱うパラメータ USTRUCT() struct XXX_API FStateTreeTask_ToggleBoolProperty_InstanceData { GENERATED_BODY() // Bool型のParameterのみを扱うプロパティ参照 UPROPERTY(EditAnywhere, Category = "", meta = (RefType = "Bool")) FStateTreePropertyRef BoolPropertyRef; }; USTRUCT(meta = (DisplayName = "Toggle Bool")) struct XXX_API FStateTreeTask_ToggleBoolProperty : public FStateTreeTaskCommonBase { GENERATED_BODY() // Taskが実行中に扱うパラメータの型を指定 using FInstanceDataType = FStateTreeTask_ToggleBoolProperty_InstanceData; virtual const UStruct* GetInstanceDataType() const override { return FInstanceDataType::StaticStruct(); } // EnterState State開始時に呼ばれる virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const override; };
EStateTreeRunStatus FStateTreeTask_ToggleBoolProperty::EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const { // FStateTreeTask_ToggleBoolProperty_InstanceData を取得 FInstanceDataType* InstanceData = Context.GetInstanceDataPtr<FInstanceDataType>(*this); check(InstanceData); // BindingしたBoolプロパティを取得し、反転する if (bool* BoolPropertyPtr = InstanceData->BoolPropertyRef.GetMutablePtr<bool>(Context)) { *BoolPropertyPtr = !(*BoolPropertyPtr); } // FinishTask を呼ぶ場合はSucceeded or Failedを返す return EStateTreeRunStatus::Running; }
「InstancedData?なんでこんな組み方してるの?」という方は、こちらをどうぞ https://qiita.com/BONTAN/items/8d78605c9d2b3d1fabde#instance-data
StateTree上では通常のプロパティと同様の操作でBindingできます。このときBinding候補になるのは、FStateTreePropertyRef の RefType で指定した型でフィルタリングされたものです。

これで、Taskが実行されるたびにBool型のParameter「IsClosed」が反転されます。やったね!
FStateTreePropertyRef の RefType について
FStateTreePropertyRef がサポートしている型や、RefTypeの記述ルールは下記コードに書かれています。
Engine\Plugins\Runtime\StateTree\Source\StateTreeModule\Public\StateTreePropertyRef.h
以下はそのコメントからの抜粋です。
- RefType = "
" - 参照するプロパティのタイプのリストをカンマ区切りで指定します
- サポートされるタイプ:
bool,byte,int32,int64,float,double,Name,String,Text,UObjectポインター、およびStruct ObjectとStructは正規パス名を使用する必要があります- 複数のタイプを指定した場合、
GetMutablePtrTupleを使用して正しいタイプにアクセスすることができます
- IsRefToArray
- これを指定すると、参照は
TArray<RefType>になります
- これを指定すると、参照は
- CanRefToArray
- これを指定すると、参照は
RefTypeまたはTArray<RefType>になります
- これを指定すると、参照は
- Optional
- これを指定すると、参照が設定されていなくてもエラーを出しません(指定されない場合はコンパイラがエラーを報告します)
例:
// float の参照 UPROPERTY(EditAnywhere, meta = (RefType = "float")) FStateTreePropertyRef RefToFloat; // FTestStructBase の参照 UPROPERTY(EditAnywhere, meta = (RefType = "/Script/ModuleName.TestStructBase")) FStateTreePropertyRef RefToTest; // TArray<FTestStructBase> の参照 UPROPERTY(EditAnywhere, meta = (RefType = "/Script/ModuleName.TestStructBase", IsRefToArray)) FStateTreePropertyRef RefToArrayOfTests; // Vector, TArray<FVector>, AActor*, TArray<AActor*> の参照 UPROPERTY(EditAnywhere, meta = (RefType = "/Script/CoreUObject.Vector, /Script/Engine.Actor", CanRefToArray)) FStateTreePropertyRef RefToLocationLikeTypes;
そして、複数のRefType が設定されている場合は以下のようにして取得します(FStateTreeRunEnvQueryTask より)。
UPROPERTY(EditAnywhere, Category = Out, meta = (RefType = "/Script/CoreUObject.Vector, /Script/Engine.Actor", CanRefToArray)) FStateTreePropertyRef Result;
auto [VectorPtr, ActorPtr, ArrayOfVector, ArrayOfActor] = InstanceData.Result.GetMutablePtrTuple<FVector, AActor*, TArray<FVector>, TArray<AActor*>>(Context); if (VectorPtr) { //*VectorPtr = InstanceData.QueryResult->GetItemAsLocation(0); } else if (ActorPtr) { //*ActorPtr = InstanceData.QueryResult->GetItemAsActor(0); } else if (ArrayOfVector) { //InstanceData.QueryResult->GetAllAsLocations(*ArrayOfVector); } else if (ArrayOfActor) { //InstanceData.QueryResult->GetAllAsActors(*ArrayOfActor); }
さいごに
これで StateTreeにおけるパラメータを C++ から 変更することが可能になります!これをうまく活用することで、これまで Actor側で持っていたフラグをStateTree側に持っていくことができ、より汎用的なStateTreeを組むことが可能になる…はずです!
ただC++での段取りが少々めんどうなので、扱うパラメータが確定するまでは Context の Actor・AI Controllerが持つプロパティで代用するのがいいかも…今後に期待!
おまけ
C++の場合はFStateTreePropertyRefを使いますが、BPの場合はFStateTreeBlueprintPropertyRefになる仕様の模様。今後のBP対応状況に関しては FStateTreeBlueprintPropertyRefを中心に見ていくのが良さそうです
おしまい