Easy Graffiti Master Documentation
EASY GRAFFITI MASTER 2.0.0 Runtime graffiti for Unreal Engine 5.7 and 5.8 | Windows 64-bit Copyright CelestiaDominance 2026. All Rights Reserved.
PURPOSE Project images onto scene surfaces during gameplay using Blueprint nodes or C++. Players can choose local images through the Windows file picker, or your game can supply an image path or a compatible 2D texture. Each application creates a separate Graffiti Decal Actor.
The plugin includes a default decal material and supports camera traces, existing hit results from your own interaction system, custom decal materials, optional moving-surface attachment, delayed appearance, timed removal, and save/restore data.
Required plugin: Niagara, included with Unreal Engine. This is a declared dependency even when you do not supply Niagara effects. The plugin provides 0 Blueprint assets, 4 production C++ classes, 2 Blueprint structs, and 1 material. The examples below are node flows for your own Blueprints.
1. QUICK BLUEPRINT WORKFLOW
Choose an image: 1) Connect your own UI button or input event to Graffiti Get Textures. 2) Check that Canceled is false AND Out Textures contains at least one entry. 3) Get an entry, break Graffiti Texture Info, and store its Texture in a Blueprint variable such as ActiveGraffitiTexture. 4) Keep that texture variable referenced while your UI or painting logic uses it.
Paint from the player's camera: 1) Connect a separate input event to Apply Graffiti. 2) Set Graffiti Texture to ActiveGraffitiTexture. 3) Use Get Player Camera Manager as Camera Source for the appropriate local player. 4) Start with Size 64, Projection Depth 2, Surface Offset 0.5, Duration 0, Spawn Delay 0, and a Trace Distance appropriate for your level. 5) Leave optional sound/effect/tag arrays empty until the basic result works. 6) Check Return Value. True means an actor was created, or created and scheduled for later reveal. False means the request was rejected or no valid surface was hit.
Apply Graffiti performs a complex Visibility-channel trace. The receiving surface must have suitable collision, block that trace, and receive decals. Show Debug draws the trace for diagnosis. Ignored Tags are actor tags: a matching first hit rejects the request; the trace does not continue through that actor.
Camera Source supports Camera Actors, Player Camera Managers, and ordinary Actors. Camera Actors use their camera component's world transform, Player Camera Managers use their camera viewpoint, and other Actors use their actor transform. For a pawn with an offset camera, use its Player Camera Manager or supply your own hit result.
One successful call creates one decal actor. If you call the node while holding an input, control the call interval and spacing in your own gameplay code. Manage the number of active decals for your target hardware.
2. USE YOUR OWN INTERACTION OR TRACE SYSTEM
Call Graffiti Apply At Hit with your selected texture and an existing blocking Hit Result. This lets your project choose its own trace channel, ignored actors, interaction range, and targeting rules.
Example flow: Your interaction event -> your trace -> check Blocking Hit -> Graffiti Apply At Hit -> check Return Value -> store Out Actor.
The hit component must be valid, registered, in the current world, and configured to receive decals. Invalid hits return false and clear Out Actor.
Attach To Surface defaults to true. The decal attaches to the hit component while preserving its initial world transform, so it can move with a door or another movable surface. A bone name supplied by the hit is passed to Unreal's attachment system. Disable attachment for a fixed world-space decal. Attachment success does not override the renderer's requirements for the receiving surface.
Out Actor gives access to Get Graffiti Info, Destroy Graffiti, Pending Spawn, and the decal component. Keep that actor reference when you need to remove or save a specific graffiti instance.
3. SIZE, ORIENTATION, DEPTH, AND TIMING
Size is the half-extent of the image's longest side in Unreal centimeters. With unit actor scale, Size 64 gives a 128 cm longest side. A 2:1 landscape image occupies 128 x 64 cm. The image's aspect ratio is preserved by the default material and decal dimensions.
Rotation adds a roll around the projection axis. Projection Depth is the decal volume's local X half-extent. Surface Offset moves the decal outward from the surface. Keep Offset nonnegative and smaller than Depth so the surface remains inside the projection volume. Smaller depths help reduce projection onto nearby geometry; results still depend on the surface and viewing angle.
Duration 0 means unlimited lifetime. A positive duration starts when the decal becomes visible. Spawn Delay postpones visibility and, for Apply Graffiti, sound/effect playback. These use game-world timers, so paused gameplay can pause them. Pending Spawn indicates that the actor is waiting to reveal.
Destroy Graffiti removes the actor and also cancels a pending reveal. Ending the world clears pending timers and retained effect references. Decal actors do not run a per-frame Tick.
Valid numeric inputs must be finite. Size and Depth must be greater than 0 and no greater than 1,000,000. Offset must satisfy 0 <= Offset < Depth. Duration and Delay must be nonnegative. Camera Trace Distance must be greater than 0 and no greater than 100,000,000. Restore data must contain a valid, nonzero world scale.
Apply Graffiti also has Use Custom Location. In that mode, the node uses your Custom Location and Custom Rotation without tracing for a surface. The rotation's local +X direction should point outward from the surface. The node applies Surface Offset and the additional graffiti rotation. Use the dedicated restore node for saved final transforms.
4. IMAGE LOADING AND STORAGE
Graffiti Get Textures opens a modal Windows picker and supports multiple selection. The game thread waits while the dialog is open. Cancellation or an unavailable dialog leaves Canceled true and clears both output arrays. A completed selection can still return empty arrays if all selected files fail validation; always inspect the array length.
Graffiti Load Texture From File loads one image without opening a dialog. It returns a texture on success or None/null on failure. Accepted paths are absolute paths, relative paths resolved against Unreal's base directory, and the plugin's graffiti:// identifiers. Relative paths are not automatically relative to your Content folder.
Supported image data: PNG, JPEG/JPG, BMP, and EXR. The loader checks the actual file format. Imported images become 8-bit BGRA, sRGB runtime textures; this is not an HDR/EXR compositing workflow. Alpha is preserved where provided by the source format.
Limits per image: - Compressed/source file: at most 32 MiB. - Each dimension: at most 8192 pixels. - Total pixels: at most 16,777,216.
One picker selection considers at most 256 entries and uses a conservative 256 MiB retained pixel-data budget. These bounds do not represent the whole process's CPU/GPU memory usage. Loading is synchronous; smaller images and smaller selections reduce stalls and memory use.
Successful imports are copied into the current game's Saved/EasyGraffiti/Textures directory. The actual Saved location is resolved by Unreal and can differ between editor and packaged games. Names are based on image contents, so ordinary same-filename imports do not overwrite different pictures. Reimporting an existing cached image keeps its source intact.
Graffiti Get Texture Path returns a stable identifier such as graffiti://<content-hash>.png for imported textures. Use that identifier for persistence. Picker FilePath outputs are resolved local cache paths for convenience. The identifier is preferable when saves move between machines or when the game's Saved root changes.
Imported files persist on disk until your game or the user removes them. The plugin does not automatically clean up image files when a decal is destroyed. If you move saves to another machine, transfer the required image cache too. Keep cache cleanup coordinated with your saved graffiti records.
Project texture assets can also be used. Their returned identifier is an Unreal object path. Ensure those assets are included in your packaged game's cook through normal project asset references or asset-management rules. Untracked transient textures and render targets have no persistent file identity; export/recreate them through your own system before expecting restoration after a restart.
5. SAVE AND RESTORE
Graffiti Applied Info contains Texture Path, final Spawn Location, final Spawn Rotation, Size, Rotation, Projection Depth, Surface Offset, and World Scale. Its fields support SaveGame serialization. Your game owns the save slot, record collection, and save/load timing.
For a fixed decal created through Apply Graffiti, save Out Graffiti Info in your own SaveGame data.
For actors returned by Graffiti Apply At Hit or Graffiti Restore From Info, call Get Graffiti Info immediately before saving. This snapshots the actor's current world location, rotation, and scale, including changes after attachment or movement.
Restore flow: Load your SaveGame -> iterate saved Graffiti Applied Info records -> Graffiti Restore From Info -> check Return Value -> store Out Actor if needed.
Restore uses the saved final transform directly, without applying rotation or surface offset a second time. It reloads imported images from graffiti:// identifiers, supported existing file paths, or available project texture object paths. A restored old absolute file path is converted to the current persistent identifier in the new actor's info.
Restore creates a world-space decal. Attachment relationships, custom material selection, remaining lifetime, pending delay, and effect arrays are not serialized in Graffiti Applied Info. Save any additional gameplay identifiers/settings yourself, pass your material override again, and restore attachment through your own actor/component references when required. Duration and Spawn Delay on the restore call start a new lifetime/delay.
Restore failure commonly means the cached image was deleted, a project texture was not cooked, or a record is invalid. Old records that contain only an Engine/Transient texture path cannot recover the original image; reimport it and save a new persistent record.
6. CUSTOM MATERIALS AND EFFECTS
The supplied material is /EasyGraffitiMaster/M_MasterMaterial and exposes a texture parameter named DecalTexture. It is referenced by the native actor so the cooker can include it. It projects image color and alpha, with UV orientation matched to the plugin's width/height convention.
Graffiti Apply At Hit and Graffiti Restore From Info accept Material Override and Texture Parameter. The override must use the Deferred Decal material domain and contain the specified texture parameter. The node rejects an unsuitable material or missing parameter instead of changing unrelated parameters.
For matching orientation in a custom material, the default graph samples using UV = (1 - TextureCoordinate.G, 1 - TextureCoordinate.R). You can duplicate the supplied material as a starting point for your own artistic behavior. The plugin sets only the named texture parameter; author other appearance settings in your material or material instance.
Apply Graffiti retains the optional Sound Array, Niagara Effects, and Cascade Effects pins. At reveal, it chooses one valid sound at random and spawns each valid Niagara/Cascade effect supplied. Leave the arrays empty for no effects. The existing-hit and restore nodes focus on placement; connect your own audio/FX logic when using them.
7. NODE REFERENCE
Apply Graffiti: camera trace or custom-transform placement; returns success and Graffiti Applied Info. Includes optional delay, duration, actor tags, debug trace, sounds, and effects. Graffiti Get Textures: Windows multi-image picker; returns cancellation state, loaded texture information, and resolved cache paths. Graffiti Load Texture From File: loads one supported file or graffiti:// identifier; returns texture or None. Graffiti Get Texture Path: returns a persistent imported-image identifier or project texture object path; empty for unsupported transient identity. Graffiti Apply At Hit: places from your blocking hit; supports an explicit material override and optional attachment; returns success and actor. Graffiti Restore From Info: restores a saved final transform and image; returns success and actor. Get Graffiti Info: actor function that snapshots current transform and image/settings for saving. Destroy Graffiti: actor function that removes a decal or cancels its pending reveal.
The last two nodes require a Graffiti Decal Actor reference. The other six are Blueprint function-library nodes in the Easy Graffiti Master category. All runtime API calls belong on the game thread. File selection is unavailable in commandlets, unattended runs, and dedicated servers; decal spawning is rejected on dedicated servers.
8. TROUBLESHOOTING AND PROJECT INTEGRATION
Nothing appears: - Check the node's Return Value and whether the texture is valid. - For tracing, check Visibility collision and the debug line. For supplied hits, check Blocking Hit and the component. - Check Receives Decals, the receiver's material/rendering configuration, projection orientation, and depth/offset. - Check Pending Spawn and Duration. A short lifetime may remove the decal quickly. - For custom materials, verify Deferred Decal domain and the exact texture parameter name.
An image fails to load: - Check the path and file access, supported image data, dimension/pixel limits, and available disk space. - If using graffiti://, retain the corresponding Saved/EasyGraffiti/Textures file. - Inspect the returned texture/array rather than treating Canceled false as proof that every image loaded.
Images overlap or painting becomes expensive: - Each call creates an actor. Limit your input repetition rate, active decal count, and image size. - Use Duration or stored actor references with Destroy Graffiti to control lifetime. - Adjust projection depth to reduce unwanted projection onto adjacent surfaces.
Multiplayer: Decals are local cosmetic actors. Automatic actor replication and network transfer of imported images are not provided. A multiplayer game must validate its own requests, distribute image data/identifiers, and invoke local placement or restore on the clients that should see the result. A graffiti:// identifier alone does not transfer its image bytes.
The plugin has no fixed input bindings or mandatory UI. Connect these nodes to your own widgets, controller input, interaction system, and SaveGame logic.
SUPPORT Discord: https://discord.gg/9Zc4wbwqG9