Wiki

Learn how to optimize your Spine 2D animations, reduce file size, and improve performance

beginnerchartsconceptsconnectionscontrolsdatafpsguidelosslesslossymemorymetricsoptimizationperformancepluspremiumpricingresultssocketsstatisticssubscriptiontabletypesuiviewerworkflow

Getting Started: Basic Workflow

beginnerworkflowguide

This guide will help you get started quickly with the JSON Optimizer.

  1. Load Project: Use the InputNode to load your .json, .atlas, and .png files.
  2. Choose a preset (Plus mode): In Plus mode, use the right panel to select one of the built-in presets (e.g., "Basic Fallback"). This automatically builds an optimization graph for you. In Free mode, build a minimal manual graph: InputNode β†’ QuantizerNode β†’ OutputNode.
  3. Run the graph: Click the "Run Graph" button.
  4. Compare results: Switch to the "Viewer" tab to visually compare the original and optimized animations.
  5. Review changes: In the "Results" and "Statistics" tabs, you will find detailed information about which keys were modified or deleted.

Socket Types & Data Flow

socketstypesdataconnections

This article explains the data types used by sockets in the node graph and what can be connected where.

Quick rule

Most processing nodes operate on a Spine Payload. Atlas-related nodes operate on an Atlas Project or Sprites. Use ValidatorNode when you’re unsure what a socket expects.

Socket types

  • Spine Payload β€” runtime-friendly representation of the Spine project used by most processing nodes.
  • Atlas Project β€” atlas metadata + page images used by atlas nodes.
  • Sprites β€” unpacked sprite images/regions (Atlas Unpacker β†’ Asset Viewer / Atlas Repacker).
  • JSON β€” original or reconstructed Spine JSON for diagnostics/validation/diffing.
  • Changes β€” a list/stream of diffs produced by some optimizers and used by viewer/reporting nodes.

Key β†’ type β†’ connect to

Socket key (examples)Data typeProduced byConnect to
payload, payload_in, payload_outSpine PayloadInputNode, most processing nodesProcessing nodes (RDP/Spline/Refit/Quantizer/Cleanup/etc.), then OutputNode.payload
original_jsonJSONInputNodeDiagnosticNode, JSONDiffNode.json_before, OutputNode.original_json, some atlas nodes (e.g. repacker alpha mode)
reconstructed_json_outJSONOutputNodeJSONDiffNode.json_after, validators/debug
changesChanges listSome processing nodes + OutputNodeAnimationViewerNode (optional), reports/debug
atlas_projectAtlas ProjectInputNode / atlas viewerAtlasUnpackerNode.atlas_project, OutputNode.atlas_project, atlas filters
atlas_in, atlas_outAtlas Project (or atlas-related stream)Atlas nodes / filtersAtlas nodes, AtlasViewerNode, AtlasMergerNode (via its multi-input)
sprites_out, sprites_in, sprites_data_inSpritesAtlasUnpackerNode, filtersAssetViewerNode.sprites_in, AtlasRepackerNode.sprites_data_in
atlas_inputsMultiple Atlas ProjectsMultiple sourcesAtlasMergerNode.atlas_inputs (connect several atlases)

Practical pipelines

  • Basic JSON optimization: InputNode β†’ (optional: DiagnosticNode / filters) β†’ optimizers (RDPNode, SplineNode, QuantizerNode, …) β†’ OutputNode.
  • Atlas repacking: InputNode.atlas_project β†’ AtlasUnpackerNode β†’ (optional: AssetViewerNode) β†’ AtlasRepackerNode β†’ OutputNode.atlas_project/atlas_assets.

Subscription Plans & Premium Features

subscriptionpremiumpluspricing

re-polish offers two subscription tiers to fit different needs.

Free Plan

  • βœ“ Basic Node Graph
  • βœ“ JSON Viewer
  • βœ“ Limited Optimizations
  • βœ“ Community Support

Plus Plan ($5/month)

  • βœ“ All Free Features
  • βœ“ Optimization toolkit covering keys, curves, and textures
  • βœ“ Bake physics into keyframes
  • βœ“ Clean baked keys into curves
  • βœ“ Graph Presets
  • βœ“ Priority Support

Getting Plus

Click the Upgrade button in the top navigation, then:

  • Select Get Plus
  • You’ll be redirected to Patreon β€” complete the subscription
  • Return to the node editor while logged into the same Patreon account so the service can verify the link and enable Plus
  • (Optional) Enter an activation code (for special offers)

Core Concepts: Lossy vs. Lossless

conceptslossylosslessbeginner

All optimization methods are divided into two types:

Recommendation: Always start with Lossless optimizations. Use Lossy methods only when further file size reduction is required, and always check the result visually.

How to Measure Effectiveness

guidemetricsstatistics

To understand how effective your optimization is, pay attention to the following metrics:

  • File Size: The final size of the .json file is the main goal of optimization.
  • Keyframe Count: In the "Statistics" tab, you will find tables and charts showing how many keyframes were removed in each animation.
  • Visual Comparison: Always use the "Viewer" tab to compare the "before" and "after" animations. Ensure that Lossy optimizations have not introduced unacceptable visual artifacts.
  • Report in the "Results" Table: Here you can examine in detail every specific change that was made to your data.

Viewer: Controls Panel

viewercontrolsui

The Viewer tab overlays a Controls panel on top of the canvas. It’s split into three groups:

Animation Controls

  • Animation β€” selects which Spine animation is playing.
  • Skin β€” selects which Skin is applied.
  • Speed β€” playback speed multiplier (0.1Γ— β†’ 3.0Γ—).

View Controls

  • Reset View β€” restores default camera/layout positioning.
  • View Options β€” numeric offsets used to position the comparison view: Spacing X / Spacing Y (distance between original/optimized) and Offset X / Offset Y (global shift).

Debug Controls

  • Debug Mode β€” enables debug rendering overlays (depends on runtime support).
  • Enable Physics β€” toggles physics simulation (if the skeleton uses physics).
  • Labels β€” toggles labels overlay.

Viewer: Performance Panel

performancefpsmemoryui

The Performance panel shows real-time runtime metrics for the currently playing skeleton(s).

Real-time

  • FPS β€” frames per second measured by the monitor.
  • Frame Time β€” time per frame in milliseconds (lower is better).
  • FPS chart β€” last 120 samples displayed as bars.

Skeleton metrics

  • Visible Slots β€” how many slots were visible on the last sample.
  • Avg. Visible β€” rolling average of visible slots (more stable than a single frame).
  • Vertices β€” current vertex count used for rendering.
  • Bounds (px) β€” current skeleton bounds widthΓ—height in pixels.
  • Avg. Bounds β€” rolling average bounds.
  • Largest Texture β€” the largest atlas page (by dimensions) detected for the skeleton.
  • Texture Memory β€” estimated total texture memory for loaded atlas pages. When available, the panel also shows a per-page breakdown (file name, dimensions, and estimated size).

Improvements (when Optimized is available)

  • Slot Improvement β€” compares Avg. Visible between Original vs Optimized.
  • Memory Change β€” compares Texture Memory between Original vs Optimized.

Results Tab

resultstableoptimization

The Results tab shows detailed optimization output.

  • Results table β€” a row-per-change view of JSON optimization results (e.g. which animation/bone/property/keyframe was modified or removed).
  • Sprite/Atlas comparison β€” when texture optimization is used, this section compares sprite sizes and packing outcomes.

Tip: use the Results view to answer: what exactly changed?

Statistics Tab

statisticschartsmetrics

The Statistics tab summarizes optimization results as charts and aggregated metrics.

  • Optimization Chart β€” visualizes optimization impact over the dataset (when JSON optimizations produced changes).
  • Metrics Table β€” key numbers such as original/new sizes and reduction percent.
  • Texture Packing Statistics β€” if atlas repacking was used, shows pages, total/used area, efficiency, and a per-page breakdown.

Use this tab to answer: how much did we improve overall?

Nodes

Input

Loads a complete Spine project (.json, .atlas, .png) and prepares it for the processing pipeline.

Purpose: This is the mandatory starting point for any graph. It validates the project files and outputs multiple data streams for processing.

Outputs:
- **payload**: Structured representation of animation data, optimized for processing by other nodes.
- **atlas_project**: Data related to the texture atlas, for use with unpacker and repacker nodes.
- **original_json**: Original, unmodified JSON data for reference or comparison.

Socket keys: payload, atlas_project, original_json

Output

Final node in the graph that exports optimized data and prepares it for download.

Purpose: Gathers all optimization results and generates the final Spine project files.

Inputs:
- **payload**: Optimized payload
- **original_json**: Original JSON passthrough for reference
- **atlas_project**: Optional atlas project (e.g., repacked)

Outputs:
- **reconstructed_json_out**: Rebuilt Spine JSON
- **original_json_passthrough_out**: Original JSON passthrough
- **payload_out**: Payload passthrough for chaining
- **changes**: Collected optimization changes
- **atlas_assets**: Atlas assets for export

Socket keys: payload, original_json, atlas_project, reconstructed_json_out, original_json_passthrough_out, payload_out, changes, atlas_assets

RDP

Simplifies animation curves using the Ramer-Douglas-Peucker (RDP) algorithm.

Purpose: Reduces the number of keyframes in linear or near-linear animation segments by removing points that lie on a straight line between two others.

Socket keys: payload_in, payload_out, changes

Spline

Fits smooth spline curves to animation keyframes, reducing unnecessary intermediate points.

Purpose: Smooth curve fitting while maintaining visual quality.

Socket keys: payload_in, payload_out, changes

Refit

Approximates dense keyframe sequences with fewer Bezier curves to reduce size.

Purpose: Fits fewer curves while staying within a tolerance.

Socket keys: payload_in, payload_out, changes

Quantizer

Reduces precision of numeric values in keyframes and curves.

Purpose: Simple but effective way to reduce file size by rounding numbers to a specified number of decimal places.

Usage: Can be applied to almost any animation data. Becomes more effective with higher keyframe counts.

Caution: Too aggressive quantization (low precision) can cause jitter or visual artifacts in animations.

Socket keys: payload_in, payload_out, changes

Cleanup

Performs various cleanup tasks to remove redundant or unnecessary animation data.

Purpose: Specialized tool for removing specific types of redundant data that other optimizers might miss.

Usage: Connect your payload to 'payload_in' and take the result from 'payload_out'. If you want a per-change report, also use 'changes'.

Socket keys:
- Inputs: payload_in
- Outputs: payload_out, changes

Currently supported cleanups:
1. **Remove Unused Color/Alpha Tracks**: Removes color/alpha timelines for slots that are never visible during the animation.
2. **Remove Redundant IK Rotations**: Removes rotation keyframes from bones that are fully controlled by an IK constraint with 100% mix.
3. **Remove Path Constraint Keys**: Removes rotate/translate keyframes from bones fully controlled by a path constraint (mix values at 100%).
4. **Sanitize Non-English Characters**: Replaces non-English characters in names/identifiers to avoid issues in downstream tools.

Scale

Scales all numeric values in animation keyframes by a specified factor.

Purpose: Uniformly scales animation data, useful for resizing skeleton proportionally or adjusting animation intensity.

Usage: Connect **payload_in** and take the result from **payload_out**.

Socket keys: payload_in, payload_out

Schneider

Fits smooth Bezier curves to animation keyframes using the Schneider curve fitting algorithm.

Purpose: Advanced curve fitting that produces natural-looking Bezier curves from dense keyframe sequences.

Availability: **Plus-only node**.

How it works: The Schneider algorithm analyzes keyframe positions and tangents to generate optimal Bezier control points that closely match the original motion.

Parameters:
- **Error Tolerance**: Maximum allowed deviation from original keyframes. Lower = more accurate, higher = smoother curves.
- **Corner Angle**: Threshold angle (degrees) at which to split curve into segments.

Best for:
- Hand-drawn or imported animations with many keyframes
- Converting linear interpolation to smooth Bezier curves
- Reducing keyframe count while maintaining curve quality

Note: More computationally intensive than simpler algorithms like RDP, but produces superior curve quality.

Socket keys: payload_in, payload_out, changes

Physics Constraint Bake

Bakes Spine PhysicsConstraint motion into bone rotate/translate keyframes and removes physics timelines.

Purpose: Converts runtime physics simulation into explicit keyframes so animations are deterministic and editable without physics constraints. After bake, physics constraints and physics timelines are removed from the payload.

Availability: **Plus-only node**.

Inputs/Outputs:
- **payload_in** β†’ **payload_out** (baked)
- **changes** (optional change list)

Controls:
- **Sample FPS**: Simulation sampling rate for the bake.
- **Bake Rotation**: Write baked rotation keys.
- **Bake Translation**: Write baked translation keys.
- **Bake Translation (Children)**: Apply translate bake to child bones that rely on physics motion.

Notes:
- Requires original Spine JSON to reconstruct simulation data.
- Use when you want to remove physics constraints but keep the motion.

Attachment Visibility

Optimizes rendering by setting a slot's attachment to null when its alpha is zero.

Purpose: Prevents the game engine from having to process or render invisible attachments.

Usage: Processes **payload_in**, outputs optimized **payload_out**, and optionally reports **changes**.

Socket keys: payload_in, payload_out, changes

Payload Merger

Merges multiple processed animation payloads back into a single unified payload.

Purpose: Essential for parallel processing pipelines where different animations or bone groups are optimized separately and need to be recombined.

Inputs:
- **base**: Master payload (skeleton structure)
- **overrides**: One or more payloads whose tracks replace base tracks

Output:
- **merged_out**: Merged payload

Socket keys: base, overrides, merged_out

Animation Viewer

Visual tool for inspecting and comparing animation curves before and after optimization.

Purpose: Provides graphical representation of keyframes and curves for selected track.

Usage: Connect **before_in** and **after_in** to overlay original vs optimized. Optionally connect **changes** to highlight impacted tracks.

Socket keys: before_in, after_in, changes

Animation Filter

Filters animation tracks based on animation name (e.g., 'run', 'idle').

Purpose: Useful for applying different optimization strategies to different animations.

Usage: Filters **payload_in** into **payload_out** and exposes **animation_list** for UI selection.

Socket keys: payload_in, payload_out, animation_list

Asset Filter

Filters atlas assets by name, works in two modes: before unpacker (filters atlas text) or after unpacker (filters sprites).

Purpose: Controls which assets are included in the workflow - either which assets to unpack from atlas, or which unpacked sprites to include in repacking.

Inputs/Outputs:
- Atlas mode: **atlas_in** β†’ **atlas_out**
- Sprites mode: **sprites_in** β†’ **sprites_out**

Socket keys: atlas_in, atlas_out, sprites_in, sprites_out

Bone Filter

Filters bone animation tracks based on bone name.

Purpose: Allows targeting or excluding specific bones from the optimization process.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Skin Filter

Filters animation and asset data based on skin names.

Purpose: Process only specific skins from a multi-skin Spine project.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Slot Filter

Filters slot animation tracks based on slot name.

Purpose: Useful for targeting or excluding specific slots that may have special timing or visibility requirements.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Parameter Filter

Filters animation tracks based on their property type (e.g., rotation, scale, color).

Purpose: Allows applying subsequent optimizations only to specific types of animation data.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Atlas Unpacker

Extracts individual sprites from a Spine texture atlas.

Purpose: Breaks down an atlas file into its component sprites, allowing for individual analysis or repacking.

Usage: Connect **atlas_project** from InputNode to **atlas_project** (or the legacy **atlas_project_in**) on this node. Optionally connect **skeleton_json_in** (from InputNode's **original_json**) to enable mesh-aware cropping (trims sprites to mesh hull bounds instead of rectangular bounds, which can significantly reduce texture memory for mesh attachments).

Outputs:
- **sprites_out**: Standardized sprites array (for viewer/repacker)
- **sprites_data_out**: Extracted sprite images/metadata (structured bundle)
- **atlas_out**: Atlas project passthrough

Socket keys: atlas_project, atlas_project_in, skeleton_json_in, sprites_out, sprites_data_out, atlas_out

Atlas Repacker

Repacks individual sprites into one or more new, optimized texture atlases.

Purpose: Optimizes texture memory and potentially reduces draw calls by creating efficient sprite sheets.

Usage: Accepts sprites either via **sprites_data_in** (structured sprites bundle) or via **sprites_out** (standardized sprites array). If needed for alpha handling / polygon packing, provide the original skeleton via **original_json**. Outputs a packed atlas as **atlas_out**.

Socket keys: sprites_data_in, sprites_out, original_json, atlas_out

Atlas Viewer

Lightweight atlas visualization and analysis tool for inspecting atlas structure before unpacking.

Purpose: Provides a fast way to preview atlas pages and regions without performing the heavy unpacking operation. Helps validate atlas structure and identify unused regions.

Usage: Connect an atlas project to **atlas_project** (or legacy **atlas_in** / **atlas**). Optionally connect skeleton JSON to **json** for usage analysis.

Socket keys: atlas_project, atlas_in, atlas, json

Atlas Merger

Combines multiple atlas sources into a single unified atlas.

Purpose: Merge multiple atlas projects into one.

Input:
- **atlas_inputs**: Multi-input array of atlas projects

Outputs:
- **atlas_out**: Merged atlas project
- **merged_out**: Legacy merged output
- **merged_atlas_out**: Legacy merged output

Socket keys: atlas_inputs, atlas_out, merged_out, merged_atlas_out

Asset Viewer

Displays individual sprites from an unpacked atlas.

Purpose: Visual debugging tool for atlas manipulation.

Usage: Accepts sprites via **sprites_out** (standard) or legacy **sprites_in** / **sprites_data**.

Socket keys: sprites_out, sprites_in, sprites_data