Hello there!
I just want to show my solution using only one bolean and playing the sound only when the door “hits” the door frame (and locks or unlocks).
The boolean is defined in the header file as:
private:
// Indicates if the lock door sound for closing has already been played
bool bHasBeenClosed = true;
Then, the implementation goes like this:
// Called every frame
void UOpenDoor::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if(TotalMassOfActors() >= PressurePlateMassThresshold){
OpenDoor(DeltaTime);
DoorLastOpened = GetWorld()->GetTimeSeconds();
} else{
if((GetWorld()->GetTimeSeconds() - DoorLastOpened) > DoorCloseDelay){
CloseDoor(DeltaTime);
}
}
}
void UOpenDoor::OpenDoor(float DeltaTime){
//Check if door is closed to play lock sound
if(FMath::IsNearlyEqual(CurrentYaw, InitialYaw, 0.2f)){
if(AudioComponent && !AudioComponent->IsPlaying()){
AudioComponent->Play();
bHasBeenClosed = false; //Resets the flag to enable the sound when the door closes again
}
}
// Round to TargetYaw when it is very near to that value to avoid infinite aproximation
if(CurrentYaw != TargetYaw){
if(FMath::IsNearlyEqual(CurrentYaw, TargetYaw, 0.1f)){
CurrentYaw = TargetYaw;
} else{
CurrentYaw = FMath::Lerp(CurrentYaw, TargetYaw, DeltaTime * .5f);
}
FRotator DoorRotation = GetOwner()->GetActorRotation();
DoorRotation.Yaw = CurrentYaw;
GetOwner()->SetActorRotation(DoorRotation);
}
}
void UOpenDoor::CloseDoor(float DeltaTime){
// Check if door are closing to play lock sound
if(FMath::IsNearlyEqual(CurrentYaw, InitialYaw, 0.2f)){
// If the door has already played the lock sound, we dont repeat again and again, thats the reason for bHasBeenClosed
if((AudioComponent) && (!AudioComponent->IsPlaying()) && (!bHasBeenClosed)){
AudioComponent->Play();
bHasBeenClosed = true;
}
}
// Round to InitialYaw when it is very near to that value to avoid infinite aproximation
if(CurrentYaw != InitialYaw){
if(FMath::IsNearlyEqual(CurrentYaw, InitialYaw, 0.1f)){
CurrentYaw = InitialYaw;
} else{
CurrentYaw = FMath::Lerp(CurrentYaw, InitialYaw, DeltaTime * 2.f);
}
FRotator DoorRotation = GetOwner()->GetActorRotation();
DoorRotation.Yaw = CurrentYaw;
GetOwner()->SetActorRotation(DoorRotation);
}
}
I hope this can be useful for someone.