State Tree: How can I access parameters from outside the component?

Hi there,

WIth behavior trees, from any object I can access the current values from the blackboard component so long as I can reference the AIController:

I have recently switched to State Trees. How can I access the current parameters of a State Tree in asimilar fashion to the above?

You will need c++ to access parameters as they don’t seem to be accessible via blueprints from external sources.

You would probably need to extend StateTreeComponent.h to get access to the state tree reference where the parameters reside (the ref itself is protected so it’s not exposed by default)

image

from the reference you can access the parameters via GetParameters (StateTreeReference.h)

Hopefully Epic will expose the parameters from BP. For now you can only set them via BP.

Hey,

I just gave this a go but unfortunately it provides me with the default values of the parameters. When they change during runtime the values here do not update, it continues to provide the default value.

image


(note, in my code here I was originally trying to get an actor from the Parameters using “GetValueObject”. I switched to getting a float to remove the step of casting from Object to Actor. I wanted to ensure that I could successfully get the parameter without the extra step that could possibly be cause for this being unsuccessful)

I can see there has been some updates in 5.6 so I’ll get round to checking that out though that doesn’t resolve this issue yet.

In case anyone from the future comes here, I’m yet to solve the problem but I got around it by creating a task that sets this variable in the class I required it.

There still doesn’t seem to be a way to access them via blueprint. I recommend just adding variables within a StateTree category in the AI controller.

// Fill out your copyright notice in the Description page of Project Settings.

#include "TycoonStateTreeComponent.h"
#include "StructView.h"          // 核心依赖:用于解析 FConstStructView
#include "UObject/UnrealType.h"  // 核心依赖:用于 FProperty 反射系统
#include "GameFramework/Actor.h"
#include "Components/ActorComponent.h"

// UTycoonStateTreeComponent 的构造函数保留
UTycoonStateTreeComponent::UTycoonStateTreeComponent()
{
    PrimaryComponentTick.bCanEverTick = true;
}

// ========================================================
// 1. 获取 整数 (Int32)
// ========================================================
int32 UTycoonStateTreeComponent::GetStateTreeInt(FName VariableName, bool& bSuccess)
{
    bSuccess = false;
    FConstStructView ParamView = InstanceData.GetStorage().GetGlobalParameters();
    if (!ParamView.IsValid()) return 0;

    if (const UScriptStruct* ScriptStruct = ParamView.GetScriptStruct())
    {
       if (FIntProperty* IntProp = FindFProperty<FIntProperty>(ScriptStruct, VariableName))
       {
          if (const int32* RealValuePtr = IntProp->ContainerPtrToValuePtr<int32>(ParamView.GetMemory()))
          {
             bSuccess = true;
             return *RealValuePtr;
          }
       }
    }
    return 0;
}

// ========================================================
// 2. 获取 世界物体 (AActor*)
// ========================================================
AActor* UTycoonStateTreeComponent::GetStateTreeActor(FName VariableName, bool& bSuccess)
{
    bSuccess = false;
    FConstStructView ParamView = InstanceData.GetStorage().GetGlobalParameters();
    if (!ParamView.IsValid()) return nullptr;

    if (const UScriptStruct* ScriptStruct = ParamView.GetScriptStruct())
    {
        // 所有对象引用在虚幻字段中统一由 FObjectProperty 表达
        if (FObjectProperty* ObjProp = FindFProperty<FObjectProperty>(ScriptStruct, VariableName))
        {
            // 安全读取容器内的 UObject 裸指针位置
            UObject* RawObj = ObjProp->GetObjectPropertyValue_InContainer(ParamView.GetMemory());
            if (RawObj)
            {
                // 向下安全转型为 AActor
                if (AActor* TargetActor = Cast<AActor>(RawObj))
                {
                    bSuccess = true;
                    return TargetActor;
                }
            }
        }
    }
    return nullptr;
}

// ========================================================
// 3. 获取 物体组件 (UActorComponent*)
// ========================================================
UActorComponent* UTycoonStateTreeComponent::GetStateTreeComponent(FName VariableName, bool& bSuccess)
{
    bSuccess = false;
    FConstStructView ParamView = InstanceData.GetStorage().GetGlobalParameters();
    if (!ParamView.IsValid()) return nullptr;

    if (const UScriptStruct* ScriptStruct = ParamView.GetScriptStruct())
    {
        if (FObjectProperty* ObjProp = FindFProperty<FObjectProperty>(ScriptStruct, VariableName))
        {
            UObject* RawObj = ObjProp->GetObjectPropertyValue_InContainer(ParamView.GetMemory());
            if (RawObj)
            {
                if (UActorComponent* TargetComp = Cast<UActorComponent>(RawObj))
                {
                    bSuccess = true;
                    return TargetComp;
                }
            }
        }
    }
    return nullptr;
}

// ========================================================
// 4. 获取 三维向量 (FVector)
// ========================================================
FVector UTycoonStateTreeComponent::GetStateTreeVector(FName VariableName, bool& bSuccess)
{
    bSuccess = false;
    FConstStructView ParamView = InstanceData.GetStorage().GetGlobalParameters();
    if (!ParamView.IsValid()) return FVector::ZeroVector;

    if (const UScriptStruct* ScriptStruct = ParamView.GetScriptStruct())
    {
        // FVector 在虚幻反射底层是一个纯数学结构体,由 FStructProperty 承接
        if (FStructProperty* StructProp = FindFProperty<FStructProperty>(ScriptStruct, VariableName))
        {
            // 防御性安全验证:确保这个结构体类型确实是 FVector
            if (StructProp->Struct == TBaseStructure<FVector>::Get())
            {
                if (const FVector* VectorPtr = StructProp->ContainerPtrToValuePtr<FVector>(ParamView.GetMemory()))
                {
                    bSuccess = true;
                    return *VectorPtr;
                }
            }
        }
    }
    return FVector::ZeroVector;
}

// ========================================================
// 5. 获取 向量数组 (TArray<FVector>)
// ========================================================
TArray<FVector> UTycoonStateTreeComponent::GetStateTreeVectorArray(FName VariableName, bool& bSuccess)
{
    bSuccess = false;
    FConstStructView ParamView = InstanceData.GetStorage().GetGlobalParameters();
    if (!ParamView.IsValid()) return TArray<FVector>();

    if (const UScriptStruct* ScriptStruct = ParamView.GetScriptStruct())
    {
        // 动态数组由 FArrayProperty 承接
        if (FArrayProperty* ArrayProp = FindFProperty<FArrayProperty>(ScriptStruct, VariableName))
        {
            // 【核心关键】:穿透剥离外壳,验证数组内部的“核心元素类型(Inner)”是不是 FVector 结构体
            if (FStructProperty* InnerStructProp = CastField<FStructProperty>(ArrayProp->Inner))
            {
                if (InnerStructProp->Struct == TBaseStructure<FVector>::Get())
                {
                    // 只要元素类型和 Offset 完全匹配,直接通过强类型指针整体搬运整个 TArray 的内存块
                    if (const TArray<FVector>* ArrayPtr = ArrayProp->ContainerPtrToValuePtr<TArray<FVector>>(ParamView.GetMemory()))
                    {
                        bSuccess = true;
                        return *ArrayPtr;
                    }
                }
            }
        }
    }
    return TArray<FVector>();
}