Game development is hard. Especially so for beginners.
Game programming consistently ranks among the most challenging domains due to realtime requirements, many multi-domain, cross-cutting concerns, and the sheer number of systems that interact. Engine APIs are accordingly complex, with roughly between 15k (Godot) and 120k (Unreal) user-facing endpoints (types, methods, properties).
LunyScript reduces that complexity with high-level, declarative patterns because follow-along copy-paste tutorials arenât enabling real growth. In fact, we have a name for this pervasive problem: tutorial hell.
We use one engine for one project at a time. But hardly anybody sticks to just one engine forever.
Especially beginners struggle to âmake the right choiceâ as they need to make a pick before they truly understand why. The time investment quickly locks them into that one engine. Portable code allows them to trial multiple engines more easily, with less âsunk costâ.
For more experienced users, switching engines is still a time-consuming task, and requires fighting muscle memory. Being able to quickly be productive elsewhere helps both the developer and lesser known engines.
Lastly, agencies around the world often use multiple engines serving diverse clients. For them, creating a shared framework poses many challenges. Copy/paste cherry-picking between projects is rather commonplace. LunyScriptâs block-based programming concept provides exactly the cross-engine framework they need for 3d realtime applications typically low in interactivity, but high in fidelity.
Finally, even within one engine being able to do simple things with simple code can be a huge productivity boost.
AI coding assistants can be powerful learning tools, but only with understanding what gets generated. Just like us humans, AIs work better with clear and consistent APIs.
When a learner asks AI for help with Unityâs GetComponent<AudioSource>().PlayOneShot() vs Godotâs $AudioStreamPlayer.play() vs Unrealâs audio system, the AI might suggest outdated methods, wrong engine conventions, or code that doesnât match what the learner sees in their editor.
With LunyScriptâs simple, fluent API, AI assistants give reliable, working code that learners can actually understand and reason about.
LunyScript is not another re-inventing wheels framework that already exists in another engine. It sits atop of engines. Ttâs the only framework that has any chance of becoming a standard.
Engine API semantics are needlessly disparate: BeginPlay, OnEnable, _enter_tree. Every engine has the same lifecycle and gameplay events/APIs. Their semantics differ, their purpose is uniform.
LunyScript starts as the uniform API to help beginners get started and transition between engines. The Scratch for game engines. But itâs also a Developer SDK which can give us more power than we ever imagined we could have.
General purpose frameworks are too abstract for beginners. Many frameworks are often loaded with CS jargon and concepts, too. LunyScript provides high-level, fluent gameplay APIs that read like game design intent.
Letâs compare with general-purpose (but Unity-only) UniRx:
this.OnCollisionEnterAsObservable()
.Where(c => c.gameObject.CompareTag("ball"))
.Do(_ => audioSource.Play())
.Subscribe();
this.OnCollisionExitAsObservable()
.Where(c => c.gameObject.CompareTag("ball"))
.SelectMany(_ => Observable.Timer(TimeSpan.FromSeconds(2.5)))
.Do(_ => Instantiate(sparkles, other.position))
.Subscribe(_ => sparkles.Despawn());
The same code in LunyScript:
When.CollisionWith("ball")
.Begins(Audio.Play("ball_tagged_loop"))
.Ends(Spawn("sparkles").At(Other).Run(Wait.Seconds(2.5), Despawn()));
LunyScript code is 66% less verbose than UniRx and reads like intent.
CS jargon is loading semantics with assumptions, raising questions:
âHmm .. select many an observable timer?â
If you read it out loud it just makes no sense! Thatâs where beginners and designers walk away!
Visual scripting tools (PlayMaker, Blueprints, etc.) are a popular choice for many non-programmers. But they are currently the ONLY choice for users intimidated by conventional programming.
Visual tools are rightfully criticized for being:
LunyScript provides the same high-level expressiveness and simplicity with all the benefits of text-based code â a viable alternative for beginners & designers.
The shared engine features and behaviors have settled. They are so fundamental to every project that engines resist changing them.
LunyScript will not chase fancy features. Anyone can add whatever they want however.
The engine adapters and observers are in separate, engine-specific repositories. I neednât manage and maintain every engine integration myself for all eternity.
Upwards of 70% of LunyEngine is fully portable. The engine-native code is mostly automatable glue, simple API mappings and a couple utility methods.
They neednât. Close enough is good enough. The behavior contract is most important!
Even if you have to tweak every physics value once more, the logic itself is already running in the new engine, unchanged!
Thatâs a lot more productive than having to start with no code, or worse: having to verify and fix automatically converted code in a foreign environment.
And itâs really just physics that will cause gameplay to differ. Perhaps in the future LunyEngine may even provide its own physics simulation.
Neither.
LunyScript is processing static graphs (FSMs, BTs) on engine heartbeat events via a central script runner.
Infrequent native events are observed and trapped for a single frame by handlers like Collision.Begins.
LunyScript handles âstructural changesâ (eg destroy object) gracefully by activating associated events (ie When.Self.Disables, When.Self.Destroys) while deferring native execution to the âend of frameâ event.
In the future, a source generator may be used to create the APIâs static language bindings (C# to Lua).
Weâre long past the days when we needed to count bytes and CPU cycles. Our games are already full of layers of abstractions.
Code we write in C# crosses the language boundary to C++ â this is rather costly. It still worked wonderfully for Unity. Same with Blueprints: we know itâs between 100x to 1,000x slower than C++ yet we use it extensively.
LunyScript, through its central processing concept and internal caching, may even prove to be faster when compared to ubiquitous uses of GameObject.Find("") or the commonplace copy-pasta trainwrecks:
if (gameObject.transform.GetComponent<Rigidbody>() != null)
{
gameObject.transform.GetComponent<Rigidbody>().linearVelocity = 0;
gameObject.transform.GetComponent<Rigidbody>().angularVelocity = 0;
gameObject.transform.GetComponent<Rigidbody>().Sleep();
}
As seen on a worryingly regular basis.
For LunyScriptâs target audience (simple games, learning projects, prototypes, details), performance is not a limiting factor.
LunyScript is for ease of entry and productivity in pro-tier game engines, and perhaps contributes to popularizing emerging engines. Creating a custom âLunyâ game engine would defeat those purposes.
Currently, roughly 95% of Steam games published are made with Unity, Unreal, Godot, and a few AAA proprietary engines. Among the first three is where the learning pains are felt most.
Building a custom engine means rebuilding:
Join Discord to ask questions, share feedback, or propose ideas! **Join Patreon for news and updates.