Plugin Features
Supported Features This page covers what you can do with your SWF content once it's inside your engine.
SwfMesh converts .swf files into real scene geometry. Use it to control materials, lighting, color palettes, clip attachment, and more - all directly in your engine to support your game development needs.
Overview#
| Capability | Unity | Godot | |
|---|---|---|---|
| 3D and 2D rendering | ✅ | ✅ | Godot ships a dedicated SwfNode2D |
| Editor integration | ✅ | ✅ | Drop-in import, live preview, frame scrubber |
| Materials | ✅ | ✅ | Replace every surface at once |
| Colour-pair overrides | ✅ | ✅ | Target one authored fill colour |
| Scene lighting | ✅ | ✅ | Diffuse only, off by default |
| Attaching clips | ✅ | ✅ | Flash's addChild, kept |
| Hit boxes | ✅ | ✅ | Box, circle, capsule |
| Timeline audio | ✅ | ✅ | Through your own buses |
| Sorting layers | ✅ | ❌ | Godot 2D uses z_index; 3D orders by world Z |
| Scale and pivot | ✅ | ✅ | Three overriding levels |
| Scripting API | ✅ | ✅ | Same surface, per-engine casing |
| Offline mesh baking | ✅ | ❌ | Required for tessellator-free targets |
Your SWF is geometry, not a movie#
SwfMesh tessellates the vector art into triangles and draws it with ordinary engine meshes and shaders. There is no offscreen surface, no baked sprite sheet, no video.
- Resolution independent. Curves are triangulated as geometry, not rasterised. Punch the camera in and everything stays clean.
- It shares your scene. SWF content becomes a true scene object.
- Every fill is a surface you can replace with your own materials - see below.
- It can be lit by scene lights, per player.
- It can collide. Regions you author in Flash become engine-native colliders.
- It is cheap to repeat. Each shape is triangulated once and reused everywhere it appears, so a crowd of copies shares one set of meshes.
| Unity | Godot | |
|---|---|---|
| Component / node | SwfPlayer on any GameObject |
SwfNode3D or SwfNode2D |
| 3D scenes | ✅ | SwfNode3D |
| 2D scenes | ✅ | SwfNode2D |
Godot's two nodes are the same player in a different dimension - one shared player core under two node shells - so the scripting surface is identical between them and a script written against one works against the other.
Editor integration#
The parts you touch every day, in both engines:
- Drop-in import. Drag a
.swfin and it becomes an engine asset. No conversion step, no intermediate format, no export dialog - reimporting is just saving over the file. - A clip dropdown, populated from the symbols you exported for ActionScript, so choosing which timeline to play is a menu rather than a string you have to remember.
- A playback block on the inspector - play, loop, random-frame and a frame scrubber
- so you can find the frame you want without entering play mode.
- Live preview of the running animation in the editor viewport.
- The frame-script table, read out of the SWF at import and shown read-only on the inspector: what the timeline will do, and on which frame, before you press play.
- Gizmos and selection in the viewport, with generated render objects kept out of your saved scene file.
Materials#
Every surface a clip draws gets a SwfMesh material by default: unlit, vertex-coloured, correct in both gamma and linear projects. You can replace it wholesale.
| Unity | Godot | |
|---|---|---|
| Inspector | Material Override on the Swf Player component | material_override on the node |
| From script | player.materialOverride = mat; |
material_override = mat |
This is all-or-nothing - it replaces the material on every surface in the clip, gradients and bitmap fills included. Reach for it when you want one look across the whole thing (a silhouette, a dissolve, a hologram); reach for colour pairs, below, when you want to target part of the art.
Unity - keep overrides on a SWF shader. Use SwfMesh/SwfCombined (or
SwfCombinedLit, SwfUnlit, SwfUnlitLit) and display order stays correct by
construction. SwfMesh/SwfCombined also keeps your gradients: it resolves the authored
fill and multiplies your Tint over the top. Other shaders work, but can z-fight
where overridden fills overlap under a tilted camera - the console and inspector warn
you when that happens.
Godot - a custom ShaderMaterial should declare cull_disabled in its
render_mode. Tessellated triangles can face either way, and the automatic back-face
fix only applies to StandardMaterial3D.
Colour-pair material overrides#
Instead of replacing every surface, target a single fill colour and give just that colour its own material.
Your hero's hat is #FF0000 in Flash. Map #FF0000 to an emissive material and the
hat glows, while the rest of the character keeps rendering exactly as authored, in the
same animation, at the same depth.
| Unity | Godot | |
|---|---|---|
| Inspector | Color Material Map - a list of (colour swatch, material) pairs, with an eyedropper | color_material_map - a typed Dictionary of Color → Material |
| From script | assign colorMaterialMap, then Refresh() |
assign color_material_map - applies immediately |
// Unity - usually set in the inspector; from script it is a serialized array.
player.colorMaterialMap = new[] {
new SwfPlayer.ColorMaterialEntry { colorValue = Color.red, material = gold },
};
player.Refresh();# Godot
var gold := StandardMaterial3D.new()
gold.albedo_color = Color8(255, 200, 40)
gold.emission_enabled = true
gold.emission = Color8(255, 160, 0)
color_material_map = { Color8(255, 0, 0): gold } # every #FF0000 fill turns goldWhat is and is not matched:
- The key is RGB. Alpha is not part of it, so a 50%-alpha red fill matches the same entry a solid red one does.
- Solid fills only. A gradient or bitmap fill is not one colour, so it cannot be keyed.
- Strokes differ by engine. Unity also matches line colours; Godot matches fills only. If you need a stroke and a fill to take different overrides, give them different colours when you author the SWF - that works in both engines.
- Your material asset is never touched. Each player duplicates it, so two characters sharing one gold material do not fight over it, and editing the source material updates every player live in the editor.
⚠️ Cost: a player with overrides renders on its own, outside the shared frame-mesh cache and the instanced path. That is the right trade for a handful of hero characters; it is the wrong one for five hundred background props.
Scene lighting#
Off by default - flat Flash art usually wants to stay flat. Turn it on per player
(Unity enableLighting, Godot enable_lighting) and the default fills swap to lit
variants.
⚠️ Godot 2D can only brighten. A Light2D adds to a canvas item, so it never
darkens, and saturated art cannot respond at all. Use SwfNode3D if lighting is
central to the look.
Attaching one clip inside another#
Flash's addChild, kept. Attach a second player into a named clip instance of a
running one and it renders at that clip's depth in the display list, inheriting its
animated transform and its colour transform.
// Unity - a sword that follows the hero's hand, through the whole animation
hero.Clip.GetClip("hand").AddChild(sword);# Godot - the same, with the child built inline
var sword := SwfNode3D.new()
sword.swf_resource = load("res://sword.swf")
$Hero.clip.get_clip("hand").add_child(sword)- The attached player keeps its own timeline - it can be playing its own animation while it rides along.
- Attach depth is respected: if the hero's arm draws over the hand on this frame, the sword draws under the arm too.
- Attachments survive a clip switch on the host, and are re-applied for you.
- Detaching (
RemoveChild/remove_child) hands the child back its own rendering. - Lifetime is non-owning: destroy either side in any order and the other detaches cleanly.
- Godot can attach across dimensions - a
SwfNode2Dinto aSwfNode3D's clip slot and the reverse.
Before you author for it:
- The target must be a named MovieClip instance - name it in Flash's Properties panel. The root timeline is not an attach point.
- The child draws through the host's renderer, so it inherits the host's ordering rather than sorting independently.
- Attachment takes SWF players, not arbitrary engine objects (support planned).
Attaching a symbol out of the same .swf is in
MovieClip Library.
Hit boxes#
Draw a shape in Flash, export it as HitBox, HitBoxCircle or HitBoxCapsule, and it
becomes an engine-native collider at runtime - never rendered, visible only while you
author. Because it lives on the timeline, the active set is frame-scoped: a hurtbox
that exists on frames 5–10 of an attack exists for exactly those frames, with the
position, rotation and scale the animator gave it.
You get pooled trigger colliders, enter and exit events, and a query for the currently active set, in both engines.
→ Hit Boxes - authoring them, the shape each kind realises, flat versus extruded in 3D, and the events.
Timeline audio, routed your way#
Sounds authored into the timeline play through your engine's audio system, not a private mixer - so they obey your buses, your snapshots and your volume sliders.
| Unity | Godot | |
|---|---|---|
| On / off, per player | enableAudio |
enable_audio |
| Routing | audioMixerGroup |
audio_bus |
| Volume | audioVolume |
audio_volume_db |
| 3D positional | positionalAudio |
positional_audio |
| Cut everything now | StopAllSounds() |
stop_all_sounds() |
Voices are pooled and audio is shared per imported file, so a crowd of players from one
.swf decodes one copy. Editor previews are silent.
Draw order#
Inside a clip, order is always the display order the animator authored. Between players, you get the engine's own tools:
- Godot 2D - a
SwfNode2Dis aNode2D, soz_index,z_as_relative,y_sort_enabledandCanvasLayerall work on it, with no plugin-specific concept to learn. - Unity - Sorting Layer and Order in Layer on the component, exactly as on a
SpriteRenderer, so "this clip is always in front of that one" is a setting rather than a camera-distance accident.SortingGroupworks too. - Godot 3D - order players by world Z. There is no sorting-layer equivalent: the
render-priority range is spent entirely on getting the inside of a clip to paint in
the right order.
layering_modepicks how that is done - Strict Display Order (the default) pins each layer's priority; Depth-Tested Compatibility relies on small Z steps instead.
Scale and pivot, in three layers#
Flash's coordinate scale is nothing like engine units, and the origin sits wherever the animator put the registration point. Set both at three levels, each overriding the one above:
| Level | Unity | Godot |
|---|---|---|
| Project default | Project Settings > SwfMesh - Global Scale, Default Pivot Offset | Project Settings > swf_mesh - global_scale, global_scale_2d, default_pivot_offset |
| Per imported asset | Scale / Pivot Offset on the importer | Scale / Pivot Offset in the Import dock |
| Per player | scaleOverride |
scale_override, pivot_override |
Set the project default once to match your units and most content just lands right.
Playback the timeline cannot express#
Small things, but they are the difference between a movie and a game object:
- Run at your frame rate, not Flash's. Turn off Use SWF Frame Rate and drive the clip at any rate you like - including one you animate.
- Random start frame. Spawn two hundred copies of one idle loop and they all breathe
in lockstep; turn on Random Frame and they don't. Unity also exposes a fixed
StartFrame. - Loop or hold, per player, without editing the SWF.
- Per-clip transform overrides. Nudge, rotate or scale a nested clip - an arm, a head - from script while its animation keeps playing. See Scripting API.
Offline mesh baking#
Unity only, today. Normally SwfMesh tessellates a character's geometry the first time it is drawn. Baking moves that work to import time: every surface is triangulated on your desktop and stored in the asset, so the runtime needs no tessellator at all.
Turn it on with Project Settings > SwfMesh > Bake Mesh Geometry (off by default);
every .swf reimports.
Two reasons to want it:
- Console builds require it. The Nintendo Switch plugin ships without a tessellator, so a Switch build fails preflight unless every asset carries a current bake. See Platforms.
- No first-use hitch. Nothing is triangulated at play time, so the first frame a character appears on costs no more than the tenth.
And two reasons not to leave it on everywhere:
- Assets get bigger - triangles take several times the space of the vectors they came from.
- Morph tweens multiply. Each distinct interpolation step placed on a timeline bakes as its own mesh.
Baked output is verified pixel-identical to live tessellation, so switching it on is a build-size and timing decision, not a visual one.
See also#
- Supported Features - what of the SWF format renders
- Hit Boxes - Flash-authored regions as engine-native colliders
- Scripting API - the playback surface, in C# and GDScript
- MovieClip Library - one SWF, many clips
- Limitations - caveats within what is supported