I did my door code the way I’d do it in Unity using the forward vector and a scalar for relative movement so it may not use UE4’s best practices.
I also found UE4’s equivalent of [System.Serialisable]
to expose some variables in the editor so I don’t have to recompile when I want to change something like the lerp speed.
Here’s my code:
Header file:
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "OpenDoor.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class BUILDINGESCAPE_API UOpenDoor : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UOpenDoor();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
public:
FVector GetOpenPosition(const float Scalar, const bool bInvert = false) const;
private:
UPROPERTY(EditAnywhere) AActor* DoorLeft;
UPROPERTY(EditAnywhere) AActor* DoorRight;
UPROPERTY(EditAnywhere) float ScalarOffset;
UPROPERTY(EditAnywhere) float LerpSpeed;
FVector DoorPos, ForwardVector;
float OffsetLastFrame;
};
C++ script:
#include "OpenDoor.h"
// Sets default values for this component's properties
UOpenDoor::UOpenDoor()
{
PrimaryComponentTick.bCanEverTick = true;
}
// Called when the game starts
void UOpenDoor::BeginPlay()
{
Super::BeginPlay();
DoorPos = GetOwner()->GetTransform().GetLocation();
ForwardVector = GetOwner()->GetActorForwardVector();
}
// Called every frame
void UOpenDoor::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
float OffsetLerped = FMath::FInterpTo(OffsetLastFrame, ScalarOffset, DeltaTime, LerpSpeed);
DoorLeft->SetActorLocation(GetOpenPosition(OffsetLerped, true));
DoorRight->SetActorLocation(GetOpenPosition(OffsetLerped));
OffsetLastFrame = OffsetLerped;
}
FVector UOpenDoor::GetOpenPosition(const float Scalar, const bool bInvert) const
{
FVector VectorOffset = ForwardVector * Scalar;
if (bInvert)
{
return DoorPos - VectorOffset;
}
return DoorPos + VectorOffset;
}
Edit:
Changed to FPS independent FInterpTo
Edit 2:
I coded it so that the entire door could be moved/rotated at runtime, but this wouldn’t work anyway due to lerping the doors. Moved setting the forward vector and door position to the start function.