{"id":4204,"date":"2022-06-11T14:06:33","date_gmt":"2022-06-11T12:06:33","guid":{"rendered":"https:\/\/store.algosyntax.com\/?post_type=asx-lms-tutorial-cpt&#038;p=4204"},"modified":"2026-03-09T07:27:05","modified_gmt":"2026-03-09T05:27:05","slug":"creating-custom-sequencer-tracks-in-unreal-engine","status":"publish","type":"asx-lms-tutorial-cpt","link":"https:\/\/store.algosyntax.com\/tutorials\/unreal-engine\/creating-custom-sequencer-tracks-in-unreal-engine\/","title":{"rendered":"Creating Custom Sequencer Tracks In Unreal Engine"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"4204\" class=\"elementor elementor-4204\" data-elementor-post-type=\"asx-lms-tutorial-cpt\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-9edd7ed elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"9edd7ed\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c44fd12\" data-id=\"c44fd12\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7a1dc24 elementor-widget elementor-widget-text-editor\" data-id=\"7a1dc24\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>To create custom sequencer tracks in UE5 you need to create a custom <strong>UMovieSceneTrack<\/strong> and <strong>UMovieSceneSection<\/strong>.<\/p><p>\u00a0<\/p><p>To make sure our custom tracks and sections show up in the Sequencer editor where they can be added, we need a custom <a href=\"https:\/\/docs.unrealengine.com\/5.0\/en-US\/API\/Editor\/Sequencer\/FMovieSceneTrackEditor\/\" target=\"_blank\" rel=\"noopener\">FMovieSceneTrackEditor<\/a> class and a custom <a href=\"https:\/\/docs.unrealengine.com\/5.0\/en-US\/API\/Editor\/Sequencer\/ISequencerSection\/\" target=\"_blank\" rel=\"noopener\">ISequencerSection<\/a> class.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cc061fc elementor-widget elementor-widget-text-editor\" data-id=\"cc061fc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>The ISequencerSection class is responsible for visualizing our UMovieSceneSection to the user. It controls how our section looks, how it&#8217;s drawn, and what&#8217;s drawn on it.\u00a0<\/p><p>The FMovieSceneTrackEditor class is responsible for the buttons and menus that will manage our UMovieSceneTrack in the editor. For example, add or remove track buttons.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-188503d elementor-widget elementor-widget-text-editor\" data-id=\"188503d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<ol><li><h2>Create A UMovieSceneSection<\/h2><\/li><\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8fba6e2 elementor-widget elementor-widget-text-editor\" data-id=\"8fba6e2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>We start with <a href=\"https:\/\/docs.unrealengine.com\/5.0\/en-US\/API\/Runtime\/MovieScene\/UMovieSceneSection\/\" target=\"_blank\" rel=\"noopener\">UMovieSceneSection<\/a> because sections go inside UMovieSceneTracks.\u00a0<\/p><p>We have to override UMovieSceneTrack::CreateNewSection() when we create a UMovieSceneTrack, and that function requires that we create our custom section and return it.\u00a0<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-75db670 elementor-widget elementor-widget-text-editor\" data-id=\"75db670\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>So, we need to create a child class of UMovieSceneSection before we proceed. You can have whatever variables you like in this class, we will get to that later. Right now our main goal is to have a track show up in the sequencer editor.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-43a4346 elementor-widget elementor-widget-code-highlight\" data-id=\"43a4346\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-cpp line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-cpp\">\n\t\t\t\t\t<xmp>UCLASS()\r\nclass MYPLUGINAPI UCustomMovieSceneSection : public UMovieSceneSection\r\n{\r\n\tGENERATED_BODY()\r\npublic:\r\n\t\r\n\tUPROPERTY(EditAnywhere)\r\n\tFString SomeUsefulVariable;\r\n};<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-89edc2f elementor-widget elementor-widget-text-editor\" data-id=\"89edc2f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<ol start=\"2\">\n \t<li>\n<h2>Create A Custom UMovieSceneTrack<\/h2>\n<\/li>\n<\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bfb660b elementor-widget elementor-widget-text-editor\" data-id=\"bfb660b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Now that we have our custom section that will go inside the track, we can create our <a href=\"https:\/\/docs.unrealengine.com\/5.0\/en-US\/API\/Runtime\/MovieScene\/UMovieSceneTrack\/\" target=\"_blank\" rel=\"noopener\">UMovieSceneTrack<\/a> child class.<\/p><p>We need to override the following virtual functions. Most of them will be called by sequencer when editing your Track so they MUST be overridden. With an exception of few.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-050e85e elementor-widget elementor-widget-code-highlight\" data-id=\"050e85e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-cpp line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-cpp\">\n\t\t\t\t\t<xmp>UCLASS()\r\nclass MYPLUGIN_API UCustomSceneTrack : public UMovieSceneTrack\r\n{\r\n\tGENERATED_BODY()\r\n\r\npublic:\r\n\r\n\t\/\/begin UMovieSceneTrack interface\r\n\r\n\tvirtual FText GetDisplayName() const override;\r\n\r\n\tvirtual FName GetTrackName() const override;\r\n\r\n\tvirtual bool IsEmpty() const override;\r\n\r\n    \/\/INTENTIONALLY NOT OVERRIDEN\r\n\t\/\/virtual UMovieSceneSection* CreateNewSection() override;\r\n\r\n\tvirtual void AddSection(UMovieSceneSection& Section) override;\r\n\r\n\tvirtual void RemoveSection(UMovieSceneSection& Section) override;\r\n\r\n\tvirtual const TArray<UMovieSceneSection*>& GetAllSections() const override;\r\n\r\n\t\/\/END UMovieSceneTrack Interface\r\n\r\n\tUPROPERTY()\r\n\tTArray<UMovieSceneSection*>  CustomSceneSections;\r\n\t\r\n};<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-88336a7 elementor-widget elementor-widget-text-editor\" data-id=\"88336a7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Notice we intentionally did not override the CreateNewSection() function.<br \/><br \/><\/p><p>This is because we have found this function is never called automatically anywhere. We could be wrong since it&#8217;s a pure virtual function.<br \/><br \/><\/p><p>We end up having to create a custom CreateNewSection(arg1,arg2) function that takes in more arguments. So you can either override this function or create your own. We are going to manually call it later in our\u00a0 FMovieSceneTrackEditor child class.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a0cfd3a elementor-widget elementor-widget-text-editor\" data-id=\"a0cfd3a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>We hope implementing these will be straight forward but if in doubt we cover them in our Plugin Development Course for Unreal Engine.\u00a0<\/p><p>They are mostly self-explanatory, for example, the IsEmpty() function will be called whenever the engine wants to check if your custom track is empty or not. You can run custom logic here.<\/p><p>\u00a0<\/p><p>The CustomSceneSections UPROPERTY() TArray is made up of UCustomMovieSceneSection we created in step 1.<\/p><p>The reason we use UMovieSceneSection is so that we don&#8217;t have to cast back and forth when working the UMovieSceneTrack interface (overridden virtual functions). This is one of the areas where Polymorphism shines.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-687c076 elementor-widget elementor-widget-text-editor\" data-id=\"687c076\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<ol start=\"3\">\n \t<li>\n<h2>Create A ISequencerSection<\/h2>\n<\/li>\n<\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-06521b7 elementor-widget elementor-widget-text-editor\" data-id=\"06521b7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>We&#8217;ve created our Custom tracks and custom sections where our backend logic goes. Now, we will cover the graphics side of things. What people see in the editor in the Sequencer window when a section is drawn\/shown.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a68a68d elementor-widget elementor-widget-text-editor\" data-id=\"a68a68d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>The ISequencerSection is responsible for how our custom USceneSection is drawn to the user. We will start with creating a child class and overriding the necessary virtual functions.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-5282997 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"5282997\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ce81fd3\" data-id=\"ce81fd3\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-78e3706 elementor-widget elementor-widget-heading\" data-id=\"78e3706\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Source Code Examples<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2079cd7 elementor-widget elementor-widget-text-editor\" data-id=\"2079cd7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>If you need Source Code Examples you can grab one of our plugins that create custom sequencer tracks and go through the documented links.<br \/><br \/>Download <a href=\"https:\/\/store.algosyntax.com\/marketplace\/unreal-engine\/umg-cinematics\/\">UMG Cinematics Plugin.<\/a><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"featured_media":0,"template":"","asx-lms-tutorial-categories":[64,55,58,45],"asx-lms-tutorial-tags":[46],"class_list":["post-4204","asx-lms-tutorial-cpt","type-asx-lms-tutorial-cpt","status-publish","hentry","asx-lms-tutorial-categories-sequencer-api","asx-lms-tutorial-categories-plugin-development","asx-lms-tutorial-categories-unreal-c-api","asx-lms-tutorial-categories-unreal-engine","asx-lms-tutorial-tags-cpp","entry"],"acf":[],"_links":{"self":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/asx-lms-tutorial-cpt\/4204","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/asx-lms-tutorial-cpt"}],"about":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/types\/asx-lms-tutorial-cpt"}],"version-history":[{"count":0,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/asx-lms-tutorial-cpt\/4204\/revisions"}],"wp:attachment":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/media?parent=4204"}],"wp:term":[{"taxonomy":"asx-lms-tutorial-categories","embeddable":true,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/asx-lms-tutorial-categories?post=4204"},{"taxonomy":"asx-lms-tutorial-tags","embeddable":true,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/asx-lms-tutorial-tags?post=4204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}