Can't compile UBlendSpaceBase::UpdateParameter

Hello,

The following code doesn’t compile in 4.15 (i have a second identical block for the 2nd FBlendParameter):

UPROPERTY()
UBlendSpace *MoveBlendSpace;
------------------------------------------------------
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->UpdateParameter(AltitudeIdx, BP_AltitudeRef);

The following code:

MoveBlendSpace->UpdateParameter(1, BP_Altitude);

was working fine in 4.14, but now i get the following error at compilation:

C2039 'UpdateParameter': is not a member of 'UBlendSpace'

So i tried to explicitely define the int32 and the const FBlendParameter&, but no success so far.

Yet, i seem to be ok with the definition from the API doc:

ENGINE_API bool UpdateParameter
(
int32 Index,
const FBlendParameter & Parameter
)

Am i doing anything wrong ?

Thanks

Cedric

Hello ,

From looking at BlendSpaceBase.h, it seems that this function was moved / renamed as I cannot find the function in the 4.15 source code, although I do see it in 4.14. Unfortunately this wasn’t mentioned in the release notes from what I can tell. I’m asking around now to see if I can track down what happened and I’ll get back to you when I know more.

Hey Matthew,

Beside the vanishing of this function, which is strange enough, my project seems to have a more serious configuration problem.

I asked Visual Studio to list all the references of the function and it pointed to 4.14 files:

Yet, i have migrated the project to 4.15:

127534-uproject.jpg

I did this the way i always do: right click on the uproject file and ask for a switch to a new version. This has always worked perfectly.

I’m going to try to track this issue, but if you have any idea on the matter, that’ll probably spare me a lot of time^^

Thanks

Cedric

This is likely related to this function no longer existing in 4.15. I’m not exactly sure but I think this information is stored in the .sdf file that is present alongside the .sln for the project and isn’t overwritten between versions. You could try deleting the .sdf and see if this reference result still appears.

Thanks Matthew, i didn’t find the sdf file but it made me think of deleting the Intermediate dir and reconstructing it (right click .uproject and “generate VS project file”), which worked.

So now i get the more normal message “The symbol UpdateParameter is not referenced” when asking for the references of the missing function.

To be continued^^

I spoke with the person responsible for this change and it seems that the idea is that the blend space x/y axis data (min / max value etc) is now in the Details Panel for the asset and the function has been removed for this reason. He’s curious if there is a reason that you need this function in particular. If so, please mention it and we can look into adding the function back in if it is a valid workflow.

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.

129101-bpmonster.jpg

  • Manually create a vanilla blendspace.

  • Run the game once so all the sequences are correctly assigned to the corresponding blendspace.

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

Thank you for the explanation, . After taking a look at the use case, it would be best to make a helper class that is a friend of UBlendspaceBase to handle these types of scenarios. Usually we could go through a deprecation path for removing functions such as this, but according to the dev responsible, this wasn’t an intended use of this function at the time.

Thanks Matthew.

I’m not familiar with friendship in c++ but from what i googled, it seems that the friend class has to be declared inside the original class. But in the case of an engine class like UBlendspaceBase, that would mean recompiling the engine source. Am i wrong ?

I’d rather continue working with the vanilla engine.

Thanks

Cedric

You’re correct, that would involve editing the UBlendspaceBase class. Unfortunately, as mentioned previously, this was not the intended workflow originally so there doesn’t seem to be another option at this time.