Fab packages and separate plugins
Pulse Foundation comes into a project in one of two ways. Both run the same code; they differ in where the plugins come from and how they are updated.
| Way | Comes from | Pulse Foundation | Updates |
|---|---|---|---|
| Fab package | Fab, installed with the Epic Games Launcher | Inside the package of the Pulse plugin, with renamed modules (PulseSkill_PulseFoundation, …) and its content under /PulseSkill/Foundation | Through Fab; every update brings its own Pulse Foundation |
| Separate plugins | Pulse HUB (or a Git checkout) | Its own plugin PulseFoundation next to the Pulse plugins | In the editor with Pulse HUB |
Use one way per project, never both.
Fab packages
Fab builds every plugin on its own, so a Pulse plugin on Fab carries its own copy of Pulse Foundation. The package builder renames the modules of that copy (prefix <Plugin>_), moves its content to /<Plugin>/Foundation and writes PulseBundle.json into the root of the package.
Everything keeps its usual names:
- Assets and Blueprints that refer to
/Script/PulseFoundation...classes or/PulseFoundation/...assets load through redirects in the package config (Config/Default<Plugin>.ini). - C++: includes and types stay the same, but a module that uses Pulse Foundation names the renamed modules in its
Build.cs, for examplePulseSkill_PulseFoundationandPulseSkill_PulseFoundationUIinstead ofPulseFoundationandPulseFoundationUI. The linker needs these direct dependencies; a public dependency ofPulseSkillonly passes on the include paths. When a project switches to separate plugins, Pulse HUB changes the names back. - Project settings of Pulse Foundation are stored under the renamed module, for example
[/Script/PulseSkill_PulseFoundationUI.PulseUISettings]instead of[/Script/PulseFoundationUI.PulseUISettings]. Project Settings writes the right section. When a project switches to separate plugins, Pulse HUB rewrites these sections.
Only one copy per project
A project can use the Fab package of one Pulse plugin. The Fab packages of two Pulse plugins bring two copies of Pulse Foundation, and only one copy can run:
- C++ projects stop the build with a message that names both copies, before the compiler runs.
- The editor (Blueprint projects, prebuilt binaries) starts. The first copy is active: the separate plugin if it is there, otherwise the package of the plugin that comes first by name. The other copies register nothing global: no settings pages, tabs, menus, console commands, cheats or gameplay debugger categories. A notice and the log (
LogPulseFoundation) name the copies. The plugin that brought an inactive copy does not work properly.
To fix it, disable all but one of the packages in Edit > Plugins, or switch to separate plugins with Pulse HUB: it reports your Fab purchases from the Epic Games Launcher, and once they are confirmed it installs the separate plugins in the same versions.
Switching to separate plugins
Assets saved while a Fab package was in use keep working after the switch. The separate Pulse Foundation redirects the names of every Pulse Fab package back to its own (DefaultPulseFoundation.ini, block between luq-bundle-exclude-begin and luq-bundle-exclude-end):
/Script/PulseSkill_PulseFoundationUIand the other renamed modules to/Script/PulseFoundationUIand so on;/PulseSkill/Foundation/...to/PulseFoundation/....
The package builder removes this block from Fab packages.
Suggestion of Pulse HUB
When a Pulse plugin came as a Fab package and Pulse HUB is not enabled, the editor suggests Pulse HUB a few seconds after it starts: updates in the editor, extras like bridges and MCP tools, and several Pulse plugins in one project. The notice has three buttons:
- Get Pulse HUB opens the page of Pulse HUB (free).
- Learn More opens this page.
- Don’t Show Again turns the notice off.
You can also turn it off in Editor Preferences > Pulse > Foundation > Workflow > Suggest Pulse HUB at Startup (per user). The notice does not show in commandlets, unattended runs, automation tests or while playing, and not when Pulse HUB is enabled. When several copies of Pulse Foundation are enabled, the conflict notice shows instead.
For plugin code
Distribution/PulseDistribution.h (namespace Pulse::Foundation) tells which copy the code runs in:
| Function | Returns |
|---|---|
GetHostPluginName() | PulseFoundation, or the plugin of the Fab package, e.g. PulseSkill |
GetModuleName(), GetModulePrefix() | PulseFoundation and an empty prefix, or PulseSkill_PulseFoundation and PulseSkill_ |
IsBundled() | True inside a Fab package |
GetContentRoot(), MakeContentPath(Path) | /PulseFoundation, or /PulseSkill/Foundation; the full path of a Pulse Foundation asset |
GetEnabledCopies(), IsActiveCopy(), HasCopyConflict() | The copies of Pulse Foundation among the enabled plugins and whether this one runs |
- Build paths of Pulse Foundation assets with
MakeContentPathinstead of writing/PulseFoundation/.... - Find the plugin of Pulse Foundation with
GetHostPluginName()instead of the namePulseFoundation. - The module interfaces (
IPulseFoundation::Get(),IPulseFoundationEditor::Get(), …) find their module by its real name, so they work in both ways. - A new Pulse plugin with a Fab package gets its lines in the reverse redirect block of
DefaultPulseFoundation.iniand in the product list of the specPulseFoundation.Distribution.