Using PulseFoundation in a Pulse plugin

PulseFoundation is the only Pulse plugin another Pulse plugin may depend on. This page lists what a Pulse plugin takes from PulseFoundation instead of own code, and what it adds so it fits the other plugins.

Dependency

```json title=”.uplugin" "Plugins": [ { "Name": "PulseFoundation", "Enabled": true } ]


```csharp title="<Module>.Build.cs"
PublicDependencyModuleNames.Add("PulseFoundation");

List PulseFoundation in the Build.cs of every module that uses its types, also when a module it depends on already lists it publicly: the include paths are passed on, but the linker needs the direct dependency (otherwise unresolved external symbol ... UPulseDeveloperSettings or Pulse::Serialization::...). Modules whose public headers use PulseFoundation types (a settings class deriving from UPulseDeveloperSettings, a component implementing IPulseDebugSnapshotProvider) list it in PublicDependencyModuleNames.

Name the minimum PulseFoundation version in the plugin’s README and check it in code where needed: static_assert(PULSE_FOUNDATION_VERSION_AT_LEAST(1, 0), "...").

Fab packages

On Fab, a Pulse plugin comes with its own copy of PulseFoundation: renamed modules (PulseSkill_PulseFoundation, …) and its content under /<Plugin>/Foundation (see Fab packages and separate plugins). The package builder renames the dependencies in the plugin’s Build.cs and .uplugin, so they keep the name PulseFoundation. In code:

  • Never write the plugin, module or content names of PulseFoundation as text. Use Pulse::Foundation::GetHostPluginName(), the module interfaces (IPulseFoundationEditor::Get(), …) and Pulse::Foundation::MakeContentPath(), e.g. for default asset paths in a settings constructor: MakeContentPath(TEXT("UI/Textures/T_PulseUI_Icon_Check.T_PulseUI_Icon_Check")).
  • A plugin that gets a Fab package adds its lines to the reverse redirect block of DefaultPulseFoundation.ini and to the product list of the spec PulseFoundation.Distribution.
  • Build the plugin with RunUAT BuildPlugin before a release. It compiles the files one by one, like Fab does, and finds missing includes that the unity files of a project build hide.

Replace own copies

Own code PulseFoundation
SaveDataToBytes / LoadDataFromBytes with SerializeTaggedProperties Pulse::Serialization::StructToBytes / ReadVersioned (same byte format)
Own import report with TArray<FString> Messages FPulseImportReport (derive or embed)
Controller / player state / pawn lookups Pulse::Player::*, FindComponentOnPlayer
UDeveloperSettings with category “Pulse” UPulseDeveloperSettings
Own handle structs FPulseHandle (or wrap it)
Own instanced struct “one per type” lists FPulseInstancedStructSet / Pulse::Structs
Own view model resolver for “owning player” UMVVMPulsePlayerViewModel + UPulsePlayerViewModelResolver
Test world setup in specs Pulse::Testing::FTestWorld
Report recorder / JSON report files FPulseReportRecorder + FPulseReportPolicy

Keep public functions that other plugins or games call; forward them to PulseFoundation and mark them UE_DEPRECATED.

Add

  • Broadcast events that others may react to loosely on Pulse.Message.<Plugin>.<Event> with a payload struct, in addition to the native and dynamic events.
  • Implement IPulseDebugSnapshotProvider on the plugin’s main components and subsystems.
  • Record PULSE_DEBUG_EVENTs for what happens (started, finished, rejected and why).
  • Add a FPulseReportPolicy to the settings when the plugin has multi-step processes, and report them.
  • Move player-facing options into a UPulsePlayerSettings subclass.
  • Add cheats as a UPulseCheatExtension subclass.

PulseFoundation plugin documentation.

This site uses Just the Docs, a documentation theme for Jekyll.