Download

Editing sequencer level sequence at runtime

Hi, is it possible to edit ULevelSequence at runtime? I’m able to add an event track to a level sequence and then add keyframe to it. The event gets fired in PIE and standalone mode but not in packaged build. Here’s a code snippet that I’m using:

//Struct with function parameters
USTRUCT(BlueprintType)
struct FInputParams
{
     GENERATED_BODY()
     
     UPROPERTY(EditAnywhere, BlueprintReadWrite)
     int32 InputParam;
};

UMovieSceneEventTrack* EventTrack = NewObject<UMovieSceneEventTrack>(this, UMovieSceneEventTrack::StaticClass()); 
UMovieSceneEventSection* EventSection = NewObject<UMovieSceneEventSection>(EventTrack, UMovieSceneEventSection::StaticClass());

 if (!EventSection)
 {
     UE_LOG(LogTemp, Error, TEXT("Event Section is not valid"));
     return;
 }

 EventTrack->AddSection(*EventSection);
 FEventPayload Payload;
 Payload.EventName = "CalledFromSequencer"; //Function must be in level blueprint
 FInputParams ParamsToPass;
 ParamsToPass.InputParam = 7; //Test value
 
 UScriptStruct* PayloadProperty = StaticStruct<FInputParams>();
 Payload.Parameters.Reassign(PayloadProperty);
 Payload.Parameters.OverwriteWith((uint8*)&ParamsToPass);

 FMovieSceneChannelProxy& Proxy = EventSection->GetChannelProxy();
 FMovieSceneEventSectionData* Channel = Proxy.GetChannel<FMovieSceneEventSectionData>(0);

 if (!Channel)
 {
     UE_LOG(LogTemp, Error, TEXT("Channel is not valid"));
     return;
 }

 TMovieSceneChannelData<FEventPayload> ChannelData = Channel->GetData();
 int32 KeyIndex = ChannelData.AddKey(10 * 1000 /*Adds this key to 10th frame */, Payload);
 UE_LOG(LogTemp, Warning, TEXT("Newly added key index: %d"), KeyIndex);

Any help will be appreciated!

have you found a solution yet?

i have the same problem. in PIE i can write a sequence and play it back correctly but in the packaged build it wont work.

i have investigated a little bit so far and all the bindings and property tracks are there when i go through all objects in the sequence but for some reason they are not applied to the objects.

bindings for existing objects are created at startup like this

Guid = SequenceAsset->MovieScene->AddPossessable(Object->GetName(), Object->GetClass());
UObject* Context = Object;
FGuid ParentGuid;
if (UActorComponent* Comp = Cast<UActorComponent>(Object))
{
	Context = Comp->GetOwner();
	ParentGuid = SequenceAsset->FindPossessableObjectId(*Context, nullptr);

	if (!ParentGuid.IsValid())
	{
		AddObjectToSequence(Context, SequenceAsset); //calls this again
		ParentGuid = SequenceAsset->FindPossessableObjectId(*Context, nullptr);
	}
}

SequenceAsset->BindPossessableObject(Guid, *Object, Context);

if (ParentGuid.IsValid())
{
	FMovieScenePossessable* Poss = SequenceAsset->MovieScene->FindPossessable(Guid);
	Poss->SetParent(ParentGuid);
}

and then adding tracks like so

UMovieSceneFloatTrack* FTrack = SequenceAsset->MovieScene->AddTrack<UMovieSceneFloatTrack>(Guid);
FTrack->SetPropertyNameAndPath(PropName, PropPath);

and then values to the tracks

UMovieSceneSection* Section = FloatTrack->FindOrAddSection(FFrameNumber(0), bAdded);
	TArrayView <FMovieSceneFloatChannel*> Channels = FloatSection->GetChannelProxy().GetChannels<FMovieSceneFloatChannel>();

FMovieSceneFloatChannel* Channel = Channels[0];
int32 Key = Channel->AddLinearKey(TrueFrame, Value);

note that i left out some casts and error handling to keep it short.

so it seems everything is set up correctly in the published build. what am i missing?

is there some step that is done by the editor to “apply” the changes?

also i found this, the documentation for the Volatile flag even says that this should be applied when the sequence changes at runtime. so i guess it is meant to work.
SequenceAsset->SetSequenceFlags(EMovieSceneSequenceFlags::Volatile | EMovieSceneSequenceFlags::BlockingEvaluation);