Hey Matthew,
Thanks, so here’s the deal on my side.
(too many characters for a reply/comment so i put this in an answer, which it is not obsviously^^)
I have a lot (~100) of monsters with different skeletons to define and would like to automatize the process as much as i can.
My first idea was to try to entirely define the Blendspace by code so i wouldn’t even have to store it as an asset on disc but i could never have this working.
So my current (half automatic) workflow is the following:
- Create a BP inheriting from my own APawn derived class, which exposes some tuning animation variables and sequences.

Although it’s not completely automated, it spares me hours of repetitive work.
To be complete or maybe clearer, here are the bits of code i have been using so far (i tried to call it in the BeginPlay and PostInitializeComponent function and both seem to work).
I include various trials and errors, it makes it a bit longer/messier, but that will give you some idea off what i tried.
////////////////
// BLENDSPACE
////////////////
// SMC is the SkeletalMeshComponent of the creature
// only if SMC_00 is set
if (SMC_00->SkeletalMesh)
{
//BS_AnimInstance = NewObject<UAnimSingleNodeInstance>(this, UAnimSingleNodeInstance::StaticClass(), FName("ThisAnimInstance"));
BS_AnimInstance = SMC_00->GetSingleNodeInstance();
#if WITH_EDITOR
FBlendParameter BP_Action;
BP_Action.DisplayName = "Action";
BP_Action.GridNum = 4;
BP_Action.Min = 0.f;
BP_Action.Max = 1.f;
const FBlendParameter &BP_ActionRef = BP_Action;
int32 ActionIdx = 0;
FBlendParameter BP_Altitude;
BP_Altitude.DisplayName = "Altitude";
BP_Altitude.GridNum = 4;
BP_Altitude.Min = 0.f;
BP_Altitude.Max = 1.f;
const FBlendParameter &BP_AltitudeRef = BP_Altitude;
int32 AltitudeIdx = 1;
MoveBlendSpace = Cast<UBlendSpace>(BS_AnimInstance->GetCurrentAsset());
// a security that is never used
if (!MoveBlendSpace) MoveBlendSpace = NewObject<UBlendSpace>(this, UBlendSpace::StaticClass());
// Doesn't work
//MoveBlendSpace = NewObject<UBlendSpace>(BS_AnimInstance, UBlendSpace::StaticClass(), FName("MoveBlendSpace"));
//MoveBlendSpace->SetSkeleton(SMC_00->SkeletalMesh->Skeleton);
//MoveBlendSpace->ValidateSkeleton();
//MoveBlendSpace->SetPreviewMesh(SMC_00->SkeletalMesh);
MoveBlendSpace->SetSkeleton(SMC_00->SkeletalMesh->Skeleton);
// worked in 4.14
//MoveBlendSpace->UpdateParameter(ActionIdx, BP_ActionRef);
//MoveBlendSpace->UpdateParameter(AltitudeIdx, BP_AltitudeRef);
// needed in 4.14, not in 4.15 with the new AddSample signature
//FBlendSample GroundIdleSample = FBlendSample(GroundIdleSequence, FVector(0.f, 0.f, 0.f), true);
//FBlendSample GroundMoveSample = FBlendSample(GroundMoveSequence, FVector(0.f, 1.f, 0.f), true);
//FBlendSample FlyIdleSample = FBlendSample(FlyIdleSequence, FVector(1.f, 0.f, 0.f), true);
//FBlendSample FlyMoveSample = FBlendSample(FlyMoveSequence, FVector(1.f, 1.f, 0.f), true);
//MoveBlendSpace->ClearAllSamples();
MoveBlendSpace->AddSample(GroundIdleSequence, FVector(0.f, 0.f, 0.f));
MoveBlendSpace->AddSample(GroundMoveSequence, FVector(0.f, 1.f, 0.f));
MoveBlendSpace->AddSample(FlyIdleSequence, FVector(1.f, 0.f, 0.f));
MoveBlendSpace->AddSample(FlyMoveSequence, FVector(1.f, 1.f, 0.f));
MoveBlendSpace->ValidateSampleData();
//SMC_00->SetAnimInstanceClass(UYagPawnAnimInstance::StaticClass());
SMC_00->AnimationData.AnimToPlay = MoveBlendSpace;
SMC_00->AnimationData.bSavedLooping = true;
SMC_00->AnimationData.bSavedPlaying = true;
SMC_00->AnimationData.SavedPlayRate = 1.f;
SMC_00->AnimationData.SavedPosition = 0.f;
// various tests
//SMC_00->OverrideAnimationData(MoveBlendSpace, true, true, 0.f, 1.f); // maintient l'animation à speed = 0
//BS_AnimInstance->SetAnimationAsset(MoveBlendSpace); // annule l'animation de base
//SMC_00->ValidateAnimation();
//BS_AnimInstance->SetLooping(true);
//BS_AnimInstance->SetPlaying(true);
//BS_AnimInstance->SetPlayRate(1.f);
//BS_AnimInstance->PlayAnim(true, 1.f, 0.f);
//SMC_00->AnimationData.Initialize(BS_AnimInstance); // annule l'animation de base
//SMC_00->PlayAnimation(MoveBlendSpace, true);
BS_AnimInstance->SetBlendSpaceInput(FVector(0.f));
//BS_AnimInstance->SetRootMotionMode(ERootMotionMode::IgnoreRootMotion);
//SMC_00->SetAnimation(MoveBlendSpace); // annule l'animation de base
//SMC_00->Play(true);
#endif // WITH_EDITOR
}
Sorry about the messy code, that’s WIP/testing, if you have ANY better idea/workflow to achieve what i want, i’m all ears^^
For example, it could be nice to have the possibility to inherit Blendspaces, so i could create one master BlendSpace with variable SkeletalMesh/sequences, etc, and then just parent it to each creature’s own BlendSpace.
Not sure it’s possible because of the somewhat pecular nature of blendspaces, but it’s the sort of idea i’m trying to look at.
Thanks a lot.
Cedric