How to use the events of a base director class in the level sequence editor?

Hello,

in the level sequence editor I can create event tracks. The events fired by these tracks are evaluated in the level sequence director class of the level sequence. There may be much level sequences which are using exactly the same events, but with other data (i.e. the events are fired at different times/they are at different positions in the event track). So this is the classic case where a base class of the director blueprint is needed where the events are defined.
I can create a blueprint child of the level sequence director and then set the base class for the director of a specific level sequence as it. Then I can access the base events in the event graph. BUT they are not shown in the level sequence editor! When I right-click the keyframe, select properties and event, there are only the events I created in the child director class…
How to get this working?

Thanks,

Thilo

2 Likes

In UE 5.2 at least, I am (sort of) able to access these events by right clicking the keyframe. The level sequence just needed to be closed and then reopened for the events to show up.

However, when the event is from the parent LevelSequenceDirector class, it won’t call the event directly. Instead, it makes a new “SequenceEvent” which then calls your event from the parent class.

BUT, it seems to allow you to rename this “SequenceEvent” the same as the event in the parent class and thus gets called directly (just don’t forget the Call to Parent Function/Event).

This is clearly a bug. There’s another case where this issue can be bypassed, but it’s not practical for regular use.

  1. Create the event in the child class — let’s call it TestEvent.
  2. In the Event Track, create a new event that calls TestEvent.
  3. Go to the parent class and create TestEvent there (with the same parameters, if any).
  4. Go back to the child class, delete TestEvent, and compile both Blueprints.

When you play the sequence, the event in the parent class is called correctly, even though TestEvent was removed from the child class.
However, if you add another event to the Event Track and try to bind it to TestEvent, it will create a new TestEvent in the child class that simply calls the parent class again.

How can this bug be reported? It’s been around for almost 5 years now… @EpicDeveloper

Subject: [FIXED] Sequencer Event Track Creates Unnecessary Child Overrides for Parent Blueprint Events

Well, I found the issue myself. Because 5 years and Epic, well…

So, when using a Level Sequence to trigger a Blueprint event, if the event is defined in a parent Blueprint and you try to bind to it from a child Blueprint instance, the Sequencer editor doesn’t bind directly to the parent’s event. Instead, it auto-creates a new, empty Custom Event in the child Blueprint with the same name, which then calls the parent function.

This creates unnecessary nodes and makes the Blueprint graph cluttered and confusing, especially when you explicitly want to call the parent’s implementation without an override.

Why It Happens

The root cause is a discrepancy between how the Sequencer editor handles event binding and how the engine resolves function calls at runtime.

  1. Runtime: At runtime, the engine correctly uses FindFunctionByName with EIncludeSuperFlag::IncludeSuper, so it walks up the inheritance chain and finds the function in the parent class. This is why existing bindings still work even if you delete the child override.
  2. Editor-Time: The UI logic for binding the event, specifically in FMovieSceneDirectorBlueprintEndpointCustomization::HandleQuickBindActionSelected, does not correctly handle the case where the selected function exists only in a parent class. When it fails to find a UK2Node for the function in the current Blueprint, it falls back to creating a new endpoint, leading to the unwanted child event.

The Fix

The solution involves a two-part change to D:\UnrealEngine\Engine\Source\Editor\MovieSceneTools\Private\MovieSceneDirectorBlueprintEndpointCustomization.cpp to allow the editor to find and bind to nodes in parent Blueprints.

Step 1: Update HandleQuickBindActionSelected to Find Parent Nodes

We need to modify this function to explicitly search the parent Blueprint’s graphs for the corresponding node if the selected function is not in the child.

// In FMovieSceneDirectorBlueprintEndpointCustomization::HandleQuickBindActionSelected(...)

// ... after getting FunctionToCall
if (FunctionToCall)
{
    // START of new code block
    UClass* FunctionOwnerClass = FunctionToCall->GetOwnerClass();
    UBlueprint* FunctionBlueprint = Cast<UBlueprint>(FunctionOwnerClass->ClassGeneratedBy);

    if (FunctionBlueprint && FunctionBlueprint != Blueprint)
    {
        // This is a function from a parent Blueprint.
        // Find the corresponding UK2Node in the parent's graphs.
        UK2Node* ParentNode = nullptr;
        for (UEdGraph* Graph : FunctionBlueprint->UbergraphPages)
        {
            for (UEdGraphNode* Node : Graph->Nodes)
            {
                UK2Node_CustomEvent* CustomEvent = Cast<UK2Node_CustomEvent>(Node);
                if (CustomEvent && CustomEvent->GetFunctionName() == FunctionToCall->GetFName())
                {
                    ParentNode = CustomEvent;
                    break;
                }
            }
            if (ParentNode) break;
        }
        
        if (!ParentNode)
        {
            for (UEdGraph* Graph : FunctionBlueprint->FunctionGraphs)
            {
                if (Graph->GetFName() == FunctionToCall->GetFName())
                {
                    for (UEdGraphNode* Node : Graph->Nodes)
                    {
                        if (UK2Node_FunctionEntry* FunctionEntry = Cast<UK2Node_FunctionEntry>(Node))
                        {
                            ParentNode = FunctionEntry;
                            break;
                        }
                    }
                }
                if (ParentNode) break;
            }
        }

        if (ParentNode)
        {
            // We found the node in the parent. Pass it to SetEndpoint.
            SetEndpoint(EndpointDefinition, ParentNode, ParentNode, EAutoCreatePayload::Variables);
            return; // We are done.
        }
    }
    // END of new code block

    // Original code continues here...
    UClass* OuterClass = CastChecked<UClass>(FunctionToCall->GetOuter());
    if (OuterClass->ClassGeneratedBy == Blueprint && Blueprint->SkeletonGeneratedClass)
    {
        // ...

Step 2: Relax the Blueprint Check in SetEndpoint

The SetEndpoint function has a check that ensures the node being bound belongs to the same Blueprint as the sequence. We need to relax this to allow a parent’s node to be bound.

// In FMovieSceneDirectorBlueprintEndpointCustomization::SetEndpoint(...)

// Find this line:
if (!ensureAlwaysMsgf(
        Pair.Value.Blueprint == Blueprint && Pair.Key == Sequence, 
        TEXT("Attempting to assign an endpoint to objects with different Sequence Director Blueprints.")))

// And change it to this:
if (!ensureAlwaysMsgf(
        (Pair.Value.Blueprint == Blueprint || (Blueprint && Pair.Value.Blueprint->ParentClass && Pair.Value.Blueprint->ParentClass->IsChildOf(Blueprint->GeneratedClass))) && Pair.Key == Sequence, 
        TEXT("Attempting to assign an endpoint to objects with different Sequence Director Blueprints.")))

After making these changes in your engine source code, a rebuild is necessary. Once rebuilt, the Sequencer Event Track will correctly bind to inherited events without creating unnecessary nodes.

Peace :victory_hand: