Sprite Shaders Animated — 2D
128 combinable shader effects for sprites, UI, and particles — with SDF outlines, a built-in animation system, runtime API, effect presets, and SRP batching. Works on Built-in, URP, and HDRP out of the box.
Leafo Studio
Made by leafousio — YouTuber, game developer, and asset creator.
Developer of Xenophobia, Rocky Path, Mark in Space.
Try 120+ basic effects
First Steps 🚀
-
Import the package
Drag the .unitypackage into your project. Everything lives under
Assets/AnimatedSprite/. -
Add the component
Select a SpriteRenderer, click Add Component → Animated Sprite Shader. The correct shader variant is auto-assigned based on your render pipeline.
-
Turn on effects
Open any category section, tick an effect, and tweak its sliders. That's it — no materials to create, no prefabs to set up.
Render Pipelines ⚙
Every shader variant ships for all three pipelines. Pick the right one and you're good to go. Open Master Setup (Window → Animated Sprite → Master Setup) to set your active pipeline — it patches all .shader files with the correct #define and configures the batching strategy.
All 17 Shader Variants
All 128 Effects ✦
Every effect listed below with a short description of what it does and what it's best used for. The colored dot next to each name shows its performance class: ● lightweight ● moderate ● heavy.
Color
36Edge
14UV / Distortion
28Dissolve / Fade
19Special Effects
31Inspector 🔧
The custom inspector auto-generates UI for all 128 effects from the central registry. No manual wiring — if it's in the registry, it shows up.
Search
Type any effect name, keyword, or category to instantly filter the list down.
Perf Dots
Green / yellow / red dot next to every effect shows its GPU cost at a glance.
Keyframe Buttons
Click ♫ next to any float, color, or vector to open the one-click keyframe editor.
Code Gen
Click C# on any effect (or the global button) to copy ready-to-paste setup code to your clipboard.
Copy / Paste / Reset
Copy an effect's settings, paste them onto another sprite, or reset to defaults. Per-effect.
Live Preview
96px preview thumbnail next to each expanded effect updates in real-time as you tweak sliders.
Outline Modes & SDF ◻
All outline and edge effects share a configurable sampling mode. Pick the one that fits your quality/performance needs.
| Mode | How It Works | Best For |
|---|---|---|
| Classic 3×3 ● Fast | Samples 8 neighbors at the given size. Simple and cheap. | Low-res sprites, mobile, large batches. |
| Multi-Ring ● Moderate | Samples 8 directions × N rings for smoother, rounder outlines. | Mid-res sprites, configurable quality via ring count. |
| SDF ● Fast | Pre-baked signed distance field. Single texture sample per pixel. Smooth at any width. | High-quality outlines, glow, any resolution. Best visual quality. |
SDF Baking
Click Bake SDF Texture in the Edge Effects section to generate a float-precision signed distance field from your sprite. The bake uses the Jump Flood Algorithm and produces a 32-bit float .exr texture — 0.5 = sprite edge, above 0.5 = inside, below 0.5 = outside.
Full Rect so outlines can extend beyond the sprite bounds. Tight meshes will clip SDF outlines.Tools 🛠
Quick actions right from the inspector — no digging through menus.
| Tool | What it does |
|---|---|
| Deactivate All | Turns off every effect at once. Clean slate. |
| Apply Children | Copies the shared material to all child renderers. |
| Atlas Setup | Reads sprite UV bounds from the atlas so edge effects stay within bounds. |
| Bake PNG | Renders the sprite with all active effects into a PNG (1×, 2×, or 4× resolution). |
| Bake SDF | Generates a signed distance field texture (32-bit float EXR) for SDF outline mode. |
| Pack Masks | Combines up to 4 grayscale masks into a single RGBA texture. |
| Setup Animator | Adds an Animator component and opens the Animation window. |
| Save / Load Preset | Save all effect settings as a ScriptableObject. Load it onto any other sprite. |
| Copy All Active (C#) | Generates and copies C# code for every currently enabled effect's settings. |
Effect Masks 🎭
Assign up to 4 grayscale textures as mask channels (R, G, B, A). They auto-pack into a single RGBA texture. Each effect can target a specific channel through the colored buttons below its parameters.
packedMasks and sent to the shader as a single sample. There's also a global Effect Mask texture that affects all effects at once.Global Settings 🌐
| Setting | Description |
|---|---|
| Effect Fade | Master fade for all effects (0 = none, 1 = full). |
| Edge Cleanup | Snaps semi-transparent edge pixels to fully opaque or transparent. Kills dirty edges on pixel art. |
| Alpha Cutoff | Hard alpha threshold for transparency. Pixels below the cutoff become invisible. |
| Effect Mask | Global mask texture affecting all effects simultaneously. |
| Pixel Art Snap | Snaps effect coordinates to a pixel grid — preserves crispness on low-res sprites. |
| Premultiplied Alpha | Premultiplies RGB by alpha in the final output. Required by some blend modes and Canvas UI. |
| Flip X / Flip Y | Mirrors the UV space. Auto-Detect button reads the SpriteRenderer's flip state. |
| Time Scale | Speed multiplier for all animated effects. |
| Time FPS | Caps animation to a specific frame rate (0 = unlimited). Great for retro looks. |
| Custom Time | Replace Unity time with a manual value. Useful for pausing or scrubbing effects. |
| UV Expand | Expands the vertex quad outward so edge effects like outlines and glow render outside sprite bounds. |
| Stencil Buffer | Full stencil control: ref, compare, pass, read/write masks. Useful for X-Ray Silhouette setups. |
| Shadows | Cast/receive shadows and shadow alpha clip threshold (3D Lit variants only). |
Performance ⚡
Every effect has a performance class shown as a colored dot in the inspector.
| Level | Meaning | Examples |
|---|---|---|
| ● Lightweight | Small math ops, no texture lookups | Strong Tint, Hit Effect, Negative, Brightness, Flicker |
| ● Moderate | A couple of cheap texture samples | Outline, UV Distort, Chromatic, Dissolve, Shine |
| ● Heavy | Multiple samples + heavy math | Bloom, Gaussian Blur, Soft Shadow, Ghosting, Motion Smear |
shader_feature_local — Unity's compiler strips unused variants at build time. For maximum mobile performance, stick to green-dot effects and use Bake PNG to flatten complex setups into a single texture.Sampler Packing
20 effect textures share 8 samplers to stay within mobile/DX11/OpenGL limits. Effects with similar sampling needs (linear clamp vs. linear repeat) are grouped onto shared samplers. You don't need to configure anything — it's automatic.
Animation System ♫
Every property is animatable through Unity's Animation window. The built-in keyframe editor generates curves without touching the timeline manually.
One-Click Keyframes
Click ♫ next to any property to open the editor with From / Mid / To values and easing curves.
Mid-Point Curves
Toggle mid-point for smooth loops (dim → bright → dim). Two-segment curve with independent easing.
Clip Picker
Add curves to any AnimationClip from a dropdown, or target the currently active clip in the Animation window.
Keyframe Editor 🎹
Click ♫ next to any float, color, or vector property to open it.
| Field | Description |
|---|---|
| From / Mid / To | Start, optional midpoint, and end values. Mid creates a smooth two-segment loop. |
| Duration | 0.05 – 10 seconds. |
| Easing | Linear, Ease In, Ease Out, Ease In-Out, Bounce, Elastic. |
| Bake FPS | Keyframes per second baked into the curve (12 – 60). |
| Loop / Ping Pong | Whether the clip loops and bounces (from→to→from). |
Animation Browser 📂
In the Tools section — shows all clips in the Animator Controller, lists animated shader properties with their value ranges. Click Open to jump to that clip in the Animation window.
C# Scripting API { }
Every effect can be enabled, configured, and animated from code. All public fields on AnimatedSpriteShader are yours to set.
Enable / Disable
var mgr = GetComponent<AnimatedSpriteShader>(); mgr.outlineEnabled = true; mgr.outlineColor = Color.cyan; mgr.outlineSize = 0.02f; mgr.dissolveEnabled = true; mgr.dissolveAmount = 0.5f; mgr.MarkDirty(); // always call after changing values from code
Switch Shader Variant
mgr.ChangeShaderVariant(AnimatedSpriteShader.ShaderVariant.Lit2D_URP);
Incremental Push
// Mark only what changed — avoids pushing all 128 effects every frame mgr.MarkEffectDirty(EffectId.Dissolve); mgr.MarkGlobalsDirty(); mgr.IncrementalPush(); // pushes only dirty groups to the GPU
MarkDirty() marks everything dirty and pushes on the next LateUpdate. For tighter control, use MarkEffectDirty(id) + IncrementalPush() to only push the groups that actually changed.Combo Examples 🎨
mgr.frozenEnabled = true; mgr.frozenContrast = 2f; mgr.frozenHighlight = 1.5f; mgr.outlineEnabled = true; mgr.outlineColor = new Color(0.5f, 0.85f, 1f); mgr.outlineSize = 0.015f; mgr.hexDissolveEnabled = true; mgr.hexDissolveAmount = 0f; // animate 0→1 to shatter mgr.MarkDirty();
mgr.holographicCardEnabled = true; mgr.shineEnabled = true; mgr.shineWidth = 0.15f; mgr.shineGlow = 2f; mgr.outlineEnabled = true; mgr.outlineColor = Color.white; mgr.outlineSize = 0.008f; mgr.MarkDirty();
mgr.hitEffectEnabled = true; mgr.hitEffectColor = Color.white; mgr.hitEffectBlend = 1f; mgr.wiggleEnabled = true; mgr.wiggleAmount = 0.05f; mgr.wiggleFrequency = 25f; mgr.MarkDirty(); // Then lerp hitEffectBlend and wiggleAmount back to 0 over ~0.15s
Effect Presets 💾
Save any sprite's complete effect setup as a ScriptableObject and load it onto other sprites. The preset stores every enabled effect plus all its parameters.
var preset = Resources.Load<AnimSpriteEffectPreset>("MyPreset"); preset.ApplyTo(mgr); mgr.MarkDirty();
Architecture 🧠
Understanding how the pieces fit together helps when extending the system or debugging edge cases.
EffectRegistry.cs
Static array of EffectDef structs. The single source of truth — maps each effect's ID, keyword, C# field name, shader property name, category, group, and parameter metadata.
AnimatedSpriteShader.cs
Runtime MonoBehaviour. Holds all 128 effect fields. Pushes values to the GPU via MaterialPropertyBlock. Handles SDF baking, atlas setup, variant switching, and incremental dirty tracking.
AnimatedSpriteShaderEditor.cs
Custom inspector. Reads the registry to auto-generate UI: categories, search, perf dots, sliders, keyframe buttons, code-gen, copy/paste, and live previews.
AllInOneProperties.hlsl
Declares every shader property, texture sampler, and _En toggle float. 20 textures share 8 samplers via aliasing. Shared across all 17 variants.
AllInOneKeywords.hlsl
All shader_feature_local pragmas. One keyword per effect — Unity strips unused ones at build time, so disabled effects cost exactly zero.
AllInOneEffects.hlsl
The effect pipeline. Functions organized as: UV → Color → Edge → Dissolve → VFX → Gameplay. Each wrapped in #ifdef blocks.
AnimSpriteMasterSetup.cs
Editor window for project-wide settings: active pipeline, shader patching, keyword mode, effect group ordering, and pipeline migration tools.
AnimSpriteProjectSettings.cs
ScriptableObject singleton storing the active pipeline, group render order, and per-group effect ordering. Shared between Master Setup and the editor.
ShaderPropertyAnimator.cs
Drives the ♫ keyframe editor. Bakes AnimationCurves with configurable easing, mid-points, and ping-pong loops. Writes directly to AnimationClips.
Shader Internals ⚙
The fragment shader processes effects in a strict order inside the dispatch groups:
// 1. UV effects (wave, twist, distort, pixelate, scroll…) uv = ApplyUVGroup(uv, time, worldPos); // 2. Sample main texture + edge cleanup half4 col = STEX(_MainTex, sampler_MainTex, uv); // 3. Filter effects (sharpen, blur, flipbook blend…) col = ApplyFilterGroup(col, uv, time); // 4. Color effects (tint, bloom, hue, posterize…) col = ApplyColorGroup(col, uv, time, worldPos); // 5. Extended color (gradient, radial gradient, color ramp…) col = ApplyColorExtGroup(col, uv, time); // 6. Edge effects (outline, glow, shadow, rim…) col = ApplyEdgeGroup(col, uv, time, masks); // 7. Dissolve effects (fade, wipe, dissolve…) col = ApplyDissolveGroup(col, uv, time, masks); // 8. VFX effects (hologram, glitch, shine, flame…) col = ApplyVFXGroup(col, uv, time, masks); // 9. Gameplay effects (health tint, x-ray, trails…) col = ApplyGameGroup(col, uv, time, masks);
Each effect block checks its _En float, optionally samples the effect mask, computes the effect, and composites via lerp or alpha blending. The order within each group is configurable through Master Setup.
SDF Pipeline ◈
The SDF system uses a signed distance field for outline and glow rendering. Here's how it works end-to-end.
Bake Process (C#)
BakeOutlineSDF() reads the sprite's texture rect, pads it by a configurable amount (default 16px), and computes inner + outer distance fields using the Jump Flood Algorithm. The result is a signed distance normalized into [0, 1]:
signedDist = isSolid ? -innerDist : outerDist; normalized = 0.5 - signedDist / (2 * spread);
Output is a 32-bit float RFloat texture saved as .exr — smooth gradients without banding. The spread value is stored on the component and pushed to the shader as _OutlineSDFSpread.
Outline Band Extraction (Shader)
The outline is carved from two one-sided smoothsteps to prevent overlap at small widths:
sdfWidth = sizePx / (spread * 2); outerEdge = 0.5 - sdfWidth; outer = smoothstep(outerEdge - softness, outerEdge, sdf); inner = smoothstep(0.5, 0.5 + softness, sdf); outline = outer * (1.0 - inner);
This avoids the classic "surge at zero width" bug where symmetric smoothsteps overlap at their tails.
Adding a Custom Effect ➕
The system is designed to be extended. Add your own effects following this pattern:
-
Write the Shader Code
Add your effect function in
AllInOneEffects.hlslinside a#ifdef YOUR_KEYWORDblock. Declare properties inAllInOneProperties.hlsl(both CBUFFER paths) and the keyword inAllInOneKeywords.hlsl. -
Register in EffectRegistry
Add a new entry to the
Allarray usingM()orMG(). Define EffectId, name, keyword, enable field, category, group, and parameters. -
Add C# Fields
Add matching public fields to
AnimatedSpriteShader.cs— the enable bool plus any parameters. Field names must match the registry exactly. -
Wire up Push()
In
Push(), add the keyword toggle and property block calls. Follow the pattern of existing effects.
M(EffectId.MyEffect, "My Effect", "_MYEFFECT_ON", "myEffectEnabled", "_MyEffect_En", EffectCategory.Special, "myEffectMaskCh", "_MyEffectMaskCh", F("myEffectAmount", "_MyEffectAmount", "Amount", 0, 1, "0.5"), C("myEffectColor", "_MyEffectColor", "Color")),
Batching & MaterialPropertyBlock 📊
One shared material per shader variant. Per-instance values go through MaterialPropertyBlock — no batch breaks for parameter changes.
Batches together: same variant + same enabled effects (same keyword set).
Doesn't break batches: different colors, amounts, intensities, textures in the property block.
Breaks batches: different variants or different sets of enabled effects.
Support & Effect Requests 💬
Got an idea for a new effect? Found a bug? Need help?
Discord Community
Quick help, effect requests, showing off what you've built, and chatting with other users.
Join the DiscordFor private issues, business, offers
🎯 Requesting a New Effect
We actively build effects based on community requests. When describing what you want, it helps to include:
→ A description or reference image / video of the effect
→ What you'd use it for (combat, transitions, environment, UI…)
→ Whether it needs to be animatable, maskable, or pipeline-specific
Popular requests get prioritized in upcoming updates.
FAQ ❓
My sprite turns pink / magenta
Shader variant doesn't match your render pipeline. Switch to the right one in the dropdown, or use Master Setup → Pipeline Migration to batch-fix all sprites.
Outline / glow bleeds into atlas neighbors
Click Atlas Setup in Tools. It writes UV bounds so edge effects stay inside your sprite's region.
SDF outline is clipped at sprite edges
Set your sprite's Mesh Type to Full Rect in the import settings. Tight meshes clip anything outside the silhouette.
SDF outline looks wrong after re-importing a sprite
Re-bake the SDF. The distance field is computed from the texture — if the sprite changes, the SDF needs regenerating.
Effects don't update in play mode
Call MarkDirty() after changing values from code. In the editor, changes push automatically.
Works with Spine / 2D Animation?
Yes. Color effects work on skeletal sprites out of the box. Edge effects apply per sub-sprite mesh.
How many effects can I stack?
No hard limit. Unity 2021.2+ supports 65,534 local keywords. Stack as many as you want.
Works with UI / Canvas?
Yes — use the GUI, GUI Additive, GUI Premultiply, or Screen Space Overlay variants.
Mobile performance?
Disabled effects = zero cost. On mobile, stick to green-dot (lightweight) effects. Use Bake PNG for complex setups — renders everything into a flat texture at export time.
How does batching work?
One shared material per variant. Per-instance data goes through MaterialPropertyBlock. Sprites with the same variant and same enabled effects batch together. Different parameter values (colors, amounts) don't break batches.
Enjoying the Asset?
Your review helps other devs find FlexiSprite and keeps us motivated to add more effects. Thank you! 🍃
⭐ Leave a Review on the Asset StoreNeed help instead? Discord