We are currently procedurally generating portions of our Sequences at edit time: Tracks, bindables, possessables, and spawnables.
We’re doing this to build a skeletal version of our Sequences for our designers and artists to fill in the finer details. However, spawnables have been heavily deprecated internally, and creating a spawnable just creates a possessable now.
We need to set the transform on a possessable from C++. The best way I could find is something like this:
if (UMovieSceneSequence* MovieSceneSequence = MovieScene.GetTypedOuter<UMovieSceneSequence>()) { if (FMovieSceneBindingReferences* BindingReferences = MovieSceneSequence->GetBindingReferences()) { if (UMovieSceneCustomBinding* CustomBinding = BindingReferences->GetCustomBinding(BindingId, BindingIndex)) { if (UMovieSceneSpawnableBindingBase* SpawnableBinding = CustomBinding->AsSpawnable(SharedPlaybackState)) {But all of the important details are Protected (SpawnTransform, specifically).
Is there an intended method to accomplish this without using the UI? I have tried many different solutions, and they all lead back to manually setting them through the UI (specifically, the ISequencer and FSequencer functions).
Possessables and Spawnables handle these types of things differently.
For Spawnables, they have a GetObjectTemplate() which returns the object and its default values. You can reset and store that ObjectTemplate to have a different spawn position value.
Possessables don’t have an ObjectTemplate, and so there data needs to be stored on the Transform track, either as a key or as a default value.
This is rough, but something more akin to:
// Using your binding, get the tracks for it. TArray<FMovieSceneBindingProxy> Bindings = UMovieSceneSequenceExtensions::GetBindings(Sequence); for (FMovieSceneBindingProxy Binding : Bindings) { Binding.BindingID = MyID; TArray<UMovieSceneTrack*> TransformTracks = UMovieSceneBindingExtensions::FindTracksByType(Binding, UMovieScene3DTransformTrack::StaticClass()); //Get transform tracks specifically. for (UMovieSceneTrack* Track : TransformTracks) { Track->Modify(); TArray<UMovieSceneSection*> Sections = Track->GetAllSections(); //Get the sections. More that likely you'll only need one, but you'll want to think about that. for (UMovieSectionSection* Section : Sections) { if (UMovieScene3DTransformSection* TransformSection = Cast<UMovieScene3DTransformSection>(Section)) { // We need to go through the scripting channel interface because the channels are private and protected by more generic code. TArray<UMovieSceneScriptingChannel*> Channels = UMovieSceneSectionExtensions::GetAllChannels(Section); //You could also use UMovieSceneSectionExtensions::GetChannel for (UMovieSceneScriptingChannel* Channel : Channels) { if (Channel->ChannelName.IsEqual(FName("Translation"), ENameCase::CaseSensitive)) { FMovieSceneDoubleChannel* DoubleChannel = Cast<FMovieSceneDoubleChannel>(Channel); DoubleChannel[0]->SetDefault(0.0f); DoubleChannel[0]->SetDefault(0.0f); DoubleChannel[0]->SetDefault(100.0f); } } } } } }Hopefully this points you in the right direction.