Why is K2_OnMovementModeChanged not visible for override?

I want to override the K2_OnMovementModeChanged method from ACharacter. Maybe this is a syntax thing, but…

.h file:



// Class declaration:
class CHARACTERMOVEMENT_API AMyCharacter : public ACharacter
{
    virtual void K2_OnMovementModeChanged(EMovementMode PrevMovementMode, EMovementMode NewMovementMode, uint8 PrevCustomMode, uint8 NewCustomMode) override;
}


.cpp file:



void AMyCharacter::K2_OnMovementModeChanged(EMovementMode PrevMovementMode, EMovementMode NewMovementMode, uint8 PrevCustomMode, uint8 NewCustomMode)
{
    Super::K2_OnMovementModeChanged(PrevMovementMode, NewMovementMode, PrevCustomMode, NewCustomMode);
    UE_LOG(LogTemp, Log, TEXT("Movement Mode Changed"));
}


This returns a compilation error:



error C3668: 'AMyCharacter::K2_OnMovementModeChanged': method with override specifier 'override' did not override any base class methods


But this function does exist:

And you can also override this function in blueprints. So why can’t I override the function?

K2_OnMovementModeChanged isn’t a virtual function in the ACharacter class, and you can’t override a non-virtual function.

Instead of K2_OnMovementModeChanged you could use OnMovementModeChanged.
You can see in docs that K2_OnMovementModeChanged is not virtual but OnMovementModeChanged is, so you can override it:

I need a confirmation about this but K2_* is exposed C++ functions for Blueprints.

I’m confused by this fact because this:

OnMovementModeChanged.png

looks like the K2_OnMovementModeChanged definition, even though the non-K2 one (plain OnMovementModeChanged) is the virtual function. On top of that, isn’t the error message usually “trying to override non-virtual function” not “function doesn’t exist”? Is there some trick going on behind the scenes here?

What happens is:
1 - OnMovementModeChanged is called from C++.
2 - WIthin OnMovementModeChanged, **K2_OnMovementModeChanged **is called, so you can use it in Blueprint.

OnMovementModeChanged is NOT “visible” to Blueprint :


virtual void OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode = 0);

K2_OnMovementModeChanged IS “visible” as BlueprintImplementableEvent:


UFUNCTION(**BlueprintImplementableEvent**, ...)
void K2_OnMovementModeChanged(EMovementMode PrevMovementMode, EMovementMode NewMovementMode, uint8 PrevCustomMode, uint8 NewCustomMode);

OnMovementModeChanged code:


void ACharacter::OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PrevCustomMode)
{
    ...

    K2_OnMovementModeChanged(PrevMovementMode, CharacterMovement->MovementMode, PrevCustomMode, CharacterMovement->CustomMovementMode);
    ...
}

Error message:


error C3668: 'AMyCharacter::K2_OnMovementModeChanged': method with override specifier 'override' did not override any base class methods

I see.

In this case, is there any way to access NewMovementMode and NewCustomMode (kind of the point of this whole excersize) within cpp?

After a little fiddling around, here is a solution:

.h file:



virtual void OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PrevCustomMode) override;


.cpp file:



// Prints previous and current EMovementMode values to LogTemp on movement mode change
void AMyCharacter::OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PrevCustomMode)
{
    Super::OnMovementModeChanged(PrevMovementMode, PrevCustomMode);
    const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EMovementMode"), true);
    UE_LOG(LogTemp, Log, TEXT("Previous movement mode is %s"), *EnumPtr->GetNameStringByValue((int64)PrevMovementMode));

    const UEnum* EnumPtrZwa = FindObject<UEnum>(ANY_PACKAGE, TEXT("EMovementMode"), true);
    UE_LOG(LogTemp, Log, TEXT("Current movement mode is %s"), *EnumPtrZwa->GetNameStringByValue((int64)GetCharacterMovement()->MovementMode.GetValue()));   
}


In other words, you have to get the current movement mode by:


GetCharacterMovement()->MovementMode.GetValue()