Hi,
I am trying to make a function (“PlayWithLoop”) that plays a Level Sequence from the start (Animation In) and let it loop between 2 marked frames and another function (“EndAndStop”) that quits the loop and just let it play out till the end (Animation Out).
So far I managed to make it but after a couple of loops, I have the feeling the delegates stops calling for the function it was assigned to without deleting the function from the delegate.
Here some code:
My Extension on MovieSceneSequencePlayer. *.h:
#include "CoreMinimal.h"
#include "MovieSceneSequencePlayer.h"
#include "MovieSceneSequencePlayerExtended.generated.h"
/**
*
*/
UCLASS()
class XLIVE_API UMovieSceneSequencePlayerExtended : public UMovieSceneSequencePlayer
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite)
UMovieSceneSequencePlayer* MovieSceneSequencePlayer = nullptr;
FMovieSceneSequencePlaybackParams PlaybackAParams;
FMovieSceneSequencePlaybackParams PlaybackBParams;
FMovieSceneSequencePlayToParams PlayToParams;
int32 NumberOfLoops, Looped = 0;
bool bOnPausedLooping = false;
UFUNCTION(BlueprintCallable, Category = "Sequencer|Extended")
void PlayWithLoop(FMovieSceneSequencePlaybackParams PointA, FMovieSceneSequencePlaybackParams PointB, int32 NumLoops = -1);
UFUNCTION(BlueprintCallable, Category = "Sequencer|Extended")
void EndAndStop();
UFUNCTION(BlueprintCallable, Category = "Sequencer|Extended")
bool CheckDelegate();
UFUNCTION()
void LoopWhenPaused();
UFUNCTION()
void PlayToEnd();
FScriptDelegate MakeScriptDelegate(FName FunctionName);
}
And cpp file:
#include "MovieSceneSequencePlayerExtended.h"
void UMovieSceneSequencePlayerExtended::PlayWithLoop(FMovieSceneSequencePlaybackParams PointA, FMovieSceneSequencePlaybackParams PointB, int32 NumLoops)
{
PlaybackAParams = PointA;
PlaybackBParams = PointB;
NumberOfLoops = NumLoops;
if (MovieSceneSequencePlayer->IsPlaying())
{
MovieSceneSequencePlayer->Stop();
}
//Plays sequence from beginning to Point B
MovieSceneSequencePlayer->PlayTo(PlaybackBParams, PlayToParams);
Looped = 0;
bOnPausedLooping = true;
//When sequence hits point B it pauses and the delegate should be called on function LoopWhenPaused.
MovieSceneSequencePlayer->OnPause.Add(MakeScriptDelegate(TEXT("LoopWhenPaused")));
}
void UMovieSceneSequencePlayerExtended::EndAndStop()
{
MovieSceneSequencePlayer->OnPause.Remove(MakeScriptDelegate(TEXT("LoopWhenPaused")));
MovieSceneSequencePlayer->OnPause.Add(MakeScriptDelegate(TEXT("PlayToEnd")));
FQualifiedFrameTime EndTime = MovieSceneSequencePlayer->GetEndTime();
FMovieSceneSequencePlaybackParams EndFrame(EndTime.Time.GetFrame(), EUpdatePositionMethod::Play);
MovieSceneSequencePlayer->PlayTo(EndFrame, PlayToParams);
}
bool UMovieSceneSequencePlayerExtended::CheckDelegate()
{
return MovieSceneSequencePlayer->OnPause.Contains(MakeScriptDelegate(TEXT("LoopWhenPaused")));
}
void UMovieSceneSequencePlayerExtended::LoopWhenPaused()
{
if (bOnPausedLooping)
{
if (NumberOfLoops < 0 || NumberOfLoops > Looped)
{
FMovieSceneSequencePlaybackParams JumpToA = PlaybackAParams;
JumpToA.UpdateMethod = EUpdatePositionMethod::Jump;
MovieSceneSequencePlayer->SetPlaybackPosition(JumpToA);
MovieSceneSequencePlayer->PlayTo(PlaybackBParams, PlayToParams);
UE_LOG(LogTemp, Warning, TEXT("Play Loop, %i"), Looped);
++Looped;
}
else
{
FQualifiedFrameTime EndTime = MovieSceneSequencePlayer->GetEndTime();
FMovieSceneSequencePlaybackParams EndFrame(EndTime.Time.GetFrame(), EUpdatePositionMethod::Play);
MovieSceneSequencePlayer->PlayTo(EndFrame, PlayToParams);
bOnPausedLooping = false;
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("REMOVED!"));
MovieSceneSequencePlayer->OnPause.Remove(MakeScriptDelegate(TEXT("LoopWhenPaused")));
}
}
void UMovieSceneSequencePlayerExtended::PlayToEnd()
{
MovieSceneSequencePlayer->Stop();
MovieSceneSequencePlayer->OnPause.Remove(MakeScriptDelegate(TEXT("PlayToEnd")));
}
FScriptDelegate UMovieSceneSequencePlayerExtended::MakeScriptDelegate(FName FunctionName)
{
FScriptDelegate ScriptDelegate;
ScriptDelegate.BindUFunction(this, FunctionName);
return ScriptDelegate;
}
I also tried using the Delegate.AddDynamic() Macro but that gave the same result.
So for the implementation, I construct an Extended Object in a different BP and set the Sequence Player to whatever sequence needs to be played. Then to start i Call “Play with Loop” and to end “End and Stop”.
When I call the Play with Loop function the sequence starts playing and begins looping, but after a while the sequence just stops.
I’ve ran it a couple of times to see if something is happening when it stops but nothing is going on. The number of times it does loop also is super random but looks like its always around 20-30ish when the function isn’t called anymore.
Now for the question
Anybody know what is going on?
Is there something wrong with the code?
Is there maybe a better way of doing this?