Run C# inside the Unity Editor, inspect live objects, keep useful probes, and temporarily patch methods while you debug.
Roslyn REPL for Unity is an editor-only toolkit for developers who want a faster feedback loop than creating throwaway editor scripts or sprinkling temporary logs through gameplay code. Open one window, run a snippet, inspect the result, save what is useful, and move on.
- Unity 2022.3 or newer is recommended.
- The package is editor-only and is designed to stay out of Player builds.
Install with the OpenUPM CLI:
openupm add com.youngchan.roslyn-replOr add OpenUPM as a scoped registry in Unity:
Name: OpenUPM
URL: https://package.openupm.com
Scope: com.youngchan
Then add the package by name:
{
"dependencies": {
"com.youngchan.roslyn-repl": "0.8.1"
}
}Package page:
https://openupm.com/packages/com.youngchan.roslyn-repl/
Use the Git URL if you prefer not to add a scoped registry:
"com.youngchan.roslyn-repl": "https://github.com/djdcks12/UNITY-ROSLYN-REPL.git#v0.8.1"- Open Unity Package Manager.
- Click
+. - Choose
Add package from disk.... - Select this package's
package.json.
You can also place the package directly at:
Packages/com.youngchan.roslyn-repl/
Roslyn and Harmony are shipped under Editor/Plugins/ as editor-only plugins. After importing the package, run:
Tools / Roslyn REPL / Verify Setup
Verify Setup checks that the compiler and patching assemblies are available and reports duplicate-assembly situations. If the dependencies are missing or were removed, run:
Tools / Roslyn REPL / Install Roslyn DLLs
- Run C# snippets directly in the Unity Editor.
- Inspect scene objects, ScriptableObjects, dictionaries, lists, and custom classes as expandable trees.
- Browse live scene objects, loaded assets, and common singleton patterns.
- Keep reusable snippets and run history per project.
- Add project-specific
usingdirectives once and reuse them across snippets. - Use
_as the previous result for quick follow-up expressions. - Watch expressions after each run, similar to a lightweight debugger watch panel.
- Temporarily replace a method body at runtime with a Harmony-powered patch.
- Keep the tool editor-only, with no Player-build dependency.
- Open
Tools / Roslyn REPL / Open. - Type a snippet.
- Press Run,
F5, orCtrl+Enter. - Inspect logs and returned values in Output.
- Save useful probes through Snippets.
- Add repeated checks through Watch.
return UnityEngine.Application.unityVersion;var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
return scene.GetRootGameObjects()
.Select(go => new
{
go.name,
active = go.activeInHierarchy,
childCount = go.transform.childCount
})
.ToArray();Debug.Log("Probe started");
return UnityEngine.Object.FindObjectsByType<UnityEngine.Camera>(
UnityEngine.FindObjectsSortMode.None);The main window gives you a multiline C# editor with line numbers, caret position, keyboard shortcuts, compile diagnostics, runtime exceptions, captured logs, and execution timing.
In Play Mode, snippets run one frame later through a tiny coroutine so the call lands in the same Player Update phase as a normal Button.onClick. This helps UI, popup, canvas, and scroll-view code behave the same from the REPL as it does from an in-game button. You can turn this off from Tools / Roslyn REPL / Run on Player Frame when you need immediate evaluation.
Snippets run on the Unity Editor main thread, so normal editor and Unity APIs are available:
var selected = UnityEditor.Selection.activeObject;
return selected != null ? selected.name : "Nothing selected";Use return when you want Output to render a value. Log-only snippets are supported too:
Debug.Log("No return value needed");Returned values are rendered as an expandable tree instead of a flat ToString() dump.
The renderer handles:
- primitive values,
- strings and enums,
- Unity objects,
- plain C# objects,
- fields (instance + private + inherited),
- arrays and lists,
- dictionaries,
- nested object graphs,
- destroyed Unity objects.
Each row shows name, type, and preview value, so large results stay readable.
The tree walks fields only by default. Property getters can run user-defined code (lazy init, IO, logging, state mutation) and inspecting a value shouldn't change project state behind your back. If you want property values in the tree, turn on Tools / Roslyn REPL / Output: Include Property Getters and re-Run — Watch follows the same fields-only default and is not affected by the toggle.
The Object Browser helps you find objects without writing search code first.
Browse:
- scene
MonoBehaviourinstances, - loaded
ScriptableObjectinstances, - singleton-like objects,
- mixed
Allresults.
Double-click an entry in Output mode to generate an inspection snippet. Switch the lower pane to Patches mode and double-click an entry to pick a method from that object's runtime type.
The browser caps the first page at 200 results and debounces search input so large projects remain responsive. When more results exist, Load more appears next to the count.
Save useful probes and reload them later. Snippets and run history are project-scoped, so one Unity project does not inherit another project's debugging helpers.
Import starter snippets from:
Tools / Roslyn REPL / Import Default Snippets
Add project namespaces once from Usings and write shorter snippets afterward:
MyGame.Runtime
MyGame.EditorTools
System.Text.RegularExpressions
The REPL combines built-in usings with your custom list on every run.
The previous successful non-null returned value is available as _.
return 41;Then:
return _ + 1;_ is exposed as dynamic, so common follow-up expressions work without casts. Failed runs, cancelled runs, log-only snippets, null returns, and watch refreshes do not overwrite it.
The Watch panel evaluates expressions after each run.
Use it for values you repeatedly care about:
Time.frameCount
Selection.activeObject
GameManager.Instance.CurrentStateWatch rows can show scalar values or expandable trees. The evaluator can resolve expressions through normal compilation, the previous result _, or a global object-search fallback. Rows show their source so you know where a value came from.
Watch compiles are cached. Each row's wrapped source is compiled once on first sight and the resulting MethodInfo is reused on later refreshes. The cache invalidates automatically when assemblies load, so project edits are not masked by stale watch code. The interactive editor still compiles fresh on every Run.
Runtime Method Patch lets you temporarily replace a void instance method while the Editor is running.
Use it to:
- add logging without editing the source file,
- test a small behavior change in Play Mode,
- bypass a branch while investigating,
- prototype a fix before copying it into the real
.csfile.
Open it from:
Tools / Roslyn REPL / Patch Method…
Pick a target type and method, write the replacement body, then click Apply Patch.
Example patch body:
Debug.Log($"Damage called: amount={amount}");
hp -= amount;
if (hp <= 0)
{
Die();
}The patch body can look like normal source code. Private fields, private methods, private static members, explicit this access, nameof(member), compound assignments, and explicit generic method calls are routed through generated reflection helpers when direct access is not available.
You can also click Pull Original to load the current source body of the target method, edit it in place, and run the edited version temporarily. Picking a method through Browse or by double-clicking an Object Browser row in Patches mode auto-pulls the source so the editor lands on a body you can immediately edit.
Once a body is pulled and edited, the Patches view shows a live diff between the original source and the current edit. Copy diff copies a unified diff. Apply to file writes the current patch body back into the target method's .cs file. A timestamped backup is saved under <project>/Library/RoslynRepl/Backups/ before the write so you can restore by hand if the edit needs to go back; that folder is Unity-ignored (no Project window noise, no accidental commits), and Unity may delete it on a Library reimport — copy a backup out if you need it long-term.
Patches can be reverted individually or all at once; Revert keeps the spec in the list as an Inactive draft you can Load back later. Delete removes the row entirely (auto-reverts the Harmony detour first if the patch is active) for cases where the draft itself isn't worth keeping — Reset Project Data is still the broad cleanup path. Active patches are remembered per project and re-applied after domain reload when possible. Disable automatic reapply from:
Tools / Roslyn REPL / Auto-reapply Patches on Reload
When auto-reapply is off, patches are still remembered but stay dormant on reload. Re-enable the setting to install every dormant patch immediately, or click Apply per row.
Supported patch targets:
- instance methods,
voidreturn type,- normal value parameters,
- non-constructor,
- non-property-accessor.
Patch bodies can use the original method parameter names. The generated wrapper also provides helper functions for explicit reflection access when you want full control:
| Helper | Purpose |
|---|---|
__instance |
Target instance, typed as the declaring type. |
__get<T>("name") |
Read a field or property from the target instance. |
__set("name", value) |
Write a field or property on the target instance. |
__call<T>("name", args...) |
Invoke a method on the target instance. |
__getOn<T>(target, "name") |
Read from another object. |
__setOn(target, "name", value) |
Write to another object. |
__callOn<T>(target, "name", args...) |
Invoke a method on another object. |
__getStatic<T>(typeof(X), "name") |
Read a static field or property. |
__setStatic(typeof(X), "name", value) |
Write a static field or property. |
__callStatic<T>(typeof(X), "name", args...) |
Invoke a static method. |
Most patch bodies do not need these helpers because natural source-style access is rewritten automatically when needed.
The package is designed not to affect Player build output:
- all scripts live under
Editor/, - the assembly definition is limited to the
Editorplatform, - Roslyn and Harmony plugin importers are enabled for
Editorand disabled forAny Platform, - there are no runtime assemblies,
Resources,StreamingAssets, build preprocessors, or postprocessors.
Runtime Method Patch changes the current Editor process through Harmony. Those detours do not enter a Player build. The one exception is Apply to file: it intentionally edits your actual .cs source file, and that source change will be compiled into future builds just like any manual code edit.
The following data is stored locally per Unity project:
- snippets,
- run history,
- custom usings,
- watch expressions,
- runtime method patch specs.
Storage location: <project>/UserSettings/RoslynRepl/*.json — patches, snippets, run history, and watch expressions live in plain JSON files inside your Unity project's UserSettings/ folder. The package writes a .gitignore (containing *) into that folder on first save, so files never appear in git status even if your project's top-level .gitignore doesn't already cover UserSettings/. Custom usings and the smaller editor toggles still live in EditorPrefs.
Treat the contents the same way you would treat a debug-time scratch buffer: patch bodies and run-history entries can carry whatever you typed in mid-debug — server URLs, auth tokens, account values. The auto-.gitignore is the safety net, but if your team mirrors UserSettings/ to another tool (Plastic SCM workspace settings, a backup script, etc.), audit that path with the same lens you would use for an editor log.
Clear REPL data for the current project from:
Tools / Roslyn REPL / Reset Project Data
Reset clears snippets, history, watches, custom usings, previous result _, visible Output, stored runtime patch specs, and the in-memory compiled-watch cache. Active Harmony patches are reverted as part of reset.
Each Run, Watch refresh, and Apply Patch loads a small dynamic assembly that cannot be unloaded until the script domain reloads. The toolbar shows an assembly-count indicator when dynamic assemblies are loaded. Click it to open a confirm dialog, or use:
Tools / Roslyn REPL / Force Domain Reload
Script recompiles and Play Mode transitions also reload the domain in typical Unity settings, so the count usually takes care of itself.
This tool executes editor code in your Unity project. Treat snippets and patches like editor scripts:
- they can read and mutate scene state,
- they can call project APIs,
- they can create assets,
- they can trigger side effects through methods and property getters,
- long blocking loops can freeze the Editor if they never return.
Snippets run synchronously on the Unity Editor main thread. The timeout only takes effect when your code observes the cancellation token ct.
while (some_condition)
{
ct.ThrowIfCancellationRequested();
DoWork();
}Code that does not check ct, including while (true) {} or any blocking call that never returns, can freeze the Unity Editor and may require force-quitting the process. The first Run on a workstation shows this warning as a confirm dialog, and the Code header keeps a persistent reminder visible afterward.
Prefer small probes, use ct in long loops, and revert runtime patches when you are done testing.
Run Tools / Roslyn REPL / Verify Setup.
If Roslyn is missing, run Tools / Roslyn REPL / Install Roslyn DLLs.
Open Usings and add the namespace without the using keyword:
MyGame.Runtime
Also confirm the assembly that defines the namespace is compiled for the Editor.
The snippet or patch may be doing blocking work on the main thread. Stop the Editor if needed, then add a cancellation check or a clear loop bound before running again.
Watch rows can fall back to previous result _ or global object search when normal compilation fails. Check the row's source label and qualify the expression with an owner name when needed.
Run Verify Setup and check that Harmony is present. Then confirm the target method is an instance void method and the parameter type list matches the method signature.
Another package probably includes Roslyn. Use Verify Setup to identify every Roslyn assembly origin, then keep one compatible Editor-enabled set active.
| Menu | Action |
|---|---|
Tools / Roslyn REPL / Open |
Open the main REPL window. |
Tools / Roslyn REPL / Patch Method… |
Open the REPL window in patching mode. |
Tools / Roslyn REPL / Import Default Snippets |
Add built-in starter snippets. |
Tools / Roslyn REPL / Verify Setup |
Check compiler and patch dependencies. |
Tools / Roslyn REPL / Install Roslyn DLLs |
Install or repair Roslyn and Harmony dependencies. |
Tools / Roslyn REPL / Reset Project Data |
Clear this project's REPL data and revert active patches. |
Tools / Roslyn REPL / Auto-reapply Patches on Reload |
Toggle whether active patch specs reinstall after domain reload. |
Tools / Roslyn REPL / Run on Player Frame |
Toggle one-frame Play Mode marshaling for Run. |
Tools / Roslyn REPL / Force Domain Reload |
Reload the script domain to unload dynamic REPL assemblies. |
MIT for this package.
Installed Roslyn and Harmony DLLs are MIT-licensed by their authors. See Editor/Plugins/Roslyn/THIRD_PARTY_NOTICES.md and Editor/Plugins/Harmony/THIRD_PARTY_NOTICES.md.