Dev Diary #3 - LUA Scripting in Room Editor 2.0
[p]Welcome to another entry in our Dev Blog series, where we take you behind the scenes of Escape Simulator 2 development. These posts will introduce you to new systems, tools, and features.[/p][p]Today’s post is written by SuperJura, one of our lead programmers. He worked on many of the game’s core systems, including the complete implementation of Lua scripting in Room Editor 2.0.
[/p][hr][/hr][p][/p][p]⚠️ Note: You don’t need to know any coding to build rooms in Escape Simulator 2. The Room Editor is designed to be simple and intuitive for everyone. Lua scripting is an advanced feature, meant only for our most dedicated room creators who want to push things even further.[/p][p][/p][hr][/hr][p][/p][p]Let’s talk about Lua 2.0 in Escape Simulator 2. Or maybe it’s really Lua 1.0, since the original version was technically in beta in the first Escape Simulator 🤔. Either way, we’re rolling out a major upgrade.
[/p][p]Just a heads-up: every image and gif you see here is still work in progress. The UI and UX are not final.[/p][p][/p][h3]Lua Now Powers All Custom Levels[/h3][p]In ES1, if you ever made a connection like “button opens door,” it was defined in the room.room file as something like “object with ID 1 activates object with ID 2.” In this case, the button had ID 1 and the door ID 2. The verb "Activates" was just one of several options in our system. Others included "PlaySound," "Teleport," "FinishLevel," and so on. Every possible interaction followed this format.[/p][p]While functional, that system didn’t align well with our broader scripting approach. Our internal levels always used a single script per room, with callbacks tied to specific game events. So for ES2, we decided to unify everything — official levels and community levels — under a single, more robust scripting model.
[/p][p]
[/p][p]The solution? We now generate Lua code for the entire level. This Lua script mirrors our internal format, complete with the same callbacks and multiplayer-safe logic systems. (More on that later.)
You can access the generated level code here:[/p][p][/p][h3]Upgraded Lua API via the api Object[/h3][p][/p][p]The api object was your best friend in ES1 Lua scripting, and in ES2 it's getting a significant upgrade. [/p][p]In ES1, we exposed many useful APIs for room scripting, but quite a few were missing. For ES2, we built a tool that scans our internal levels and exposes all the APIs we use to Lua. If we can use it, so can you. This will greatly expand the possibilities for custom interactions. [/p][p]Don’t worry — we’re keeping the familiar tools like api.vector2(), api.levelNote(), and others.
[/p][h3]New Callbacks That Mirror Our Internal Events[/h3][p][/p][p]The api object isn’t the only thing getting an upgrade. We’re also introducing a full set of new callbacks that reflect our own internal level events.[/p][p]With Lua now powering the entire level logic, you’ll have access to all game-level callbacks. For example, you can track the precise movement of Dials and Turnables, or check whether a player has entered or exited a zoom. We’ll release the full list of callbacks once all components are finalized in the RE 2.0.[/p][p][/p][h3]Cleaner Lua Script Structure[/h3][p][/p][p]In ES1, Lua scripts were triggered from start to finish on every event, and you had to check the callType to determine what actually happened. Event arguments were passed in a context object, which varied based on the call type. [/p][p]After reviewing that system, we decided to adopt a cleaner, function-based approach in ES2. Each callback now has its own function, and arguments are explicitly named — no more generic “context” objects.
[/p][p]
[/p][h3]Multiplayer-Friendly by Default (If You Follow a Few Rules)[/h3][p][/p][p]In ES1, multiplayer logic relied on "Level Logic Packets" — networking packets that updated puzzle states. While it worked, it didn’t translate well to custom Lua scripts. As a result, we often had to say multiplayer wasn’t fully supported for scripted levels.[/p][p][/p][p]That’s changing in ES2. We’ve replaced Level Logic Packets with a system we call "Non-Desyncable Networking." If your code is written in a “coop-friendly” way, it will sync automatically across all players.[/p][p][/p][p]What does "coop-friendly" mean?[/p]
[/p][h3]Full Save System Support
[/h3][p]As you may know, ES2 features a full save system, moving beyond the checkpoint-based approach from ES1. This includes full support for Lua-scripted custom rooms.[/p][p]Lua is a bit unique in that you can define variables in your scripts that need to persist across saves. We’re developing a system specifically for this, including naming conventions to exclude values from serialization when needed.[/p][p]This also means custom-scripted rooms will support drop-in multiplayer, since it relies heavily on the save system.[/p][p][/p][h3]Built-In Lua Editor [/h3][p]In ES1, you had to use an external editor like VS Code, Notepad++, Rider, or Visual Studio to write Lua scripts.[/p][p]In ES2, we’re introducing a built-in text editor for Lua, complete with syntax highlighting tailored to the ES2 API. If you still prefer your favorite external tool, you’re welcome to keep using it — but now, you’ll also have a convenient in-game option. [/p][p][/p][p]
[/p][p]The editor will also feature a small file picker where you can quickly switch between Lua files, and the ability to create new Lua files directly from the editor. [/p][p][/p][h3]Small QOL improvements[/h3][p]There are also a bunch of small quality of life improvements like better lua script name validator or the ability to target lua props with other props to call a specific function.[/p][previewyoutube][/previewyoutube][hr][/hr][p][/p][p]That’s it for today’s update. More dev posts are coming soon, including deep dives into the Room Editor 2.0, multiplayer architecture, the music of ES2, and more.[/p][p][/p][p]If you want to stay updated, make sure to follow the game and add Escape Simulator 2 to your wishlist.[/p][p]
[dynamiclink][/dynamiclink][/p][p]Thanks for reading!
[/p][p]- Pine team[/p]
[/p][hr][/hr][p][/p][p]⚠️ Note: You don’t need to know any coding to build rooms in Escape Simulator 2. The Room Editor is designed to be simple and intuitive for everyone. Lua scripting is an advanced feature, meant only for our most dedicated room creators who want to push things even further.[/p][p][/p][hr][/hr][p][/p][p]Let’s talk about Lua 2.0 in Escape Simulator 2. Or maybe it’s really Lua 1.0, since the original version was technically in beta in the first Escape Simulator 🤔. Either way, we’re rolling out a major upgrade.
[/p][p]Just a heads-up: every image and gif you see here is still work in progress. The UI and UX are not final.[/p][p][/p][h3]Lua Now Powers All Custom Levels[/h3][p]In ES1, if you ever made a connection like “button opens door,” it was defined in the room.room file as something like “object with ID 1 activates object with ID 2.” In this case, the button had ID 1 and the door ID 2. The verb "Activates" was just one of several options in our system. Others included "PlaySound," "Teleport," "FinishLevel," and so on. Every possible interaction followed this format.[/p][p]While functional, that system didn’t align well with our broader scripting approach. Our internal levels always used a single script per room, with callbacks tied to specific game events. So for ES2, we decided to unify everything — official levels and community levels — under a single, more robust scripting model.
[/p][p]
You can access the generated level code here:[/p][p][/p][h3]Upgraded Lua API via the api Object[/h3][p][/p][p]The api object was your best friend in ES1 Lua scripting, and in ES2 it's getting a significant upgrade. [/p][p]In ES1, we exposed many useful APIs for room scripting, but quite a few were missing. For ES2, we built a tool that scans our internal levels and exposes all the APIs we use to Lua. If we can use it, so can you. This will greatly expand the possibilities for custom interactions. [/p][p]Don’t worry — we’re keeping the familiar tools like api.vector2(), api.levelNote(), and others.
[/p][h3]New Callbacks That Mirror Our Internal Events[/h3][p][/p][p]The api object isn’t the only thing getting an upgrade. We’re also introducing a full set of new callbacks that reflect our own internal level events.[/p][p]With Lua now powering the entire level logic, you’ll have access to all game-level callbacks. For example, you can track the precise movement of Dials and Turnables, or check whether a player has entered or exited a zoom. We’ll release the full list of callbacks once all components are finalized in the RE 2.0.[/p][p][/p][h3]Cleaner Lua Script Structure[/h3][p][/p][p]In ES1, Lua scripts were triggered from start to finish on every event, and you had to check the callType to determine what actually happened. Event arguments were passed in a context object, which varied based on the call type. [/p][p]After reviewing that system, we decided to adopt a cleaner, function-based approach in ES2. Each callback now has its own function, and arguments are explicitly named — no more generic “context” objects.
[/p][p]
- [p]Don’t use random values unless they’re synced[/p]
- [p]Don’t change the level state based on a specific player or other local-specific situations[/p]
- [p]Avoid changing the level and data in non-synced callbacks[/p]
- [p]Change the state of the room in synced callbacks[/p]
[/p][h3]Full Save System Support
[/h3][p]As you may know, ES2 features a full save system, moving beyond the checkpoint-based approach from ES1. This includes full support for Lua-scripted custom rooms.[/p][p]Lua is a bit unique in that you can define variables in your scripts that need to persist across saves. We’re developing a system specifically for this, including naming conventions to exclude values from serialization when needed.[/p][p]This also means custom-scripted rooms will support drop-in multiplayer, since it relies heavily on the save system.[/p][p][/p][h3]Built-In Lua Editor [/h3][p]In ES1, you had to use an external editor like VS Code, Notepad++, Rider, or Visual Studio to write Lua scripts.[/p][p]In ES2, we’re introducing a built-in text editor for Lua, complete with syntax highlighting tailored to the ES2 API. If you still prefer your favorite external tool, you’re welcome to keep using it — but now, you’ll also have a convenient in-game option. [/p][p][/p][p]
[dynamiclink][/dynamiclink][/p][p]Thanks for reading!
[/p][p]- Pine team[/p]