← All posts

gameLightning Games

Unity MethodReload: Edit Gameplay Code Live on IL2CPP Phones

Unity MethodReload: Edit Gameplay Code Live on IL2CPP Phones

Every Unity mobile developer knows the loop: change one number in a jump or a camera shake, wait for the domain reload, then wait again for a full IL2CPP build before you can feel the change on a real phone. In October 2026 Unity published MethodReload, an experimental feature that swaps the body of a tagged C# method inside a running game, in the Editor and on IL2CPP development builds. This guide explains what it does, how to set it up on a mobile project, where it breaks, and how we would trial it.

▶ Watch the video version (about 4 minutes):

What MethodReload is

MethodReload ships inside com.unity.pipeline, the same experimental package that powers the Unity CLI. You mark a method with the [MethodReload] attribute, start a watcher, enter Play Mode or attach a development player, and then edit the method body. When you save, the running instance uses the new body the next time the method is called. Unity demoed it on stage at Unite Seoul and announced it on the Unity blog and Discussions on October 22, 2026.

It is not a replacement for domain reload. Unity is direct about that: bigger changes still go through a normal compile. The target is the small tweaks that make up most of an iteration session, such as tuning speeds, timings, curves, spawn rules and UI behaviour.

The feature has changed names quickly. According to the package changelog, version 0.6.0 (August 31, 2026) renamed "hot reload" to "code reload" with a [CodeReload] attribute, and the current 0.9 manual uses [MethodReload] and the script.methodreload command group. Unity's blog post still names 0.7.0-exp.1 as the install string, while the latest release is 0.9.1-exp.1 (October 22, 2026). Follow the 0.9 method reload manual for the version you actually install, and expect names to move again.

Why this matters for mobile and IL2CPP

The Editor already has ways around slow reloads. You can turn off domain reload in Enter Play Mode settings, as described in the Unity manual, as long as you reset static state yourself. Asset Store hot reload tools patch methods in a running Mono runtime and support full C#.

None of that helps on a phone running an IL2CPP build. IL2CPP compiles C# ahead of time to native code, so there is no runtime to patch and no domain to reload. Every change has meant a rebuild, an install and a fresh start of the app, often several minutes per cycle on a mid-sized Android or iOS project.

MethodReload takes a different route. Each tagged method gets a small check woven in at compile time. On every call it asks a registry whether a newer body exists. If one does, a small IL interpreter, written in plain C# and compiled into the development build along with your game, runs the new IL. If not, the original compiled code runs. The Editor compiles your edit and pushes it to connected players over PlayerConnection, the channel the Profiler uses, so it works over USB without opening a port.

Unity's own comparison is a fair summary: if your iteration pain lives in the Editor, existing tools are mature; if it lives on a device, especially IL2CPP, this is the first option that reaches it.

How the options compare

OptionWhere it worksC# coverageMain cost
Domain reload (default)EditorFullFull reload on every change
Domain reload disabledEditorFullYou must reset statics yourself
Asset Store hot reload toolsEditor, Mono playersFullNo IL2CPP support
MethodReload, interpreterEditor, any dev build incl. IL2CPPSubsetTagging, slower interpreted code
MethodReload, Assembly.LoadEditor, desktop Mono dev buildsFullPublic members only, needs runtime server

Setting it up on a Unity mobile project

Unity 6.0 or later is required. A safe first setup looks like this:

  1. Install on a branch. Add the package by name in Package Manager (com.unity.pipeline) or through the Unity CLI. Pin the exact version in Packages/manifest.json so the team runs the same build of an experimental package.
  2. Tag the methods you tune. Tagged methods must be public (instance or static) and return void or IEnumerator. Anything else is skipped at build time with a warning. The tag must exist before you enter Play Mode or build, because the dispatch check is woven in at compile time.
  3. Start the watcher. Open Project Settings, Pipeline, Editor, and click Start Watching in the Method Reload Interpreter Watch section. The watch covers the whole Assets folder, but a saved .cs file only compiles if it mentions MethodReload.
  4. Try it in the Editor first. Enter Play Mode and edit a tagged Update or tuning method. The watcher runs your change through the same interpreter used on device, so subset problems show up here before you wait for a build.
  5. Enable the runtime in development builds. In Project Settings, Pipeline, Runtime, turn on the option for development builds, as described in Runtime connection and setup. Build a Development Build, install it, and connect it with Autoconnect Profiler or through the Profiler or Console window.
  6. Edit and save. Each save compiles in the Editor with the player's scripting defines and pushes to every connected player. No restart is needed.

A minimal example from Unity's docs:

using Unity.Pipeline.MethodReload;
using UnityEngine;

public class Spinner : MonoBehaviour
{
    public float rotationSpeed = 90f;

    [MethodReload]
    public void Update()
    {
        transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime);
    }
}

If you prefer a terminal, the same push is available as a Unity CLI command (unity command script.methodreload reload_player "Assets/Scripts" in the 0.9 manual), which is also how an AI coding agent could drive it.

The limits you have to plan around

Only method bodies change

A reload never touches fields, call sites or type layout. You cannot add fields or classes. A reloaded body can declare and call a new helper method, but that helper cannot become a reload entry point until your next real compile. In practice you decide in advance which methods you will tune, and tag them.

The interpreter runs a C# subset

Inside a tagged body you cannot use await or Task, try/catch/finally, lock, LINQ query syntax, decimal, dynamic, reflection or threading types, ref/out/in parameters, multi-dimensional arrays or generic methods. Primitives, method calls, loops, delegates, string interpolation, collections and coroutine yield do work. A Roslyn analyzer shipped with the package flags violations in your IDE on tagged methods only.

IL2CPP stripping still applies

On device, interpreted code can only call engine and .NET members that exist in the build. IL2CPP strips code nothing references, so if your new body calls an API the game never used, the push lists it as a warning and the call throws if it is reached. The 0.9 settings page can generate a link.xml that keeps every member of the types your game already uses; regenerate it after larger code changes. Unity's rule of thumb: change what a method does, not which APIs it depends on.

Coroutines and performance

A tagged IEnumerator picks up the new body the next time StartCoroutine runs; coroutines already running keep the old one. An [OnMethodReloaded] method on the same class can stop and restart them. Interpreted code is slower than compiled code, so frame times measured while a reload is active are not your real numbers. Profile with the reload cleared.

Release builds and security

In a release build a tagged method simply runs its compiled body, with no prologue and no interpreter. The attribute lives in a separate Unity.Pipeline.Attributes assembly so tagged code still compiles there. The Pipeline runtime assemblies only compile into development or instrumented builds unless you add the ENABLE_RUNTIME_PIPELINE define on purpose.

That gate matters. The runtime setup page warns that a build with the runtime server enabled carries a local HTTP server that executes commands. Never add ENABLE_RUNTIME_PIPELINE to a store build, and add a CI check that fails if a release build contains Unity.Pipeline assemblies.

Who should try it now

  • Good fit: teams tuning game feel on real phones (touch controls, camera, haptics timing, physics feel), and anyone who iterates on device-only behaviour such as notch layouts, sensors or performance-scaled effects.
  • Wait: teams with a strict "no experimental packages" rule, projects whose hot code depends on async/await or heavy generics, and anyone who would expect a feature this young to keep the same API between versions.
  • Already happy: if your slow loop is only in the Editor and you use an Asset Store hot reload tool or disabled domain reload, keep that setup. MethodReload adds value mainly on hardware.

Our take

At Lightning Games we build Unity mobile games in Da Nang, and a large share of our tuning time is spent rebuilding IL2CPP players to test a few lines of feel code on a phone. MethodReload targets exactly that loop, and the design is careful: nothing ships in release builds, the device link uses the Profiler channel, and the analyzer catches unsupported code early. We are trialling it on a branch with a short list of tagged methods: input handling, camera follow and difficulty curves. We are not adding it to main until the API settles, given that the attribute has been renamed twice since August. If you already use the Pipeline package for builds and tests (see our Unity CLI and Pipeline 0.9 guide), MethodReload is a small extra step and worth an afternoon.

Sources

Want to see what we build with Unity? Visit Lightning Games for our mobile titles and development notes.


Cover photo: Playing with smartphone by Santeri Viinamäki, CC BY-SA 4.0, via Wikimedia Commons (cropped).

Facebook