Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Code Generation with Roslyn in Unity 6: My Working Setup

In this devlog, I want to walk you through how I’ve successfully integrated Roslyn into a Unity 6 project to generate C# code at runtime. Unity doesn't natively support Roslyn for runtime code generation, so the process takes a bit of setup—but it's totally doable and quite fun once everything is in place.

What Is Roslyn and Why Use It?

Roslyn is Microsoft’s open-source compiler platform for .NET. More than just a compiler, it exposes rich APIs that allow you to read, analyze, transform, and generate C# code programmatically.

The Syntax Tree

At the heart of Roslyn is the syntax tree—a structured, hierarchical representation of your code. Every element in your source file, from class declarations to if statements and method calls, becomes a node in this tree.

Roslyn provides a powerful API to create and manipulate these nodes with strongly-typed objects rather than working with raw strings. Once you've built the syntax tree representing your code, you can easily output it as a source code and save it in a file, or compile it.

This makes Roslyn ideal for building code generators, refactoring tools, or even custom compilers inside tools like Unity.

Visual Studio 2022 includes a Syntax Tree Visualizer that makes it much easier to understand how C# code is represented as a syntax tree. It’s a great learning aid, helping you build a mental model of how to go from source code to syntax nodes—and back again.

This feature is also available in JetBrains Rider 2025.1, making it equally handy for developers using Rider. For this example, however, we won't make use of the Syntax Tree Visualizer, and any version of JetBrains Rider will be OK.

Syntax Tree Visualizer in JetBrains Rider 2025.1

This is an example of how the Syntax Tree of a simple class is represented in the Syntax Tree Visualizer offered by JetBrains Rider 2025.1

Step 1 – Installing Roslyn in Unity: Two Alternatives

There are two main approaches I’ve tested for bringing Roslyn into Unity. Each comes with pros and cons depending on what you value more: simplicity or stability.

Option 1 – Using NuGetForUnity (Quick, but Messy)

The fastest way is using NuGetForUnity.

  1. Install the package following the instructions in the GitHub README.

  2. Once installed, a NuGet menu appears in Unity.

  3. Click Manage NuGet Packages and search for Microsoft.CodeAnalysis.

  4. Install it.

This method brings in a huge number of packages, many of which are unnecessary or outright problematic, showing several missing references in the Log. For example, I'm puzzled why Roslyn needs a reference toSQLitePCLRaw.Core , even though SQLite has apparently nothing to do with Roslyn.

You’ll need to manually clean up the following:

  • Remove every folder under Assets/Packages except:

    • Microsoft.Bcl.AsyncInterfaces
    • Microsoft.CodeAnalysis.Analyzers
    • Microsoft.CodeAnalysis.Common
    • Microsoft.CodeAnalysis.CSharp
    • Microsoft.CodeAnalysis.Workspaces.Common
    • System.Collections.Immutable
    • System.Composition.AttributeModel
    • System.Composition.Hosting
    • System.Composition.Runtime
    • System.Composition.TypedParts
    • System.Reflection.Metadata
    • System.Runtime.CompilerServices.Unsafe

Also, edit Assets/packages.config to match:

<?xml version="1.0" encoding="utf-8"?>
<packages>
   <package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" />
   <package id="Microsoft.CodeAnalysis" version="4.13.0" manuallyinstalled="true" />
   <package id="Microsoft.CodeAnalysis.Analyzers" version="3.11.0"/>
   <package id="Microsoft.CodeAnalysis.CSharp" version="4.13.0" manuallyinstalled="true"/>
   <package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="4.13.0"/>
   <package id="Microsoft.CodeAnalysis.Common" version="4.13.0"/>
   <package id="Microsoft.CodeAnalysis.Workspaces.Common" version="4.13.0"/>
   <package id="System.Composition" version="8.0.0"/>
   <package id="System.Composition.AttributedModel" version="8.0.0"/>
   <package id="System.Composition.Convention" version="8.0.0"/>
   <package id="System.Composition.Hosting" version="8.0.0"/>
   <package id="System.Composition.Runtime" version="8.0.0"/>
   <package id="System.Composition.TypedParts" version="8.0.0"/>
   <package id="System.Reflection.Metadata" version="9.0.4" manuallyinstalled="true"/>
</packages>

 ⚠️ Important: Unity or NuGetForUnity may re-add the deleted packages on project reloads or updates. I haven't found out (I didn't even try, to be honest) why and how to fix it. If that happens, just delete them again, or better go for...

🛠️ Option 2 – Manual Install (More Effort, More Stability)

For full control and long-term stability, I recommend downloading the NuGet packages manually.

  • Go to nuget.org.

  • Download these packages:

    • Microsoft.Bcl.AsyncInterfaces
    • Microsoft.CodeAnalysis.Analyzers(only need the cs folder, ignore the vb folder)
    • Microsoft.CodeAnalysis.Common
    • Microsoft.CodeAnalysis.CSharp
    • Microsoft.CodeAnalysis.Workspaces.Common
    • System.Collections.Immutable
    • System.Composition.AttributeModel
    • System.Composition.Hosting
    • System.Composition.Runtime
    • System.Composition.TypedParts
    • System.Reflection.Metadata
    • System.Runtime.CompilerServices.Unsafe
  • Rename each .nupkg to .zip and extract them.

  • Copy the contents of the lib/netstandard2.0/ folder for each package into a corresponding folder under Assets/Packages.

Note: for Microsoft.CodeAnalysis.Workspaces.Common, from the Inspector, disable Validate References.

You can now move forward with a lean and clean Roslyn install that won’t break your Unity setup.

Step 2 – Generating Code with Roslyn in Unity

Let’s create a very basic script that uses Roslyn to generate C# code and write it to a file in the Unity project.

Create a script named RoslynTest.cs with the following content:

using UnityEditor; 
using UnityEngine; 
using Microsoft.CodeAnalysis; 
using Microsoft.CodeAnalysis.CSharp; 
using Microsoft.CodeAnalysis.CSharp.Syntax; 
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;  
public class RoslynTest
{
     [MenuItem("Test/Roslyn Code Generation")]
     public static void TestRoslynCodeGeneration()
     {
         var generatedCompilationUnit = GenerateCompilationUnit();
         var generatedCodeString = generatedCompilationUnit.ToFullString();
         var outputPath = "Assets/generatedCode.cs";
         System.IO.File.WriteAllText(outputPath, generatedCodeString);
     }
     private static CompilationUnitSyntax GenerateCompilationUnit()
     {
         // We'll paste generated code here
     }
}

Step 3 – Use Roslyn Quoter to Get the API Call

Now, go to this awesome tool:

👉 https://roslynquoter.azurewebsites.net

Paste the code below—this is what we want to generate programmatically:

using System;  
namespace DeeDeeR {
     public class MyClass
     {
         private string _name;
         public string Name { get; set; }
         public MyClass()
         {
             _name = "this is my name";
         }
         public bool IsGreaterThanZero(int value)
         {
             if (value > 0)
             {
                 return true;
             }
             else
             {
                 return false;
             }
         }
     }
 }

Click “Get Roslyn API calls to generate the code!”, then copy the resulting API syntax tree calls.

Back in your RoslynTest.cs, paste them into the GenerateCompilationUnit method:

private static CompilationUnitSyntax GenerateCompilationUnit()
{
     return
         CompilationUnit()
             .WithUsings(
                 // more of this
             )
             .NormalizeWhitespace(); 
}

Step 4 – Run It!

Go back to Unity, and from the top menu choose:

Test → Roslyn Code Generation

You’ll see a new generatedCode.cs file in your Assets folder, containing the code you described earlier.

Final Considerations

While Roslyn is a powerful tool, it does come with some challenges, especially when integrating it into a Unity project. Here are a few honest takeaways from my experience:

  1. Installing the required libraries is tedious
    You need to bring in quite a few packages, especially if you choose the manual route for stability. It's not plug-and-play.

  2. Learning Roslyn isn’t quick or easy
    Roslyn’s API is robust and expressive, but also very verbose. Generating even simple code structures requires a good understanding of syntax trees, nodes, and tokens. There's definitely a learning curve.

  3. A lot of code for relatively simple output
    Generating a class using Roslyn can take dozens of lines of API calls—whereas a custom string-based code generator using StringBuilder would get the job done in just a few lines. Yes, it’s dirtier and riskier, but it works and is much faster to write.
    Fortunately a tool like Roslyn Quoter can simplify your life quite a bit.

✅ So why bother with Roslyn?

Despite the friction, Roslyn offers some real advantages:

  • Type safety and structure: Instead of messy string concatenation, you get a strongly-typed API that ensures your generated code is always valid C#.

  • Refactor-friendly: Code written with Roslyn can easily be adjusted, extended, or analyzed—making it ideal for building tools, analyzers, or code transformation pipelines.

  • Editor integration: Roslyn is used under the hood by both Visual Studio and Rider, so your generated code can plug directly into your IDE’s tooling.

  • 🔄 Bidirectional understanding: Once you understand Roslyn, you can not only generate code but also analyze and modify existing source files programmatically.

In short: it's more work up front, but the long-term benefits make it a nice tool in the box for a software engineer focusing on .NET ecosystem.

— Dee-Dee-R

Support this post

Did you like this post? Tell us

Leave a comment

Log in with your itch.io account to leave a comment.