Skip to content

Repository files navigation

TileMap Plus

An LDtk-style 2D tile-map editor and runtime for Unreal Engine's Paper2D: rule/bitmask auto-tiling, exact-tile stamps, depth-parallaxed backgrounds, per-tile collision shapes, and native Box2D 2D physics for tile collision — in one plugin.

Built and tested against Unreal Engine 5.8.


Requirements

  • Unreal Engine 5.8. The .uplugin pins EngineVersion: 5.8.0; the plugin is built and tested against that version only.
  • Paper2D and ProceduralMeshComponent — both enabled automatically via the .uplugin's own Plugins list.
  • Windows (Win64) is the primary, fully supported platform. A Linux static Box2D library (Source/ThirdParty/Box2DLibrary/lib/Linux/libbox2d.a) is vendored alongside the Win64 one (lib/Win64/box2d.lib), so a Linux dedicated-server build links too. macOS and every other platform have no vendored library and are unsupported.
  • No PlatformAllowList, by design. TileMapPlus.uplugin declares none, so UBT will configure the whole plugin for whatever platform a host project targets. Rather than let an allowlist silently drop the plugin on an unsupported platform, Box2DLibrary.Build.cs fails the configure step loudly and by name for anything besides Win64 and Linux — a Mac target gets an explicit BuildException ("Box2D Mac library not provided — the Mac target is unsupported.") instead of a plugin that quietly isn't there.
  • A C++ project is required to build from source; this repository is not a Blueprint-only drop-in.

Install

From Fab — once listed, install through the Epic Games Launcher and enable TileMap Plus in Edit → Plugins.

From source — clone (or copy) into your project's Plugins/ directory:

YourProject/
  YourProject.uproject
  Plugins/
    TileMapPlus/

Right-click the .uprojectGenerate Visual Studio project files, then build.

Quick Start

  1. Create — Content Browser → AddTileMap Plus Asset, or open the asset editor's Map menu → Open Sample… to start from one of the bundled samples in Content/Samples instead.
  2. Paint — pick a tile set in the Palette tab, choose a brush from the toolbar (Paint, Rectangle Fill, Flood Fill, Random Scatter, Stamp, Eraser, Entity, Eyedropper, or Select), and paint on the active layer in the Viewport. Stack (Shift+T) isn't a brush — it's a toggle: turn it on and a paint click stacks tiles onto the cell instead of replacing them, and it coexists with whichever brush is active.
  3. Rules — open the Rule Editor tab, give a rule set a Mode (Off, Cardinal · 16, Blob · 47, or Full · 256) and a tile set, then assign tiles on the 3×3 neighbour grid. Add Missing creates one rule per uncovered pattern and the coverage counter tracks how much of the mode is defined. Stamps with Exact Tiles also work against an Off-mode rule set — the exact tile survives resolves even with no auto-tiling defined.
  4. Stamps — build a multi-cell arrangement once (a tree, a house, a fence) and place it in a single click with the Stamp brush. Give it Exact Tiles so every cell keeps its own authored art instead of resolving through the rule set.
  5. Layers — the Layers tab lists ordinary tile layers plus collapsible Auto-Layers and Backgrounds sections. A background gets its own Depth, so a perspective camera parallaxes it; both layers and backgrounds are fixed in the level's space unless you switch on their Enable Parallax.
  6. Collision — a layer's Collision Settings choose a Shape Source (Full Cell, or the tile set's own per-tile shapes authored in the Paper2D Tile Set editor) and a physics backend: Chaos, or native Box2D via the TileMapPlusBox2D adapter.

What it gives you

  • Rule/bitmask auto-tiling — Cardinal · 16, Blob · 47, or Full · 256 neighbour modes, with a Rule Editor that explains itself: a live result preview per rule, coverage reporting, Add Missing, and Sort by Pattern.
  • Stamps that carry exact tiles — a multi-cell prop is one named stamp; each cell can name its own tile-set tile instead of resolving through the rule set on every placement.
  • Parallax from depth, not scrolling — tile layers sit at their ZOffset, backgrounds at their own authored Depth, and a perspective camera turns depth into parallax; nothing scrolls by default, and the asset editor previews the same authoring pose the runtime uses.
  • Per-tile collision shapes — Full Cell, the Paper2D tile set's own authored shapes, or a fallback between the two; solid and one-way tiles partition before meshing so a mixed run never fuses into one box.
  • Native Box2D 2D physics — bodies, joints, movement, and queries backed by a vendored Box2D 3.2 (double-precision) static library, with a dedicated adapter that turns tile collision geometry into live Box2D bodies and keeps regeneration atomic.
  • LDtk and Tiled JSON import/export — selected-level LDtk import, including external .ldtkl files, cross-checked against the real format in LDtk Format Reference below.
  • Shared definitions across levels — promote a level's local rule/tile definitions into a shared container, with cook partitioning so one shared container doesn't drag every other level's art into every cook.
  • Optional replicated multiplayer — bounded, paged world-tile replication; authoritative Box2D puppets for co-op; and an additive client-prediction protocol layered on top. The replication types and the prediction protocol are implemented with source-level invariants and automation, documented in Documentation below; real net-driver verification (actual client/server sockets, not in-process fixtures) is still pending — see Predicted Box2D Movers: Causal Correction.
  • Runtime tile editing — edit tiles at runtime with atomic Box2D collision regeneration, so a failed replacement can't leave collision half-rebuilt.

Modules

Module Type Purpose
TileMapPlus Runtime The map asset, auto-tile resolution, tile animations, and physics-free collision-chain export. No Box2D dependency.
Box2DRuntime Runtime Box2D 3.2 bodies, shapes, joints, movement, and queries (BOX2DRUNTIME_API), absorbed in-tree from the standalone Box2D plugin.
TileMapPlusBox2D Runtime The adapter — turns a tile map's neutral collision geometry into live Box2D bodies.
TileMapPlusEditor Editor The asset editor (Viewport, Layers, Palette, Details, Rule Editor), the LDtk/Tiled importer, and the editor-side automation tests.
Box2DEditor Editor Box2D component visualizers and details customizations.

Box2DLibrary (Source/ThirdParty/Box2DLibrary) is the vendored External module — the static box2d.lib / libbox2d.a plus headers — that Box2DRuntime links privately. It is never listed in the .uplugin's own module array.

Documentation

One doc grounds LDtk interop against the real format; the rest are docs/solutions/ — one flat file per problem, each with a measured root cause, rejected approaches, and the test that pins the fix.

LDtk reference

Doc Covers
LDtk Format Reference Field-level reference for the LDtk project JSON format — identifiers, layers/tiles, IntGrid & auto-rules, tilesets, entities, versioning — cross-checked against the schema and real sample files.

Rendering, collision, editor & import

Doc Covers
Render Anchor & Parallax Reference Why rendered tiles, collision, and parallax all read from one lattice origin and one parallax reference.
Parallax Render-Graph Lifecycle One authored domain, one lifecycle-owned derived render/collision/entity graph, and generated-resource suspension.
Editor Interaction Foundation The brush/gesture/undo model behind painting, selection, and World Level Edit mode.
Cook Partitioning & Package Graph Selective cook partitioning so a shared definitions container doesn't drag every level's art into every cook.
Shared Definitions, Compatibility View & Promotion Promoting a level's local rule/tile definitions into a shared container without breaking self-contained assets.
LDtk Selected-Level Import Deterministic import of one selected LDtk world/level, including external .ldtkl files, with atomic failure.
Content-Demo Build/Cook/Package Proof Why content-bearing demos need editor, cook, package, and packaged-runtime proof as separate, non-substitutable gates.
Runtime Collision View & Atomic Box2D Regeneration Runtime tile edits and all-or-nothing Box2D collision regeneration.
TileMapPlus → Box2D Adapter Architecture How the TileMapPlusBox2D module turns tile-map collision geometry into live Box2D bodies.
Slate Viewport Zoom Anchor Offset Smooth zoom interpolation via anchor-point tracking in the 2D viewport.

Networking & replication

Doc Covers
World-Causal Tile Revisions Joining replicated cell state to logical, render, Chaos, and Box2D geometry under one causal barrier.
Bounded Paged Iris Replication Scaling tile-world replication past one FastArray with authenticated, paged Iris seals.
FastArray Prepared Publication Preparing a FastArray transaction without dirtying or renumbering the live replicated property.
Net Commit/Callback Barrier Publishing a prepared multi-map transaction atomically across callback-heavy UE collision APIs.
Net Wire Budget & Engine Sentinels Keeping a truthful manifest inside a wire budget, and two engine enum/name sentinels that break naive checks.
Network Physical-Parity Probe Coordinates Why a loss/late-join physics parity probe must use the published map geometry, not a hardcoded coordinate.
Network Request & Entity Boundaries Rate-limiting edit requests, and keeping server-authoritative entity spawn from overriding actor replication policy.
Replication Immutable Baseline & Worldless Assets Why the shared tile asset needs an immutable baseline and explicit worldless-asset locks.
Networking N0: Authority, Headless Truth & Schema Boundaries Process-authority (not actor-authority) gating, and why dedicated servers allocate no render state.
N1b Authoritative Box2D Puppets Delayed authoritative body/input streaming, possession epochs, and exactly-once cooked entity identity.
Predicted Box2D Movers: Causal Correction Client-side prediction, replay, and correction across network, physics-step, and world-mutation domains.
UE 5.7 FastArray Receive Batches What UE 5.7 actually calls on FastArray receipt, and draining tile edits at the physics-step boundary.

Box2D physics & determinism

Doc Covers
Box2D Audit Remediation & Pin Bump Closing record for the Box2D audit remediation: invariants, rejected approaches, measured failure fingerprints.
Contact Introspection & Orientation Asking "what is this body touching right now", receiver-relative, without reconstructing state from events.
Cross-Platform Determinism Closure Canonical math, canonical creation order, and a comparable determinism artifact across Win64/Linux.
Event Dispatch Safety Patterns Avoiding crashes when a collision-event handler destroys actors mid-broadcast.
Fixed-Tick Hook & One-Shot Input The one pre-step hook, input latching, and apply-once one-shot APIs that make movement frame-rate independent.
Headless & In-Engine Testing Driving FBox2DWorld and the full component stack in automation without a GUI.
Mover Landing Closure & Initial-Overlap Recovery Depenetrating a mover spawned inside geometry without stealing its authored travel.
Mover Step Replay & Module FP Semantics Why bUseUnity=false isn't a floating-point flag, and how UE 5.7 actually defaults MSVC module FP semantics.
Mover Toolkit PerformMovement The simultaneous-plane character-controller solve: mutable planes, command-safe stops, honest one-way stairs.
Mover Wrapper & Callback-Hybrid Query Combining identifiable overlap planes with an unidentifiable translation cast for CollideMover.
One-Way Platform Filtering Patterns Why pure velocity-based PreSolve filtering is unstable at rest and at shallow angles.
Ordered Pre-Step Phases Getting a causal ordering guarantee out of UE multicast delegates, without a second physics hook.
Production Readiness Patterns The PIE-validation hardening pass: event semantics, movement correctness, safety guards, diagnostics, editor tooling.
Render Interpolation, Two-Domain History Interpolating a transform that is simultaneously render output and a simulation input.
Shape Offsets Are Body-Frame Shape-component offsets are relative to the owning actor's pose, never the attach parent.
Surface-Material Identity & Chain Rebuild Versioned material identity so a chain rebuild preserves per-segment friction/restitution/conveyor data.
Chain-Cast Backport & Cross-Build Backporting an upstream one-sided-chain fix and cross-compiling for Linux without faking the target.
Vendored-Library Version Assessment (superseded) Historical v3.1.1-vs-upstream assessment; superseded by the 3.2.0-dev pin — kept for provenance.
World Tuning: Creation-Time Projection Validating b2WorldDef fields before the destructive world-recreate path can destroy a valid world.
XZ_YDown Plane & Conventions The Paper2D-aligned simulation plane and the one screen-space convention that makes every plane behave alike.
Feel Baseline Recordings Why a movement-feel refactor needs a recording made before the change, not a legacy-toggle comparison.

Build & testing infrastructure

Doc Covers
Fail-Closed Automation & Mutation Testing The house rules behind this repo's test suite — see Testing below.
RunUAT BuildPlugin Workflow Building a standalone plugin with no host .uproject, via RunUAT BuildPlugin or a junction link.
UBA OOM Kill-Loop Diagnosing a build that livelocks at zero completed actions on a memory- and disk-constrained machine.
UMovementComponent Base-Class Pitfalls UPROPERTY shadowing and virtual-hiding traps when deriving from UMovementComponent.
Game-Target PCH Missing Includes Why code compiles in the Editor target and fails in the Game target with "use of undefined type".
Transactional Reconcile / Probe / Friend-Link Traps Three MSVC/linker traps from a backup-first reconcile coordinator: probes, anonymous-namespace friends, incremental links.
TWeakObjectPtr Blueprint Limitation UHT rejects TWeakObjectPtr inside a BlueprintReadWrite UPROPERTY.
UE 5.8 Engine-Behavior Migration Traps Four engine/environment behavior changes the first full UE 5.8 suite run surfaced, unrelated to the branch under test.
One Persistent UE 5.8 Host Why the maintainers' automation runs against one reused host project instead of a disposable one per run.

Testing

Automation tests live beside the code they cover, one .cpp per test file under each module's Private/Tests/ folder, registered with IMPLEMENT_SIMPLE_AUTOMATION_TEST / IMPLEMENT_COMPLEX_AUTOMATION_TEST. Test names are dotted paths that group into three prefixes:

Prefix Covers
TileMapPlus 143 tests: the rule engine and multi-world layout under the plain TileMapPlus.* namespace (Source/TileMapPlus/Private/Tests), plus every TileMapPlusBox2D.* adapter test the prefix also matches as a plain string (Source/TileMapPlusBox2D/Private/Tests and the legacy-replication fixtures in Source/TileMapPlusEditor/Private/Tests).
Box2D 243 tests: the Box2D physics plugin itself — bodies, joints, queries, movement, networking (Source/Box2DRuntime/Private/Tests, Source/Box2DEditor/Private/Tests, and Source/TileMapPlusEditor/Private/Tests/Box2DEditorLifecycleTest.cpp).
Paper2DPlus 521 tests under the historical Paper2DPlus.TileMapPlus.* / Paper2DPlus.Box2D.* namespaces — disjoint from the other two prefixes, retained from before the tile-map half was split out of the Paper2DPlus plugin, and still holding the bulk of the importer, asset, replication, and Box2D suites.

All three prefixes are required for full coverage — none of them subsumes another. Run the suite headlessly with UnrealEditor-Cmd, filtering by prefix (StartsWith: can be chained with + to run several prefixes in one pass):

"<EngineRoot>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "<YourProject>.uproject" ^
  -ExecCmds="Automation RunTests StartsWith:TileMapPlus+StartsWith:Box2D+StartsWith:Paper2DPlus" ^
  -TestExit="Automation Test Queue Empty" -unattended -nopause -nosplash -nullrhi ^
  -ReportExportPath="<OutputDir>"

<OutputDir>/index.json reports the pass/fail/skip counts. scripts/run-tests.ps1 is the maintainers' own wrapper around this same three-prefix run, built and pointed at their persistent development host — it is not a portable entry point for a plugin consumer, but its default -TestFilters @('Paper2DPlus', 'TileMapPlus', 'Box2D') is exactly the prefix set above.

A handful of tests are manual/opt-in rather than acceptance: Manual.AssetAuthoring.* regenerates committed test fixtures and requires an explicit flag (-TileMapPlusBuildCookCorpus or -TileMapPlusBuildSamples) — it is not part of an ordinary run and will fail closed without that flag.

License

MIT — see LICENSE. You may use, modify, and redistribute this source, including commercially, provided the copyright notice is retained.

The vendored Box2D library is separately MIT-licensed by Erin Catto; see THIRD_PARTY_NOTICES.md for the vendored-library accounting, or its own LICENSE and NOTICE directly.

See CHANGELOG.md for release history.

Support

Built by Infinite Gameworks.

About

TileMap Plus for Unreal Engine 5.8 Paper2D: tile-map editing with rule/bitmask auto-tiling, exact-tile stamps, depth-based parallax layers and Box2D-backed tile collision. MIT.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages