Solo Project · Roslyn Compiler · Unity · C#

Unity C# Trainer

An interactive learning tool I designed and built in Unity — letting beginners write real C#, compile it at runtime using Roslyn, and see it affect a live scene immediately.

Unity C# Roslyn Compiler Runtime Assembly Fungus 12-Stage Lesson System
Visit Itch Page

How I Built It

The core technical challenge was making real C# compilation work safely inside a running Unity build. I integrated the Roslyn compiler to enable true runtime code execution — then built the lesson system, editor, and console around it. Below are the key systems I designed and implemented.


Full Code Available on Request


1. Using Roslyn Inside Unity

I integrated the Roslyn compiler into Unity to dynamically compile user-written code at runtime. This was the foundational decision that made the whole project possible — Unity has no native support for runtime code injection, so I had to set up the Roslyn pipeline, manage assembly references, and ensure compilation didn't block the main thread.

Roslyn & Editor Imports

2. Compiling User Code

When a player clicks Compile, I parse their script into a syntax tree and feed it into the Roslyn compilation pipeline. I also dispose of any previously running runtime script instances before each new compile — a step I added early on after spotting memory growth during playtests.

Compile & Cleanup

3. Building the Runtime Assembly

I use Roslyn to emit an in-memory DLL from the player's script. I include all currently loaded assemblies as references so the user's code can access Unity APIs without any extra setup on their part — keeping the experience beginner-friendly while still running real compiled code.

Assembly Builder

4. Detecting the User's Class

Once the in-memory DLL is ready, I search it for the first class that extends MonoBehaviour. That becomes the live script running inside the game world — a simple reflection step that lets beginners write natural Unity-style code without any wrapper boilerplate.

Detecting MonoBehaviour

5. Final Challenge Player Spawn

For the final challenge, I spawn a fully interactable character and attach the player's compiled script as its controller. This gives beginners a direct, tangible connection between their code and a character they can play — the payoff of the whole lesson arc.

Player Spawn Logic

6. Runtime Update Invocation

I solved Unity's lifecycle problem for injected scripts by manually invoking the user's Update() from the Roslyn controller's own Update(). Since only one user script runs at a time, I can fetch and invoke its implementation cleanly — giving beginners seamless frame-by-frame behaviour without them needing to know any of this is happening.

Runtime Update Loop

7. Script Injection & Loading

I built a template injection system that pushes pre-authored starter code into the editor at the start of each lesson, guiding beginners through the challenge without overwhelming them with a blank slate. I also support loading scripts from external files for more advanced users.

Inject & Load Scripts

8. Lesson Manager

I designed a Lesson class holding each lesson's block name, sample code, and a DisableNextButton flag for gating progression. A manager I built handles loading these into both the code editor and the Fungus dialogue system, keeping the lesson content and the tutorial flow in sync.

Lesson Manager

About the Project

The Unity C# Trainer is a fully interactive learning tool I built to teach beginners the core principles of C# inside Unity. Unlike static tutorials, it lets players write real C#, compile it at runtime, and see the results immediately in a live scene.


Key Features


Challenges I Solved

Runtime Performance: Unity has no built-in support for runtime code injection. Integrating Roslyn made it possible, but ensuring compilation didn't cause frame hitches required careful async handling and memory management throughout.

Replicating Unity's Lifecycle: Making injected scripts behave like native MonoBehaviours — especially Update() — required me to link the user's implementation into the Roslyn controller's own update loop. Since only one user script runs at a time, I fetch and invoke it from there, giving seamless frame-by-frame behaviour with no extra wiring from the player's side.

Lesson Display: To convey lessons clearly, I built a manager and a Lesson class that injects pre-authored code into the editor at the right moment. I integrated this with the Fungus interactive storytelling asset — with small modifications to fit how my lesson manager was structured.

Console Feedback: Surface-level Unity console access wasn't available for injected runtime code. Given time constraints, I used Quantum Console by QFSW to deliver the readable, real-time error and log output the experience depended on.

Code Editor: Building a full syntax-highlighted IDE from scratch wasn't feasible in the available time. I used InGame Code Editor by Trivial Interactive as a foundation, which freed up enough development time to expand the lesson count from the original 6 to 12.


What I Learned

[ close ] Screenshot