Is there a way to get an actor's initial transform in a sequence?

Supposing that the actor has transform track on it.
I need the 1st frame key values.

I need the transform before the sequence starts playing. The actor is bound to the sequence in runtime through “actor binding”. Before the sequence starts, the actor would have to walk to its initial position in the sequence, so that there would be a smooth transition between gameplay and cinematics. The initial transform is needed so the actor would know where to move to.

I’ve been looking through source code for the whole afternoon but couldn’t figure it out.

Thanks in advance!

The sequence:

The “Transform Origin Actor” property on the level sequence actor

Just make your actor save its initial transform to a variable on begin play, then get that value whenever you want the initial value.

Thanks for the quick reply Sveitar.
I need the transform before the sequence starts playing.
The actor is bound to the sequence in runtime through “actor binding”. Before the sequence starts, the actor would have to walk to its initial position in the sequence, so that there would be a smooth transition between gameplay and cinematics. The initial transform is needed so the actor would know where to move to.

I just tried your idea in fact. I called “ScrubTo”, scrubbing the sequence to the 1st frame, then getting the actor reference through “GetSequenceBinding”. I did get the initial transform without playing the sequence. The problem was, the actor had to be bound to the sequence before scrubbing. I can’t do the binding until actor is moved to place. And I need the transform in order to move the actor…

Sorry I should have explained a bit more. The transform on the participating actor is a “relative transform”, relative to the level sequence actor containing it. Usually such a transform is in world space but in my level sequence actor “Transform Origin Actor” has been set to the sequence actor itself. So all participating actors’ transforms are now relative to the level sequence actor. The reason for the setup: both level sequence actor and all its participating actors would be spawned in runtime (could be anywhere in the level). The participating actors would be spawned somewhere in the level. To play the sequence, a level sequence actor would be spawned at another random location. Then the participating actor would walk to that location. Once it has reach the same spot where the sequence actor is, it would be bound to the sequence then the sequence would start playing. By knowing its initial transform in the sequence, the process would look seamless (otherwise the participating actor might SNAP to its location in the sequence when the sequence starts).
Of course there might be another way to implement the feature and I am open to ideas.

I do not understand why you want to move the actor to the first keyframe transform when you are explicitly defining that transform in the sequence. If so, you can also explicitly tell the actor to move to that location. Sorry if I misunderstood you :S

auto* sequence = GetLevelSequenceInternal();
check(sequence);

    auto* movieScene = sequence->MovieScene;
    check(movieScene);

    static const FName s_transformTrackName(TEXT("Transform"));

    // Every object should have only one transform track
    const UMovieScene3DTransformTrack* transformTrack = movieScene->FindTrack<UMovieScene3DTransformTrack>(bindingId.GetGuid(), s_transformTrackName);
    check(transformTrack);

    const TArray<UMovieSceneSection*>& trackSections = transformTrack->GetAllSections();
    check(trackSections.Num() > 0);

    // Take the 1st section since we are getting initial transform
    const UMovieSceneSection* section0 = trackSections[0];
    const FMovieSceneChannelProxy& channelProxy = section0->GetChannelProxy();
    auto channelArray = channelProxy.GetChannels<FMovieSceneFloatChannel>();

    // Assuming order: Translation X 3 -> Rotation X 3 -> Scale X 3
    const int32 translationStartIndex = 0;
    const int32 rotationStartIndex = 3;
    const int32 scaleStartIndex = 6;

    FVector initialTranslation = FVector::ZeroVector;
    FVector initialRotationVec = FVector::ZeroVector;
    FVector initialScale = FVector::OneVector;

    int32 numOfTransformChannels = channelArray.Num() - 1; // Exclude weight channel

    for (int32 channelIndex = 0; channelIndex < numOfTransformChannels; channelIndex++)
    {
        const FMovieSceneFloatChannel* channel = channelArray[channelIndex];

        float channelValue = 0.0f;
        bool result = channel->Evaluate(FFrameTime(0), channelValue);
        check(result);

        if (channelIndex < translationStartIndex + 3)
        { // Translation channels
            initialTranslation[channelIndex - translationStartIndex] = channelValue;
        }
        else if (channelIndex < rotationStartIndex + 3)
        { // Rotation channels
            initialRotationVec[channelIndex - rotationStartIndex] = channelValue;
        }
        else if (channelIndex < scaleStartIndex + 3)
        { // Scale channels
            initialScale[channelIndex - scaleStartIndex] = channelValue;
        }
    }

    FRotator initialRotation(initialRotationVec[1], initialRotationVec[2], initialRotationVec[0]);

    return FTransform(initialRotation, initialTranslation); // ignore scale (for now)
1 Like

is there a way to do thay in blueprint?

Dropping by, as this was useful for me, to say that using this requires adding the “MovieScene” and “MovieSceneTracks” modules to your Build.cs dependencies!!

Not that I’m aware of. Probably not, the tracks and sections aren’t reachable in BP, and even lots of the structures are not made to be blueprint type, so I highly doubt it for now.