FollowPhotoCameras Documentation
FOLLOW PHOTO CAMERAS — DOCUMENTATION
Version 2.0.0
Publisher: CelestiaDominance
Release copies: Unreal Engine 5.6, 5.7, and 5.8 / Windows Win64
1. OVERVIEW
Follow Photo Cameras creates runtime cameras that orbit and follow an actor and save PNG photographs. You can capture automatically at an interval or request a manual capture pass from Blueprint or C++.
Version 2.0.0 keeps Start Cameras, Stop Cameras, and Take Photo. It also provides Start Camera Session, which accepts an output folder directly and returns a session object with independent controls and confirmed save results.
The plugin captures a scene from its own cameras. It does not change the player's view target, record video, capture desktop windows, or include screen-space HUD/UMG overlays. Output is an opaque, 8-bit, lossless PNG, not HDR/EXR.
2. INSTALLATION
Install the copy matching your Unreal Engine version. Enable Follow Photo Cameras in Edit > Plugins, then restart the editor if requested. For a project-local source installation, place the FollowPhotoCameras folder inside your project's Plugins folder and build with the toolchain required by that engine version.
Use one active installation of the plugin in a project. A project-local copy takes precedence over an engine-installed copy; remove an obsolete project-local copy when you intend to use a newer engine-installed version.
No project input bindings, Blueprint subclasses, external image encoders, or engine modifications are required. Connect the public nodes to your own UI or input events. The plugin is code-only; its default camera visuals reference Unreal's runtime basic shapes. You may supply your own static mesh.
Supported runtime platform: Windows Win64. Capture requires a rendering game, PIE instance, standalone game, or rendering multiplayer client. Dedicated servers, NullRHI processes, and editor-only worlds cannot start a photo session. Calls must run on the game thread. The target must be alive in the same world as the world context.
3. QUICK START — AUTOMATIC PHOTOS
1) In a Blueprint that belongs to the running world, create a Follow Photo Camera Settings variable or use Make Follow Photo Camera Settings.
2) For the first test, set Camera Count = 1, Resolution Preset = 1K, Shots Per Camera = 3, and Manual Trigger Photos = false.
3) Call Start Camera Session. Supply your target actor, the settings, and an output folder.
4) Leave Output Folder blank to use your project's Saved/FollowPhotoCameras directory. A relative folder such as Photos/MyCharacter is resolved under the project's Saved directory. An absolute folder such as D:/MyPhotos uses that location directly.
5) Store the returned Follow Photo Camera Session object in a Blueprint variable. If it is invalid, display Failure Reason.
6) Read Photos Saved and Pending Saves to show progress. When Is Active becomes false, inspect Completed and Last Error.
The first automatic pass runs on a subsequent manager tick. Each pass attempts up to Max Cameras Captured Per Pass when Performance Mode is enabled. With more cameras than that limit, successive passes rotate through the cameras. Capture Interval Seconds is the interval between passes, not a guaranteed per-camera image interval.
Capture finishes when every camera reaches its confirmed photo quota and accepted writes finish. A save failure stops the session and exposes an error. An invalid or destroyed target also stops the session.
4. QUICK START — MANUAL PHOTOS
Set Manual Trigger Photos = true before starting a session. Call Take Photo on the returned session whenever you want a capture pass. Call Stop on that session to finish early.
The Take Photo return value is the number of accepted images in that pass. With async saving, accepted images may still be compressing or writing. Photos Saved counts confirmed files; Pending Saves counts accepted writes whose results have not yet been collected by the game thread.
A return value of zero can mean the session is inactive, it is configured for automatic capture, its quota is exhausted, a capture already ran during this engine frame, its save queue is full, or the current camera positions were skipped by collision/visibility checks. Use the session properties to distinguish completion or errors from a temporary skipped pass.
The session allows at most one capture pass per engine frame, including manual calls. Request another pass on a later frame when required. Manual mode does not use Capture Interval Seconds.
5. BLUEPRINT LIBRARY NODES
Start Camera Session
Inputs: World Context Object, Actor To Follow, Settings, Output Folder.
Outputs: Follow Photo Camera Session object, Failure Reason.
Starts without opening a folder dialog. Validates the world, target, settings, hardware texture dimensions, output folder, and resource budgets. Returns an invalid object on failure. On success, the session exposes the normalized Effective Settings and absolute Output Folder.
Start Cameras (existing node)
Inputs: World Context Object, Actor To Follow, Settings.
Return: boolean.
Opens a native Windows folder picker, then starts a session. Returns false on cancellation or startup failure. This dialog workflow is unavailable in unattended processes. Use Start Camera Session for your own folder-selection UI, automation, or a predetermined output directory.
Stop Cameras (existing node)
Input: World Context Object.
Return: number of sessions stopped in that world.
Stops every active Follow Photo Cameras manager in the resolved world and finishes accepted writes. The count refers to sessions/managers, not individual camera actors. Other worlds are unaffected.
Take Photo (existing library node)
Input: World Context Object.
Return: total accepted images from manual sessions in that world.
Requests one pass from each active manual session. Automatic sessions are ignored. To address only one session, call Take Photo on its session object instead.
6. SESSION OBJECT
Keep the object returned by Start Camera Session in a Blueprint variable or a reflected C++ reference. Its final results remain available while you keep that reference, even after its camera manager has stopped.
Controls:
- Take Photo: request a manual pass for this session only.
- Stop: stop this session and finish writes that have already been accepted.
Read-only properties:
- Is Active (bIsActive): the session is still running or collecting pending results.
- Completed (bCompleted): all configured photo quotas finished naturally without a save failure. An explicit early Stop is not natural completion.
- Photos Saved: number of successfully encoded and written PNG files.
- Pending Saves: accepted async writes awaiting result collection.
- Failed Saves: number of failed readback/save operations reported by the session.
- Last Error: latest actionable failure. Empty when no error was recorded. Target destruction is reported here without being counted as a failed disk write.
- Last Saved File: absolute path of a confirmed PNG. Async completion order may differ from camera order.
- Output Folder: the resolved absolute output directory.
- Effective Settings: settings after preset resolution and range normalization.
Stop, Stop Cameras, and world teardown wait for already accepted save jobs. This preserves accepted output and prevents worker jobs from accessing destroyed capture actors. Stopping a session with large images or slow storage can therefore take time. Normal automatic/manual capture can compress and write in the background, but GPU rendering and pixel readback still run synchronously.
While the world is paused, normal automatic capture and movement pause. The manager can still collect completed save results. Sessions belong to their current world and stop during world teardown/level travel. Starting a new session creates new cameras; an active session is not serialized as a save-game capture job.
7. ALL CAMERA SETTINGS
CAMERAS
CameraCount — default 1, range 1–32.
Number of follow cameras in this session. Every camera has its own motion state and photo quota. The session shares one render target between its sequential captures.
bShowCameraActors — default true.
Shows runtime camera visuals in the playable world. These visuals are hidden from scene captures, including other Follow Photo Cameras sessions.
CameraVisualMesh — default none.
Optional static mesh used as the camera visual. With no custom mesh, the plugin uses Unreal's runtime cube and cylinder shapes. Assign your asset through the settings so Unreal can track its reference for cooking. This affects the visible camera representation, not the photographed target.
CAPTURE
ResolutionPreset — default R2K.
R1K: 1024 x 540
R2K: 2048 x 1080
R4K: 4096 x 2160
R8K: 8192 x 4320
R12K: 12288 x 6480
Custom: uses ResolutionX and ResolutionY.
ResolutionX — default 1920; ResolutionY — default 1080.
Used only with Custom. Each dimension is normalized to 64–16384. The requested result must also fit the active graphics device and the image memory budget. A preset that exceeds the device limit is rejected rather than silently resized.
CaptureIntervalSeconds — default 1.0, range 0.01–60.0.
Time between automatic passes. Actual throughput also depends on frame rate, the camera pass limit, rendering/readback cost, visibility, and queue capacity. Missed time does not create a burst of catch-up captures in one frame.
bManualTriggerPhotos — default false.
When true, photos are requested by Take Photo. Otherwise the manager schedules automatic passes.
ShotsPerCamera — default 25, range 1–100000.
Maximum confirmed photos per camera. Pending saves reserve quota so repeated requests cannot overshoot it. Failed saves do not count as successful photos.
bRequireTargetVisibility — default true.
Skips photographs when the target is obstructed according to the configured visibility trace channel. Disable this when intentional occlusion is part of the desired photograph. Visibility checks use target bounds sample points; they are not pixel-level segmentation or a guarantee that the whole actor fits in frame.
CAPTURE / PERFORMANCE
bEnablePerformanceMode — default true.
Limits cameras attempted in each pass, uses round-robin scheduling, and enables the optional async compression/write path.
MaxCamerasCapturedPerPass — default 2, range 1–32.
Maximum camera attempts in a pass with Performance Mode enabled. Obstructed camera attempts also consume this limit to bound the work done in a pass. With Performance Mode disabled, a pass can attempt all cameras.
bAsyncPngCompressionAndSave — default true.
When both this and Performance Mode are enabled, PNG compression and disk writing run on worker threads. Pixel readback remains synchronous. With either option disabled, the image is compressed and written synchronously.
MaxPendingAsyncSaveJobs — default 12, range 1–256.
Per-session limit on pending async writes. A separate process-wide raw-pixel memory budget can reduce the number of simultaneous jobs further. A full queue defers new shots; it does not count them as saved or report a disk failure.
CAPTURE / QUALITY
bEnableCaptureExposureCompensation — default true.
Overrides capture exposure bias. It does not force the exposure metering method, so an explicitly configured manual exposure method remains usable.
CaptureExposureCompensation — default 0.1, range -4.0–4.0.
Exposure bias applied while compensation is enabled. Positive values brighten, negative values darken.
bUseLinearToGammaConversion — default true.
Legacy readback flag. FinalColorLDR is already output-color data on the plugin's 8-bit render target, so this flag normally has no additional effect. It is not an HDR conversion workflow.
CaptureOutputGamma — default 2.2, range 1.0–3.0.
Output gamma supplied to the render target.
MOVEMENT / SMART
bEnableSmartCollisionAvoidance — default true.
Uses sphere sweeps and overlap checks to resolve a camera pose. Cameras can move closer than Min Distance in confined spaces. Recovery positions are checked, and configured height offsets are not mistaken for a runaway camera distance. When no valid pose is available, the plugin may skip the image.
CameraCollisionChannel — default Camera (ECC_Camera).
Trace channel used by camera sweeps and overlap checks. Configure relevant walls and obstacles to block this channel.
VisibilityTraceChannel — default Visibility (ECC_Visibility).
Trace channel used to check whether the target is obstructed. Transparent geometry still follows its collision response; configure the channel to match the intended behavior.
CollisionProbeRadius — default 18 cm, range 1–1000 cm.
Radius of the collision probe. Adjust this for the scale and geometry of your scene.
MOVEMENT
MovementPreset — default Balanced.
Cinematic favors smoother movement and more lag; Aggressive favors faster motion and less lag. Balanced is the middle preset. The preset's smoothness/lag values are averaged with the corresponding user settings to produce the effective motion values.
MovementSmoothness — default 0.7, range 0–1.
Higher values soften orbit movement and retargeting.
bEnableCameraLag — default true.
Enables interpolated follow behavior.
CameraLagStrength — default 0.35, range 0–1.
Contributes to the effective lag strength when lag is enabled. Disable Camera Lag to remove lag completely; the preset also contributes to the effective strength.
bAdaptLagToTargetSpeed — default true.
Increases follow response as the followed actor's velocity increases. An actor that is teleported without updating velocity may not report meaningful speed, although its position is still followed.
ORBIT
MinDistance — default 150 cm; MaxDistance — default 1000 cm.
Preferred orbit radius before the separate height offset is applied. Range 10–100000 cm. These are not a strict maximum on the final 3D distance once height, lag, and collision resolution are included.
MinHeightOffset — default 1 cm; MaxHeightOffset — default 1000 cm.
Additional vertical offset relative to the followed focus. Range -100000–100000 cm.
MinPitchDegrees — default -10; MaxPitchDegrees — default 25.
Pitch range for orbit placement, normalized to -89–89 degrees. These placement angles are separate from the camera's final look-at rotation.
Reversed distance, height, and pitch ranges are normalized by swapping their endpoints.
CAMERA
FieldOfView — default 90, range 10–170 degrees.
Scene capture field of view. A large target or a very close camera may require a wider field of view or greater distance; automatic whole-actor framing is not provided.
FocusOffset — default (0, 0, 0).
World-space offset from the target's visual bounds center. A target without meaningful visual bounds falls back to its actor location. Use an offset to aim above or beside the default focus.
EFFECTS
bApplyPostProcess — default false.
Blends the supplied PostProcessSettings into the capture.
PostProcessSettings — Unreal's standard post-process settings structure.
Enable the override checkbox for each field you intend to change. World post-process volumes can still contribute. Capture exposure compensation, when enabled, overrides the exposure bias after these settings are copied. Disable compensation if your custom bias should take precedence.
8. RESOURCE LIMITS AND PERFORMANCE
The plugin validates finite numeric settings and uses 64-bit image-size calculations before allocating capture resources. Invalid enum values and unsupported texture sizes fail startup with a reason.
Across all sessions/worlds in one process, it limits the combined capture render targets to 512 MiB, pending async raw pixel buffers to 512 MiB, and active cameras to 64. Each session can request at most 32 cameras. Separate PIE processes have separate limits. These are plugin buffer limits, not a cap on Unreal's total RAM or VRAM: scene rendering, temporal histories, PNG compression, and the rest of the game use additional memory.
A 12K preset image requires approximately 304 MiB for one BGRA pixel buffer alone. Sharing a render target reduces repeated target allocations, but high resolution and many camera views remain expensive. Start with 1K/2K, a small camera count, and one or two cameras per pass. Measure frame times and memory on the hardware you intend to support before using 8K/12K captures during gameplay.
The output folder is checked for writability before cameras start. Keep its normalized absolute path at or below 180 characters so generated image and temporary filenames remain within the supported Windows path budget. Storage availability can still change after startup; inspect Last Error and Failed Saves.
9. MULTIPLAYER, PAUSE, AND WORLD LIFETIME
Sessions and capture actors are local and are not replicated. Start a session on the rendering client that should produce the files. This includes a listen-server player's local process when rendering is available. Calling the nodes on a dedicated server will fail safely.
World context prevents one PIE/game world from starting a session for an actor in another world. The legacy Stop Cameras and Take Photo library nodes operate on all relevant sessions in their own world. They do not separate local players within a shared split-screen world; use independent session objects when individual callers should control only their own cameras.
The plugin follows the target's transform and visual bounds. Existing mesh visibility flags, collision responses, post-process volumes, lighting, and rendering features still determine what appears in a scene capture.
10. FILES AND TROUBLESHOOTING
Photos use names such as camera_01_0123456789abcdef0123456789abcdef.png. Camera numbers start at 1. Files are written through exclusive temporary files and finalized without replacing an existing PNG.
Start returns false or an invalid session:
Read Failure Reason from Start Camera Session. Check the target/world, rendering availability, output path, graphics texture limit, and whether other sessions already occupy the process-wide budgets. Folder cancellation is a normal false result for Start Cameras.
Take Photo returns zero:
Confirm Manual Trigger Photos is enabled, the session is active, the call runs on a later frame than the previous pass, and there is remaining quota. Inspect Pending Saves. Review collision/visibility settings if all current camera poses are obstructed.
Pending Saves stays visible while paused:
Normal manager ticks collect worker results, including paused ticks. Explicit Stop also waits for and collects accepted results. Do not force-close the application as a substitute for Stop when you need confirmation that accepted output finished.
Images are dark or exposure varies:
Check scene lighting, world post-process volumes, and exposure overrides. For repeatable capture, enable Apply Post Process and explicitly configure manual exposure in PostProcessSettings, including the relevant override flags and physical-camera exposure option. Compensation adjusts bias without replacing the selected exposure method. Temporal effects and exposure history can require scene-specific warm-up; the plugin does not promise pixel-identical camera output across renderers or engine versions.
Frame hitches during capture:
Lower resolution, camera count, or cameras per pass. Keep async saving enabled. Compression can move off the game thread, but rendering and GPU readback can still cause a hitch.
Camera appears inside geometry or photos are skipped:
Check that your geometry has collision and blocks the chosen camera/visibility channels. Tune probe radius and orbit ranges. An entirely enclosed or unsuitable target may have no valid camera pose. Disable visibility requirements only when obstructed photographs are intentional.
Post-process setting has no effect:
Enable Apply Post Process and the individual override checkbox. Review overlapping world volumes. Disable capture exposure compensation if it conflicts with your intended exposure bias.
A custom visual is absent in a packaged game:
Assign the mesh through CameraVisualMesh in the saved settings/Blueprint that is included in the cook. Do not rely solely on a path typed into runtime code to make an otherwise unreferenced custom asset cook.
11. C++ USE
Add FollowPhotoCameras to your module dependencies. Include FollowPhotoCameraLibrary.h and FollowPhotoCameraSession.h. Keep the returned session in a UPROPERTY TObjectPtr<UFollowPhotoCameraSession> when an owning UObject should retain it.
Example (called on the game thread from a live gameplay object):
FFollowPhotoCameraSettings Settings;
Settings.bManualTriggerPhotos = true;
Settings.ResolutionPreset = EFollowPhotoResolutionPreset::R1K;
FString FailureReason;
PhotoSession = UFollowPhotoCameraLibrary::StartCameraSession(
this, ActorToFollow, Settings, TEXT("Photos/MyActor"), FailureReason);
if (PhotoSession)
{
const int32 Accepted = PhotoSession->TakePhoto();
// Check PhotosSaved/PendingSaves on later game-thread ticks.
}
When finished:
if (PhotoSession) { PhotoSession->Stop(); }
For a path built from FPaths::ProjectSavedDir(), first convert it to an absolute path with FPaths::ConvertRelativePathToFull before supplying it as OutputFolder. Otherwise it is interpreted as a caller-provided path relative to Saved.
12. UPGRADING FROM 1.0.0
The original Blueprint library nodes, settings structure, existing setting names, and resolution/movement enums remain available. Version 2 adds settings and a session API without requiring existing graphs to adopt it.
Review these intentional behavior changes: Start reports actual initialization success; automatic capture begins on a subsequent tick; Take Photo reports accepted work rather than guaranteeing an async file is already saved; repeated same-frame calls cannot exceed the capture pass budget; save failures stop and report failure; target focus uses visual bounds; capture exposure compensation no longer forces histogram metering; and unsafe/unbounded allocation requests can fail validation.
The old library nodes still act on every relevant session in their world. Use Start Camera Session and its object methods when you need separate callers, separate output folders, confirmed save counts, or per-session failure details.
13. LINKS
Fab listing: https://www.fab.com/listings/02e3e613-6739-4f6e-a651-0f0f78f39f1a
Publisher: https://www.fab.com/sellers/CelestiaDominance
Support: https://discord.gg/9Zc4wbwqG9
Copyright CelestiaDominance 2026. All Rights Reserved.