Extending BlendSpace

I used the c++ class wizard to extend from BlendSpace, but I am receiving the following errors when trying to compile and I’m not sure how to fix them. I’m using version 4.5.1.


1>------ Build started: Project: Test, Configuration: Development_Editor x64 ------
1>  Performing 1 actions (4 in parallel)
1>  [1/1] Link UE4Editor-Test.dll
1>     Creating library C:\Users\154464\Documents\Unreal Projects\Test\Intermediate\Build\Win64\TestEditor\Development\UE4Editor-Test.lib and object C:\Users\154464\Documents\Unreal Projects\Test\Intermediate\Build\Win64\TestEditor\Development\UE4Editor-Test.exp
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimationAsset::PostLoad(void)" (?PostLoad@UAnimationAsset@@UEAAXXZ)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimationAsset::PostLoad(void)" (?PostLoad@UAnimationAsset@@UEAAXXZ)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimationAsset::Serialize(class FArchive &)" (?Serialize@UAnimationAsset@@UEAAXAEAVFArchive@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimationAsset::Serialize(class FArchive &)" (?Serialize@UAnimationAsset@@UEAAXAEAVFArchive@@@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::PostLoad(void)" (?PostLoad@UBlendSpaceBase@@UEAAXXZ)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::PostLoad(void)" (?PostLoad@UBlendSpaceBase@@UEAAXXZ)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::PostEditChangeProperty(struct FPropertyChangedEvent &)" (?PostEditChangeProperty@UBlendSpaceBase@@UEAAXAEAUFPropertyChangedEvent@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::PostEditChangeProperty(struct FPropertyChangedEvent &)" (?PostEditChangeProperty@UBlendSpaceBase@@UEAAXAEAUFPropertyChangedEvent@@@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::TickAssetPlayerInstance(struct FAnimTickRecord const &,class UAnimInstance *,struct FAnimAssetTickContext &)const " (?TickAssetPlayerInstance@UBlendSpaceBase@@UEBAXAEBUFAnimTickRecord@@PEAVUAnimInstance@@AEAUFAnimAssetTickContext@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::TickAssetPlayerInstance(struct FAnimTickRecord const &,class UAnimInstance *,struct FAnimAssetTickContext &)const " (?TickAssetPlayerInstance@UBlendSpaceBase@@UEBAXAEBUFAnimTickRecord@@PEAVUAnimInstance@@AEAUFAnimAssetTickContext@@@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UBlendSpaceBase::GetAllAnimationSequencesReferred(class TArray<class UAnimSequence *,class FDefaultAllocator> &)" (?GetAllAnimationSequencesReferred@UBlendSpaceBase@@UEAA_NAEAV?$TArray@PEAVUAnimSequence@@VFDefaultAllocator@@@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UBlendSpaceBase::GetAllAnimationSequencesReferred(class TArray<class UAnimSequence *,class FDefaultAllocator> &)" (?GetAllAnimationSequencesReferred@UBlendSpaceBase@@UEAA_NAEAV?$TArray@PEAVUAnimSequence@@VFDefaultAllocator@@@@@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::ReplaceReferredAnimations(class TMap<class UAnimSequence *,class UAnimSequence *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class UAnimSequence *,class UAnimSequence *,0> > const &)" (?ReplaceReferredAnimations@UBlendSpaceBase@@UEAAXAEBV?$TMap@PEAVUAnimSequence@@PEAV1@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@PEAVUAnimSequence@@PEAV1@$0A@@@@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UBlendSpaceBase::ReplaceReferredAnimations(class TMap<class UAnimSequence *,class UAnimSequence *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class UAnimSequence *,class UAnimSequence *,0> > const &)" (?ReplaceReferredAnimations@UBlendSpaceBase@@UEAAXAEBV?$TMap@PEAVUAnimSequence@@PEAV1@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@PEAVUAnimSequence@@PEAV1@$0A@@@@@@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl UBlendSpaceBase::ValidateSampleInput(struct FBlendSample &,int)const " (?ValidateSampleInput@UBlendSpaceBase@@MEBA_NAEAUFBlendSample@@H@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl UBlendSpaceBase::ValidateSampleInput(struct FBlendSample &,int)const " (?ValidateSampleInput@UBlendSpaceBase@@MEBA_NAEAUFBlendSample@@H@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UBlendSpace::IsValidAdditive(void)const " (?IsValidAdditive@UBlendSpace@@UEBA_NXZ)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UBlendSpace::IsValidAdditive(void)const " (?IsValidAdditive@UBlendSpace@@UEBA_NXZ)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl UBlendSpace::SnapToBorder(struct FBlendSample &)const " (?SnapToBorder@UBlendSpace@@MEBAXAEAUFBlendSample@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl UBlendSpace::SnapToBorder(struct FBlendSample &)const " (?SnapToBorder@UBlendSpace@@MEBAXAEAUFBlendSample@@@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual enum EBlendSpaceAxis __cdecl UBlendSpace::GetAxisToScale(void)const " (?GetAxisToScale@UBlendSpace@@MEBA?AW4EBlendSpaceAxis@@XZ)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual enum EBlendSpaceAxis __cdecl UBlendSpace::GetAxisToScale(void)const " (?GetAxisToScale@UBlendSpace@@MEBA?AW4EBlendSpaceAxis@@XZ)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl UBlendSpace::IsSameSamplePoint(class FVector const &,class FVector const &)const " (?IsSameSamplePoint@UBlendSpace@@MEBA_NAEBVFVector@@0@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl UBlendSpace::IsSameSamplePoint(class FVector const &,class FVector const &)const " (?IsSameSamplePoint@UBlendSpace@@MEBA_NAEBVFVector@@0@Z)
1>TestBlendSpace.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl UBlendSpace::GetRawSamplesFromBlendInput(class FVector const &,class TArray<struct FGridBlendSample,class FDefaultAllocator> &)const " (?GetRawSamplesFromBlendInput@UBlendSpace@@MEBAXAEBVFVector@@AEAV?$TArray@UFGridBlendSample@@VFDefaultAllocator@@@@@Z)
1>Test.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl UBlendSpace::GetRawSamplesFromBlendInput(class FVector const &,class TArray<struct FGridBlendSample,class FDefaultAllocator> &)const " (?GetRawSamplesFromBlendInput@UBlendSpace@@MEBAXAEBVFVector@@AEAV?$TArray@UFGridBlendSample@@VFDefaultAllocator@@@@@Z)
1>C:\Users\154464\Documents\Unreal Projects\Test\Binaries\Win64\UE4Editor-Test.dll : fatal error LNK1120: 13 unresolved externals
1>  -------- End Detailed Actions Stats -----------------------------------------------------------
1>ERROR : UBT error : Failed to produce item: C:\Users\154464\Documents\Unreal Projects\Test\Binaries\Win64\UE4Editor-Test.dll
1>  Cumulative action seconds (8 processors): 0.00 building projects, 0.00 compiling, 0.00 creating app bundles, 0.00 generating debug info, 0.17 linking, 0.00 other
1>  UBT execution time: 4.94 seconds
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.MakeFile.Targets(38,5): error MSB3073: The command ""C:\Program Files\Unreal Engine\4.5\Engine\Build\BatchFiles\Build.bat" TestEditor Win64 Development "C:\Users\154464\Documents\Unreal Projects\Test\Test.uproject" -rocket" exited with code -1.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

TestBlendSpace.h


#pragma once

#include "Animation/BlendSpace.h"
#include "TestBlendSpace.generated.h"

/**
 * 
 */
UCLASS()
class TEST_API UTestBlendSpace : public UBlendSpace
{
	GENERATED_UCLASS_BODY()
	
};


TestBlendSpace.cpp


#include "Test.h"
#include "TestBlendSpace.h"


UTestBlendSpace::UTestBlendSpace(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
}

You need to override the virtual functions

Thanks. I’m still getting the same errors though. Does this look correct?

TestBlendSpace.h

#pragma once

#include "Animation/BlendSpace.h"
#include "TestBlendSpace.generated.h"


UCLASS()
class TEST_API UTestBlendSpace : public UBlendSpace
{
	GENERATED_UCLASS_BODY()

public:
	virtual void PostLoad() override;
	virtual void Serialize(FArchive& Ar) override;
	virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
	virtual void TickAssetPlayerInstance(const FAnimTickRecord& Instance, class UAnimInstance* InstanceOwner, FAnimAssetTickContext& Context) const override;
	virtual bool GetAllAnimationSequencesReferred(TArray<UAnimSequence*>& AnimationSequences) override;
	virtual void ReplaceReferredAnimations(const TMap<UAnimSequence*, UAnimSequence*>& ReplacementMap) override;

	virtual bool IsValidAdditive() const override;

protected:
	virtual bool ValidateSampleInput(FBlendSample & BlendSample, int32 OriginalIndex = INDEX_NONE) const override;

	virtual void SnapToBorder(FBlendSample& Sample) const override;
	virtual EBlendSpaceAxis GetAxisToScale() const override;
	virtual bool IsSameSamplePoint(const FVector& SamplePointA, const FVector& SamplePointB) const override;
	virtual void GetRawSamplesFromBlendInput(const FVector &BlendInput, TArray<FGridBlendSample> & OutBlendSamples) const override;
	
};

TestBlendSpace.cpp

#include "Test.h"
#include "TestBlendSpace.h"


UTestBlendSpace::UTestBlendSpace(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
}

void UTestBlendSpace::PostLoad() {}

void UTestBlendSpace::Serialize(FArchive& Ar) {}

void UTestBlendSpace::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) {}

void UTestBlendSpace::TickAssetPlayerInstance(const FAnimTickRecord& Instance, class UAnimInstance* InstanceOwner, FAnimAssetTickContext& Context) const {}

bool UTestBlendSpace::GetAllAnimationSequencesReferred(TArray<UAnimSequence*>& AnimationSequences) 
{
	return Super::GetAllAnimationSequencesReferred(AnimationSequences);
}

void UTestBlendSpace::ReplaceReferredAnimations(const TMap<UAnimSequence*, UAnimSequence*>& ReplacementMap) {}

bool UTestBlendSpace::ValidateSampleInput(FBlendSample & BlendSample, int32 OriginalIndex) const 
{
	return Super::ValidateSampleInput(BlendSample, OriginalIndex);
}

bool UTestBlendSpace::IsValidAdditive() const
{
	return Super::IsValidAdditive();
}

void UTestBlendSpace::SnapToBorder(FBlendSample& Sample) const {}

EBlendSpaceAxis UTestBlendSpace::GetAxisToScale() const 
{
	return Super::GetAxisToScale();
}

bool UTestBlendSpace::IsSameSamplePoint(const FVector& SamplePointA, const FVector& SamplePointB) const
{
	return Super::IsSameSamplePoint(SamplePointA, SamplePointB);
}

void UTestBlendSpace::GetRawSamplesFromBlendInput(const FVector &BlendInput, TArray<FGridBlendSample> & OutBlendSamples) const {}

The quick look I had made me think PostLoad had two overloads, but now I’m not so sure of it since well, the message below states there is a problem in the inheritance from UAnimationAsset.
Did you define all of the virtuals?

I’ve only defined all of the virtual functions that gave an error. Is that what you mean?

Hi! I’m trying to do the same.

Has anyone found the workaround?

I tried to override 1 function at a time, making sure each LNK2001 disappears.
I was like “Yes! finally!”, when I hit my “ctrl+shift+b” overriding the last LNK2001.

then LNK2019s…

Basically, I think the compiler is telling me Super::whatever are not available.
Experimenting and looking around for days…

The header.



UCLASS( config = Engine, hidecategories = Object, MinimalAPI, BlueprintType )
class UMYBlendSpace : public UBlendSpace {
    GENERATED_BODY()

    ///************************ AnimationAsset.h overwrites ************************/
    public:
    virtual void SetPreviewMesh( USkeletalMesh* PreviewMesh, bool bMarkAsDirty = true ) override;
    virtual USkeletalMesh* GetPreviewMesh( bool bFindIfNotSet = false ) override;
    virtual USkeletalMesh* GetPreviewMesh() const override;

    protected:
    virtual void RefreshParentAssetData() override;
    #if WITH_EDITOR
    virtual void RemapTracksToNewSkeleton( USkeleton* NewSkeleton, bool bConvertSpaces ) override;
    #endif // WITH_EDITOR

    private:

    ///************************ BlendSpaceBase.h overwrites ************************/
    //~ Begin UObject Interface
    virtual void PostLoad() override;
    virtual void Serialize( FArchive& Ar ) override;
    #if WITH_EDITOR
    virtual void PreEditChange( UProperty* PropertyAboutToChange ) override;
    virtual void PostEditChangeProperty( struct FPropertyChangedEvent& PropertyChangedEvent ) override;
    #endif // WITH_EDITOR
    //~ End UObject Interface

    //~ Begin UAnimationAsset Interface
    virtual void TickAssetPlayer( FAnimTickRecord& Instance, struct FAnimNotifyQueue& NotifyQueue, FAnimAssetTickContext& Context ) const override;

    virtual TArray<FName>* GetUniqueMarkerNames() override;
    #if WITH_EDITOR
    virtual bool GetAllAnimationSequencesReferred( TArray<UAnimationAsset*>& AnimationAssets, bool bRecursive = true ) override;
    virtual void ReplaceReferredAnimations( const TMap<UAnimationAsset*, UAnimationAsset*>& ReplacementMap ) override;
    virtual int32 GetMarkerUpdateCounter() const override;
    #endif
    virtual int32 GetPerBoneInterpolationIndex( int32 BoneIndex, const FBoneContainer& RequiredBones ) const override;

    ///************************ BlendSpace.h overwrites ************************/
    public:
    virtual bool IsValidAdditiveType( EAdditiveAnimationType AdditiveType ) const override;
    virtual bool IsValidAdditive() const override;
    //protected:
    //~ Begin UBlendSpaceBase Interface
    virtual EBlendSpaceAxis GetAxisToScale() const override;
    virtual bool IsSameSamplePoint( const FVector& SamplePointA, const FVector& SamplePointB ) const override;
    virtual void GetRawSamplesFromBlendInput( const FVector &BlendInput, TArray<FGridBlendSample, TInlineAllocator<4> > & OutBlendSamples ) const override;

    #if WITH_EDITOR
    virtual void SnapSamplesToClosestGridPoint() override;
    virtual void RemapSamplesToNewAxisRange() override;
    #endif // WITH_EDITOR

    //~ End UBlendSpaceBase Interface
};


cpp is just a bunch of functions calling their Supers.

e.g.



void UMYBlendSpace::SetPreviewMesh( USkeletalMesh* PreviewMesh, bool bMarkAsDirty/*=true*/ ) {
    Super::SetPreviewMesh( PreviewMesh, bMarkAsDirty ); // ← LNK2019s
    UAnimationAsset::SetPreviewMesh( PreviewMesh, bMarkAsDirty ); // ← LNK2019s
    UBlendSpace::SetPreviewMesh( PreviewMesh, bMarkAsDirty ); // ← LNK2019s
}


and the error



Severity    Code    Description    Project    File    Line    Suppression State
Error    LNK2019    unresolved external symbol "public: virtual void __cdecl UAnimationAsset::SetPreviewMesh(class USkeletalMesh *,bool)" (?SetPreviewMesh@UAnimationAsset@@UEAAXPEAVUSkeletalMesh@@_N@Z) referenced in function "public: virtual void __cdecl UMYBlendSpace::SetPreviewMesh(class USkeletalMesh *,bool)" (?SetPreviewMesh@UMYBlendSpace@@UEAAXPEAVUSkeletalMesh@@_N@Z)    ThirdPerson    F:\Projects\Intermediate\ProjectFiles\AnimNode_BlendSpace.cpp.obj    1


It has nothing to do with overrides directly. You can’t call base class methods if they weren’t exported. So basically, if the method declaration in the base isn’t prefixed with SOMETHING_API, and the class definition doesn’t have that prefix either, then you can’t call it from your own module.

No workaround, besides using a custom source-built engine. It implies that Epic devs didn’t envision extension/overriding of the given class/method outside of the engine module in which it’s located.