The result I got to was more or less the same as what we were guided through after the pause. The door sounds once when opening and when closing as intended, however I was thinking it may sound more believable if the door closing sound went off towards the end of the closing animation.
I tried using an “if (CurrentYaw >= InitialYaw)” so that the sound would only play when the door is back to the initial position. But from what I could tell, lerp doesn’t go back to it’s initial value, it just gets very close, which makes the door look like it’s closed, but is still technically moving. (I might be wrong)
I thought about giving it a little buffer space “if (CurrentYaw >= InitialYaw ± 2.f)” but when i thought about how the door could be set anywhere from negative to positive 360 degrees and then the door opening took a fixed -90. I got a bit confused.
Anyways, this is what I got
OpenDoor.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Engine/TriggerVolume.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;
void OpenDoor(float DeltaTime);
void CloseDoor(float DeltaTime);
float TotalMassOfActors() const;
void FindAudioComponent();
void CheckPressurePlate() const;
private:
float InitialYaw;
float CurrentYaw;
bool OpenDoorSound = false;
bool CloseDoorSound = true;
UPROPERTY(EditAnywhere)
float DoorTriggerMass = 70.f;
UPROPERTY(EditAnywhere)
float OpenAngle = -90.f;
float DoorLastOpened = 0.f;
UPROPERTY(EditAnywhere)
float DoorCloseDelay = 2.f;
UPROPERTY(EditAnywhere)
float DoorOpenSpeed = 1.f;
UPROPERTY(EditAnywhere)
float DoorCloseSpeed = 1.f;
UPROPERTY(EditAnywhere)
ATriggerVolume* PressurePlate = nullptr;
UPROPERTY()
UAudioComponent* AudioComponent = nullptr;
};
OpenDoor.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "OpenDoor.h"
#include "Components/PrimitiveComponent.h"
#include "Components/AudioComponent.h"
#include "Engine/World.h"
#include "GameFramework/Actor.h"
#include "GameFramework/PlayerController.h"
#define OUT
// Sets default values for this component's properties
UOpenDoor::UOpenDoor()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UOpenDoor::BeginPlay()
{
Super::BeginPlay();
CheckPressurePlate();
FindAudioComponent();
InitialYaw = GetOwner()->GetActorRotation().Yaw;
CurrentYaw = InitialYaw;
OpenAngle += InitialYaw;
}
// Called every frame
void UOpenDoor::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if(TotalMassOfActors() >= DoorTriggerMass)
{
OpenDoor(DeltaTime);
DoorLastOpened = GetWorld()->GetTimeSeconds();
}
else
{
if (GetWorld()->GetTimeSeconds() > (DoorLastOpened + DoorCloseDelay))
{
CloseDoor(DeltaTime);
}
}
}
void UOpenDoor::OpenDoor(float DeltaTime)
{
CurrentYaw = FMath::Lerp(CurrentYaw, OpenAngle, DeltaTime * DoorOpenSpeed);
FRotator DoorRotation = GetOwner()->GetActorRotation();
DoorRotation.Yaw = CurrentYaw;
GetOwner()->SetActorRotation(DoorRotation);
if(!AudioComponent) {return;}
if (!OpenDoorSound)
{
AudioComponent->Play();
OpenDoorSound = true;
CloseDoorSound = false;
}
}
void UOpenDoor::CloseDoor(float DeltaTime)
{
CurrentYaw = FMath::Lerp(CurrentYaw, InitialYaw, DeltaTime * DoorCloseSpeed);
FRotator DoorRotation = GetOwner()->GetActorRotation();
DoorRotation.Yaw = CurrentYaw;
GetOwner()->SetActorRotation(DoorRotation);
if(!AudioComponent) {return;}
if (!CloseDoorSound)
{
AudioComponent->Play();
CloseDoorSound = true;
OpenDoorSound = false;
}
}
float UOpenDoor::TotalMassOfActors() const
{
float TotalMass = 0.f;
// Find overlapping actors
TArray<AActor*> OverlappingActors;
if (!PressurePlate) {return TotalMass;}
PressurePlate->GetOverlappingActors(OUT OverlappingActors);
// Add up their mass
for (AActor* Actor: OverlappingActors)
{
TotalMass += Actor->FindComponentByClass<UPrimitiveComponent>()->GetMass();
}
return TotalMass;
}
void UOpenDoor::FindAudioComponent()
{
AudioComponent = GetOwner()->FindComponentByClass<UAudioComponent>();
if (!AudioComponent)
{
UE_LOG(LogTemp, Error, TEXT("%s is missing audio component."), *GetOwner()->GetName());
}
}
void UOpenDoor::CheckPressurePlate() const
{
if (!PressurePlate)
{
UE_LOG(LogTemp, Error, TEXT("%s has OpenDoor component but no pressure plate set!"), *GetOwner()->GetName());
}
}