Skip to main content

Changing a Component in a Parent Object

If we derive a C++ class from an existing Unreal class, and that existing class contains components, we can extend (subclass) those components without changing the source code of the base class.

An Example​

The ACharacter class contains a number of different components, specifically these:

offset

Say for example we want to replace the UCharacterMovementComponent with an extended version - the UMyNewCharacterMovementComponent which we have created and which is derived from UCharacterMovementComponent.

We want to change from this:

to this:

The UMyNewCharacterMovementComponent is shown below; for the purposes of this article we have added a constructor which changes the GravityScale member of UCharacterMovementComponent to 0.5 from its default value of 1.0.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "MyNewCharacterMovementComponent.generated.h"

UCLASS()
class TEST_API UMyNewCharacterMovementComponent : public UCharacterMovementComponent
{
GENERATED_BODY()
public:
UMyNewCharacterMovementComponent();
};

The implementation of the constructor is:

#include "MyNewCharacterMovementComponent.h"
UMyNewCharacterMovementComponent::UMyNewCharacterMovementComponent()
{
GravityScale = 0.5f;
}

If we create a C++ class called AMyCharacter derived from ACharacter the code looks like this:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"

UCLASS()
class TEST_API AMyCharacter : public ACharacter
{
GENERATED_BODY()

public:
// Sets default values for this character's properties
AMyCharacter();

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;

// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};

What we want to do is replace the UCharacterMovementComponent created in the ACharacter base class with our new UMyNewCharacterMovementComponent. To do this we add a FObjectInitializer& parameter to the class constructor in MyCharacter.h:

AMyCharacter(const FObjectInitializer& OI);

and in MyCharacter.cpp we change the constructor to this:

AMyCharacter::AMyCharacter(const FObjectInitializer& OI)
: Super( OI.SetDefaultSubobjectClass<UMyNewCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
{
PrimaryActorTick.bCanEverTick = true;
}

The call to Super(OI.SetDefaultSubobjectClass) is what changes the component associated with the ACharacter::CharacterMovementComponentName name from the UCharacterMovementComponent to our UMyNewCharacterMovementComponent so that when the AMyCharacter object is created it now has a UMyNewCharacterMovementComponent component.

If you drop a MyCharacter actor into the world map an look at its components we can see that:

  • the Character Movement component is now a UMyNewCharacterMovementComponent object
  • the gravity scale property has a value of 0.5, showing our component constructor was executed:

Note that you can only change a component to one which is derived from the original component. If you try to change it to something unrelated the engine will log a message like this:

Error: Class /Script/Test.Unrelated is not a legal override for component CharMoveComp because it does not derive 
from Class /Script/Engine.CharacterMovementComponent. Using Class /Script/Engine.CharacterMovementComponent to construct
component.

Feedback​

Please leave any feedback about this article here