Subclassing AnimMontage

I want to specify anim notifies on all of my ability animation montages at once.

Therefore, I am trying to subclass UAnimMontage.

So, I created a new class in the editor that inherits from it and compiled.

I am getting the following linker errors

2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual float __cdecl UAnimSequenceBase::GetPlayLength(void)" (?GetPlayLength@UAnimSequenceBase@@UEAAMXZ)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual float __cdecl UAnimSequenceBase::GetPlayLength(void)" (?GetPlayLength@UAnimSequenceBase@@UEAAMXZ)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl UAnimSequenceBase::GetNumberOfFrames(void)const " (?GetNumberOfFrames@UAnimSequenceBase@@UEBAHXZ)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl UAnimSequenceBase::GetNumberOfFrames(void)const " (?GetNumberOfFrames@UAnimSequenceBase@@UEBAHXZ)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl UAnimSequenceBase::GetFrameAtTime(float)const " (?GetFrameAtTime@UAnimSequenceBase@@UEBAHM@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl UAnimSequenceBase::GetFrameAtTime(float)const " (?GetFrameAtTime@UAnimSequenceBase@@UEBAHM@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual float __cdecl UAnimSequenceBase::GetTimeAtFrame(int)const " (?GetTimeAtFrame@UAnimSequenceBase@@UEBAMH@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual float __cdecl UAnimSequenceBase::GetTimeAtFrame(int)const " (?GetTimeAtFrame@UAnimSequenceBase@@UEBAMH@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::GetAssetRegistryTags(class TArray<struct UObject::FAssetRegistryTag,class FDefaultAllocator> &)const " (?GetAssetRegistryTags@UAnimSequenceBase@@UEBAXAEAV?$TArray@UFAssetRegistryTag@UObject@@VFDefaultAllocator@@@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::GetAssetRegistryTags(class TArray<struct UObject::FAssetRegistryTag,class FDefaultAllocator> &)const " (?GetAssetRegistryTags@UAnimSequenceBase@@UEBAXAEAV?$TArray@UFAssetRegistryTag@UObject@@VFDefaultAllocator@@@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::OnAssetPlayerTickedInternal(struct FAnimAssetTickContext &,float,float,struct FAnimTickRecord const &,class UAnimInstance *)const " (?OnAssetPlayerTickedInternal@UAnimSequenceBase@@UEBAXAEAUFAnimAssetTickContext@@MMAEBUFAnimTickRecord@@PEAVUAnimInstance@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::OnAssetPlayerTickedInternal(struct FAnimAssetTickContext &,float,float,struct FAnimTickRecord const &,class UAnimInstance *)const " (?OnAssetPlayerTickedInternal@UAnimSequenceBase@@UEBAXAEAUFAnimAssetTickContext@@MMAEBUFAnimTickRecord@@PEAVUAnimInstance@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::HandleAssetPlayerTickedInternal(struct FAnimAssetTickContext &,float,float,struct FAnimTickRecord const &,struct FAnimNotifyQueue &)const " (?HandleAssetPlayerTickedInternal@UAnimSequenceBase@@UEBAXAEAUFAnimAssetTickContext@@MMAEBUFAnimTickRecord@@AEAUFAnimNotifyQueue@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::HandleAssetPlayerTickedInternal(struct FAnimAssetTickContext &,float,float,struct FAnimTickRecord const &,struct FAnimNotifyQueue &)const " (?HandleAssetPlayerTickedInternal@UAnimSequenceBase@@UEBAXAEAUFAnimAssetTickContext@@MMAEBUFAnimTickRecord@@AEAUFAnimNotifyQueue@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::Serialize(class FArchive &)" (?Serialize@UAnimSequenceBase@@UEAAXAEAVFArchive@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimSequenceBase::Serialize(class FArchive &)" (?Serialize@UAnimSequenceBase@@UEAAXAEAVFArchive@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::PostLoad(void)" (?PostLoad@UAnimMontage@@UEAAXXZ)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::PostLoad(void)" (?PostLoad@UAnimMontage@@UEAAXXZ)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::PostEditChangeProperty(struct FPropertyChangedEvent &)" (?PostEditChangeProperty@UAnimMontage@@UEAAXAEAUFPropertyChangedEvent@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::PostEditChangeProperty(struct FPropertyChangedEvent &)" (?PostEditChangeProperty@UAnimMontage@@UEAAXAEAUFPropertyChangedEvent@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UAnimMontage::IsValidAdditive(void)const " (?IsValidAdditive@UAnimMontage@@UEBA_NXZ)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UAnimMontage::IsValidAdditive(void)const " (?IsValidAdditive@UAnimMontage@@UEBA_NXZ)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual enum EAnimEventTriggerOffsets::Type __cdecl UAnimMontage::CalculateOffsetForNotify(float)const " (?CalculateOffsetForNotify@UAnimMontage@@UEBA?AW4Type@EAnimEventTriggerOffsets@@M@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual enum EAnimEventTriggerOffsets::Type __cdecl UAnimMontage::CalculateOffsetForNotify(float)const " (?CalculateOffsetForNotify@UAnimMontage@@UEBA?AW4Type@EAnimEventTriggerOffsets@@M@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::GetMarkerIndicesForTime(float,bool,class TArray<class FName,class FDefaultAllocator> const &,struct FMarkerPair &,struct FMarkerPair &)const " (?GetMarkerIndicesForTime@UAnimMontage@@UEBAXM_NAEBV?$TArray@VFName@@VFDefaultAllocator@@@@AEAUFMarkerPair@@2@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::GetMarkerIndicesForTime(float,bool,class TArray<class FName,class FDefaultAllocator> const &,struct FMarkerPair &,struct FMarkerPair &)const " (?GetMarkerIndicesForTime@UAnimMontage@@UEBAXM_NAEBV?$TArray@VFName@@VFDefaultAllocator@@@@AEAUFMarkerPair@@2@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual struct FMarkerSyncAnimPosition __cdecl UAnimMontage::GetMarkerSyncPositionfromMarkerIndicies(int,int,float)const " (?GetMarkerSyncPositionfromMarkerIndicies@UAnimMontage@@UEBA?AUFMarkerSyncAnimPosition@@HHM@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual struct FMarkerSyncAnimPosition __cdecl UAnimMontage::GetMarkerSyncPositionfromMarkerIndicies(int,int,float)const " (?GetMarkerSyncPositionfromMarkerIndicies@UAnimMontage@@UEBA?AUFMarkerSyncAnimPosition@@HHM@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::TickAssetPlayer(struct FAnimTickRecord &,struct FAnimNotifyQueue &,struct FAnimAssetTickContext &)const " (?TickAssetPlayer@UAnimMontage@@UEBAXAEAUFAnimTickRecord@@AEAUFAnimNotifyQueue@@AEAUFAnimAssetTickContext@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::TickAssetPlayer(struct FAnimTickRecord &,struct FAnimNotifyQueue &,struct FAnimAssetTickContext &)const " (?TickAssetPlayer@UAnimMontage@@UEBAXAEAUFAnimTickRecord@@AEAUFAnimNotifyQueue@@AEAUFAnimAssetTickContext@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::RefreshCacheData(void)" (?RefreshCacheData@UAnimMontage@@UEAAXXZ)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::RefreshCacheData(void)" (?RefreshCacheData@UAnimMontage@@UEAAXXZ)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UAnimMontage::GetAllAnimationSequencesReferred(class TArray<class UAnimSequence *,class FDefaultAllocator> &)" (?GetAllAnimationSequencesReferred@UAnimMontage@@UEAA_NAEAV?$TArray@PEAVUAnimSequence@@VFDefaultAllocator@@@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UAnimMontage::GetAllAnimationSequencesReferred(class TArray<class UAnimSequence *,class FDefaultAllocator> &)" (?GetAllAnimationSequencesReferred@UAnimMontage@@UEAA_NAEAV?$TArray@PEAVUAnimSequence@@VFDefaultAllocator@@@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::ReplaceReferredAnimations(class TMap<class UAnimSequence *,class UAnimSequence *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class UAnimSequence *,class UAnimSequence *,0> > const &)" (?ReplaceReferredAnimations@UAnimMontage@@UEAAXAEBV?$TMap@PEAVUAnimSequence@@PEAV1@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@PEAVUAnimSequence@@PEAV1@$0A@@@@@@Z)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UAnimMontage::ReplaceReferredAnimations(class TMap<class UAnimSequence *,class UAnimSequence *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class UAnimSequence *,class UAnimSequence *,0> > const &)" (?ReplaceReferredAnimations@UAnimMontage@@UEAAXAEBV?$TMap@PEAVUAnimSequence@@PEAV1@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@PEAVUAnimSequence@@PEAV1@$0A@@@@@@Z)
2>FPSAbilityAnimMontage.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UAnimMontage::HasRootMotion(void)const " (?HasRootMotion@UAnimMontage@@UEBA_NXZ)
2>FPSGame.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl UAnimMontage::HasRootMotion(void)const " (?HasRootMotion@UAnimMontage@@UEBA_NXZ)
2>D:\Omniwar\FPSGame\Binaries\Win64\UE4Editor-FPSGame-8322-Win64-DebugGame.dll : fatal error LNK1120: 19 unresolved externals

I haven’t been able to find anyone else extending this class.

Does anyone have an example?

It looks like UAnimMontage and UAnimSequenceBase are both in the Engine module. So I don’t think I’m missing a module?

I thought it might want me to override the virtuals that it is complaining about. But I looked at UAnimMontage and it doesn’t override GetPlayLength(). So I don’t think that is it.

#pragma once

#include "Animation/AnimMontage.h"
#include "FPSAbilityAnimMontage.generated.h"

UCLASS()
class FPSGAME_API UFPSAbilityAnimMontage : public UAnimMontage
{
	GENERATED_BODY()	
};

Here is my Build.cs just in case.

using UnrealBuildTool;
​
public class FPSGame : ModuleRules
{
    public FPSGame(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(
            new string[] {
                "Core",
                "CoreUObject",
                "Engine",
                "InputCore",
                "OnlineSubsystem",
                "OnlineSubsystemUtils",
                "UMG",
                "Slate",
                "SlateCore"
            }
        );
​
        PrivateDependencyModuleNames.AddRange(new string[] {  });
​
        // Uncomment if you are using Slate UI
        // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
​
        DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
​
        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");
        if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64))
        {
            if (UEBuildConfiguration.bCompileSteamOSS == true)
            {
                DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
            }
        }
    }
}

Any ideas?

I’ve been facing the same issues trying to extend UAnimSequence. I think this is due to UAnimSequenceBase having the MinimalAPI flag and (or?) not exposing certain functions with the ENGINE_API macro.

I’ve been fixing this by adding that macro to the declaration of those functions. It’s annoying to have to change the source of the engine, but I don’t know if there is any better way. Also not sure why some of the functions already have that macro and others don’t.

Yes, it is because AnimMontage isn’t exported from the engine module (no ENGINE_API macro). You are correct.