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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.