转自:https://forums.unrealengine.com/development-discussion/c-gameplay-programming/104831-creating-and-using-a-blendspace-in-c

creating and using a blendspace in c++

12-23-2016, 07:09 PM
 
Hello all,

i'm trying to automatize the animation of (a lot of) pawns and would like not to have to define ~100 blendspaces and animblueprint by hand in the editor.

If i can get it to work, i'll just have to create blueprints inheriting from this class and set the skeletal mesh and animations.

This subject seems to pop up every now and then, there are a few post on the answerhub, and even a wiki by Rama, but all of them seem to assume that the BlendSpace is created in the editor.

As you can see, i'm trying several methods (via the skeletal mesh component and the anim instance) to animate the mesh with the blendspace, none of them works so far.
I tried everything i could find related to animation and blendspace in the api documentation.

I can spawn the blueprint, but the mesh remains static so obviously i miss something.

I tried to set this in the blueprint, and i can see the debuging flow correctly going through everything.

I can't check visually the blendspace, so i'm a bit lost and dry now.

Here's the code:

void AYagPawn::BeginPlay()
{
Super::BeginPlay(); [...] // creating the BS (SMC_00 is a USkeletalMeshComponent)
ThisBlendSpace1D = NewObject<UBlendSpace1D>(this, UBlendSpace1D::StaticClass());
ThisBlendSpace1D->SetSkeleton(SMC_00->SkeletalMesh->Skeleton); // setting a parameter for the BS
FBlendParameter BP_Speed;
BP_Speed.DisplayName = "Speed";
BP_Speed.GridNum = ;
BP_Speed.Min = .f;
BP_Speed.Max = .f;
ThisBlendSpace1D->UpdateParameter(, BP_Speed); // adding two sample (at 0 and 100)
// IdleSequence and MoveSequence are UAnimSequence to be set in the BP inheriting this pawn class
FBlendSample IdleSample = FBlendSample(IdleSequence, FVector(.f, .f, .f), false);
FBlendSample MoveSample = FBlendSample(MoveSequence, FVector(.f, .f, .f), false);
ThisBlendSpace1D->AddSample(IdleSample);
ThisBlendSpace1D->AddSample(MoveSample); // first method
SMC_00->PlayAnimation(ThisBlendSpace1D, true); // second method
SMC_00->SetAnimation(ThisBlendSpace1D);
SMC_00->Play(true); // third method
SMC_00->OverrideAnimationData(ThisBlendSpace1D, true, true, .f, .f); // fourth method
BS_AnimInstance = Cast<UAnimSingleNodeInstance>(SMC_00->GetAnimInstance());
BS_AnimInstance->SetAnimationAsset(ThisBlendSpace1D);
BS_AnimInstance->PlayAnim(true, .f, .f);
} void AYagPawn::Tick( float DeltaSeconds)
{
Super::Tick(DeltaSeconds); [...] // update BS with Speed (a float)
BS_AnimInstance->SetBlendSpaceInput(FVector(Speed, .f, .f)); // useless in principle but i tried
SMC_00->OverrideAnimationData(ThisBlendSpace1D, true, true, .f, .f);
}

And here is the variables section in the BP:

As you can see, the BS is still empty (normal, it will be created in the begin play function at runtime) and both animations have default values.

Any idea ?

Thanks

Cedric

EDIT: i realized i wasn't setting the animation mode, so i added this in the constructor:

Code:
SMC_00->SetAnimationMode(EAnimationMode::AnimationSingleNode);

But it still doesn't work.

Answers:

Edit: I should have read your entire question. I'm interested in this so I'm going to help you get the bottom of it! You're probably missing an update call somewhere, or you need to serialize the result to an asset or something. I'll report back.

Here's a compiled simple animation blueprint. It uses a blendspace called "Strafe_IP" and has two variables: Right, Forward. Note that the Character class doesn't appear to call or update the animation - it only sets it initially.

Code:
UCLASS(config=Engine, Blueprintable, BlueprintType, meta=(ReplaceConverted="/Game/Blueprints/BPA_Test.BPA_Test_C", OverrideNativeName="BPA_Test_C"))
class UBPA_Test : public UAnimInstance
{
public:
GENERATED_BODY() UPROPERTY(meta=(OverrideNativeName="AnimGraphNode_Root_6D3BF226443B80030387A5AADD092A5D"))
FAnimNode_Root Root; UPROPERTY(meta=(OverrideNativeName="AnimGraphNode_BlendSpacePlayer_44691A814B28B34EF79F7B8F71402E07"))
FAnimNode_BlendSpacePlayer BlendSpacePlayer; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, meta=(DisplayName="Right", Category="Default", OverrideNativeName="Right"))
float Right; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, meta=(DisplayName="Forward", Category="Default", OverrideNativeName="Forward"))
float Forward; UBPA_Test(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
static void __CustomDynamicClassInitialization(UDynamicClass* InDynamicClass);
static void __StaticDependencies_CommonAssets(TArray<FBlueprintDependencyData>& AssetsToLoad);
};
UBPA_Test::UBPA_Test(const FObjectInitializer& ObjectInitializer) : Super()
{
if(HasAnyFlags(RF_ClassDefaultObject) && (UBPA_Test::StaticClass() == GetClass()))
UBPA_Test::__CustomDynamicClassInitialization(CastChecked<UDynamicClass>(GetClass())); Root.Result.LinkID = ;
BlendSpacePlayer.BlendSpace = CastChecked<UBlendSpaceBase>(CastChecked<UDynamicClass>(UBPA_Test::StaticClass())->UsedAssets[], ECastCheckedType::NullAllowed);
BlendSpacePlayer.EvaluateGraphExposedInputs.CopyRecords = TArray<FExposedValueCopyRecord> ();
BlendSpacePlayer.EvaluateGraphExposedInputs.CopyRecords.AddUninitialized();
FExposedValueCopyRecord::StaticStruct()->InitializeStruct(BlendSpacePlayer.EvaluateGraphExposedInputs.CopyRecords.GetData(), ); auto& _Right = BlendSpacePlayer.EvaluateGraphExposedInputs.CopyRecords[];
_Right.SourcePropertyName = FName(TEXT("Right"));
_Right.DestProperty = FindFieldChecked<UFloatProperty>(FAnimNode_BlendSpacePlayer::StaticStruct(), TEXT("X"));
_Right.Size = ; auto& _Forward = BlendSpacePlayer.EvaluateGraphExposedInputs.CopyRecords[];
_Forward.SourcePropertyName = FName(TEXT("Forward"));
_Forward.DestProperty = FindFieldChecked<UFloatProperty>(FAnimNode_BlendSpacePlayer::StaticStruct(), TEXT("Y"));
_Forward.Size = ; Right = 0.000000f;
Forward = 0.000000f;
} void UBPA_Test::__CustomDynamicClassInitialization(UDynamicClass* InDynamicClass)
{
ensure( == InDynamicClass->ReferencedConvertedFields.Num());
ensure( == InDynamicClass->MiscConvertedSubobjects.Num());
ensure( == InDynamicClass->DynamicBindingObjects.Num());
ensure( == InDynamicClass->ComponentTemplates.Num());
ensure( == InDynamicClass->Timelines.Num());
ensure(nullptr == InDynamicClass->AnimClassImplementation); InDynamicClass->AssembleReferenceTokenStream();
FConvertedBlueprintsDependencies::FillUsedAssetsInDynamicClass(InDynamicClass, &__StaticDependencies_DirectlyUsedAssets); auto AnimClassData = NewObject<UAnimClassData>(InDynamicClass, TEXT("AnimClassData"));
AnimClassData->TargetSkeleton = CastChecked<USkeleton>(CastChecked<UDynamicClass>(UBPA_Test::StaticClass())->UsedAssets[], ECastCheckedType::NullAllowed);
AnimClassData->RootAnimNodeIndex = ;
AnimClassData->RootAnimNodeProperty = InDynamicClass->FindStructPropertyChecked(TEXT("Root"));
AnimClassData->AnimNodeProperties = TArray<UStructProperty*> ();
AnimClassData->AnimNodeProperties.Reserve();
AnimClassData->AnimNodeProperties.Add(InDynamicClass->FindStructPropertyChecked(TEXT("Root")));
AnimClassData->AnimNodeProperties.Add(InDynamicClass->FindStructPropertyChecked(TEXT("BlendSpacePlayer")));
InDynamicClass->AnimClassImplementation = AnimClassData;
} void UBPA_Test::__StaticDependencies_CommonAssets(TArray<FBlueprintDependencyData>& AssetsToLoad)
{
const TCHAR* __Local__3 = TEXT("/Game/MovementAnimsetPro/BlendSpaces");
const TCHAR* __Local__4 = TEXT("/Game/Mannequin/Character/Mesh");
FBlueprintDependencyData LocAssets[] =
{
FBlueprintDependencyData(__Local__3, TEXT("Strafe_IP"), TEXT("Strafe_IP"), TEXT("/Script/Engine"), TEXT("BlendSpace")),
FBlueprintDependencyData(__Local__4, TEXT("UE4_Mannequin_Skeleton"), TEXT("UE4_Mannequin_Skeleton"), TEXT("/Script/Engine"), TEXT("Skeleton")),
};
for(auto& LocAsset : LocAssets) { AssetsToLoad.Add(LocAsset); }
} struct FRegisterHelper__UBPA_Test
{
FRegisterHelper__UBPA_Test()
{
FConvertedBlueprintsDependencies::Get().RegisterClass(TEXT("/Game/Blueprints/BPA_Test"), &UBPA_Test::__StaticDependenciesAssets);
}
static FRegisterHelper__UBPA_Test Instance;
}; FRegisterHelper__UBPA_Test FRegisterHelper__UBPA_Test::Instance;

最新文章

  1. 编写ros串口节点,使用官方serial包
  2. Python中的参数
  3. [TED] New video technology that reveals an objects hidden properties
  4. C#类、接口、虚方法和抽象方法0322
  5. 用php随机生成福彩双色球号码的2种方法
  6. iOS - AutoLayout
  7. window.opener调用父窗体方法的用法
  8. [ActionScript 3.0] flash如何访问父级或者舞台上的变量、函数等的方法
  9. VML/SVG在Web开发中一些常见的框架
  10. 华为上机:IP地址转换
  11. java 复习003
  12. 我的第一篇文章 —— IE6的那些css常见bug(汇总)
  13. 【图像浏览】FastStone Image Viewer——快速、小巧、功能强大
  14. 每天一个Linux命令(23)--linux 目录结构(二)
  15. 初涉算法——C++
  16. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(三)用户接口层之RTSP命令
  17. 【汇编语言】Win10 安装 DOXBox0.74
  18. 下载 Internet Explorer 11(脱机安装程序)
  19. ab,qps 并发连接数
  20. STM32的SPI2操作Flash

热门文章

  1. 解决tomcat同时部署两个SpringBoot应用提示InstanceAlreadyExistsException
  2. 2019微软Power BI 每月功能更新系列——Power BI 4月版本功能完整解读
  3. [转]https://www.jianshu.com/p/06443248f4d8
  4. Find Longest common string
  5. leetcode 381.Insert Delete GetRandom
  6. 蓝桥杯——X星球居民问题
  7. PyCharm提交代码到git
  8. 手机连接fiddler之后,安装证书的方法
  9. 我的代码-flask
  10. mysql并发更新