Skip to content

Migrating from Photon Fusion

You have a Unity game on Photon Fusion 2.1 and you want it on Lattice. This hub is the one place to start. It walks the whole port as a single journey and points you at the tool, the addon, and the three deep guides at each step.

The honest headline

A Fusion → Lattice port is assisted, not automatic. A codemod does the mechanical rewrites and produces a precise to-do list; you do the netcode-shaped parts (spawn model, RPC payloads, input routing, prediction timing) by hand against a clear pattern. Lattice does not hide the hard parts of a port behind a one-click button — it makes them explicit and gives you a recipe for each. Budget real engineering time; you will ship a port you understand.

The journey at a glance

flowchart LR
  A["① Assess<br/>parity cookbook"] --> B["② Convert<br/>fusion2lattice codemod"]
  B --> C["③ Port the hard parts<br/>KCC · physics · collections · input"]
  C --> D["④ Check parity<br/>feature-by-feature verdicts"]
  D -->|loop on each feature| C
Step What you do Use
① Assess Inventory which Fusion features your game uses and learn each one's Lattice verdict (✅ core / 🧩 addon / 📝 port / ⚠️ gap) before you touch code. Parity cookbook
② Convert Run the fusion2lattice codemod over your project. It rewrites the high-confidence Fusion surface and emits a per-file report of everything left to do, bucketed Auto / Review / Manual. Migration tool guide
③ Port the hard parts Work the report's Manual list: the KCC character controller, networked physics, networked collections, and input routing — each with a concrete com.lattice.netcode pattern. KCC + physics port
④ Check parity Confirm each feature has a Lattice home, build a vertical slice, then fan the pattern out. Parity cookbook

Start here

  • ① Assess — parity cookbook


    Every Photon Fusion feature, with an honest verdict and a concrete pattern: KCC, scene loading, physics, pooling, animator, input, AoI, lag comp, prediction, matchmaking, host migration, voice. Read this first to size the job.

    Feature parity cookbook

  • ② Convert — the fusion2lattice tool


    A Roslyn codemod that rewrites the mechanical Fusion → Lattice surface and reports the rest. Honest about what it does and does not solve, with a full before → after walkthrough on a bundled sample.

    Migration tool guide

  • ③ Port — KCC, physics & collections


    The deep dive on the hard parts: rebuilding the Fusion KCC as a CharacterMotor (the codemod's --kcc adapter auto-converts your KCCProcessors into IKccProcessors — you finish the collision wiring + feel), the authority-simulate + replicate physics pattern, and bounded replacements for networked collections.

    KCC + physics port

The two pieces that carry the port

Beyond the guides, two concrete artifacts do the heavy lifting — know what each is:

  • fusion2lattice — the migration tool (a net8.0 console app under tools/fusion2lattice/). It is a Roslyn codemod, not a regex pass: it parses each .cs to a syntax tree, rewrites the high-confidence mappings into a separate output tree (your sources are never touched), and writes a per-file report plus a MIGRATION-SUMMARY.md. It mechanically handles ~75–80% of detected constructs and flags the rest — it does not pretend to finish the port. See the migration tool guide.

  • CharacterMotor — the addon that replaces the Fusion KCC. Shipped in the com.lattice.netcode Unity package, it is a rollback-ready motor over a replicated MotorState with an ordered, customizable step pipeline (IMotorStep) — the direct analogue of the KCC processor stack. It also ships a KCC-compat layer (IKccProcessor / KccData / KccProcessorStep) so you can paste a Fusion KCCProcessor.Process body in with minimal edits — and the codemod's --kcc adapter mode (the default) auto-converts your KCCProcessor / NetworkKCCProcessor classes into IKccProcessors for you, mapping KCCData members onto KccData. The deep design is in the KCC + physics port.

What --kcc adapter does — and where it stops

The fusion2lattice --kcc adapter flag (the default) detects a Fusion KCCProcessor / NetworkKCCProcessor and rewrites it to a Lattice IKccProcessor: it changes the base type, the Process signature, and the KCCData.X → data.X member access (Position, Velocity, RealVelocity, LookYaw, Height, IsGrounded, Crouching, Tick, LastGroundTick, LastJumpTick). It is a scaffold, not a finished port — collision/sweep calls (kcc.Move / penetration / ICollisionProbe wiring) and the movement feel are flagged for you to finish by hand. Pass --kcc report to detect-only (emit KCC as Manual findings) instead.

Host migration is still a gap — plan for it

Host migration has no drop-in equivalent. Run a dedicated/managed authority instead of a player-host, or use the shared-authority "soft continuity" interim pattern. The parity cookbook §15 is blunt about it.

What maps where — the short version

A quick orientation before you read the cookbook. Full reasoning and code live behind each link.

You leaned on (Fusion) On Lattice it's Where
KCC + KCCProcessor stack 🧩 addon + 📝 auto-convert CharacterMotor + KCC-compat; --kcc adapter
NetworkRigidbody / NetworkTransform 🧩 addon ReplicatedBody / ReplicatedTransform (authority-sim + replicate)
NetworkMecanimAnimator 🧩 addon NetworkAnimator ([Networked] animator params)
NetworkObjectProvider / pool 🧩 addon NetworkObjectPool over Spawn/Despawn
NetworkArray / Dictionary / LinkedList 📝 port bounded POD field / Bytes field / event deltas
INetworkInput / GetInput 📝 port InputRouter (event to authority, mailbox by netid)
NetworkSceneManagerDefault 📝 port load + ready-barrier + proceed event handshake
Prediction / rollback / interpolation core core does it — keep your tick deterministic
Lag compensation, Area of Interest core core history-rewind + interest management
Matchmaking / lobby platform lattice-director
Host migration ⚠️ gap dedicated-authority interim pattern
Voice ⚠️ third party Vivox / Dissonance / custom over events

Vertical slice before breadth

Don't port everything at once. Assess with the cookbook, convert with the tool, then build one vertical slice — a single CharacterMotor (gravity + move + jump), spawned on a host, predicted on one owning client, transform driven from replicated state. Get prediction feeling right on that one object, then fan the same pattern out to every other moving thing. Every later step reuses that shape.

Next steps