I’m not sure if this is the best implementation, but it seems to work. I added a USoundBase* Sound in mover.h so I can select the sound specifically for each mover (like sliding stone or creaking doors), and some variables to start the play and not restart it until the movement has stopped.
I’m interested to hear if there is a better or built in method?
void UMover::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
FRotator CurrentRotation = GetOwner()->GetActorRotation();
FRotator TargetRotation = OriginalRotation;
FVector CurrentLocation = GetOwner()->GetActorLocation();
FVector TargetLocation = OriginalLocation;
if (ShouldMove == true)
{
TargetRotation = RotateOffset + OriginalRotation;
TargetLocation = MoveOffset + OriginalLocation;
}
float Speed = MoveOffset.Length() / MoveTime;
float RotSpeed = 45; // degrees per second. I can't convert rotaion into degrees (per second) so I'll just set a speed and don't worry about frame rate independence.
// check if the rotaitons are almost equal or the locations are almost equal (so it works for a slidiong wall or rotating door
if ((!CurrentRotation.Equals(OriginalRotation, 5) && !CurrentRotation.Equals(RotateOffset + OriginalRotation, 5))
|| (!CurrentLocation.Equals(OriginalLocation, 5) && !CurrentLocation.Equals(MoveOffset + OriginalLocation, 5)))
{
PlaySound(true);
}
else PlayingSound = false;
FRotator NewRotation = FMath::RInterpConstantTo(CurrentRotation, TargetRotation, DeltaTime, RotSpeed);
FVector NewLocation = FMath::VInterpConstantTo(CurrentLocation, TargetLocation, DeltaTime, Speed);
GetOwner()->SetActorRotation(NewRotation);
GetOwner()->SetActorLocation(NewLocation);
}
void UMover::PlaySound(bool PlayNow)
{
if (Sound && PlayNow == true && !PlayingSound )
{
UGameplayStatics::PlaySoundAtLocation(this, Sound, GetOwner()->GetActorLocation());
PlayingSound = true;
}
}
Thanks,
Matthew