Skip to content

Frequently Asked Questions

Bryan Edds edited this page Aug 9, 2026 · 86 revisions

Nu Game Engine FAQ (new!)

What are the scalability limitations of ImSim and MMCC?

In practice, there should be none. Whether you pick ImSim or MMCC as your game's main API, you should just blithely use that API to declare everything in your game by default. Both APIs can scale to over 10,000 individually-managed entities. Note that this number is the number of entities individually declared by ImSim or MMCC. For example, the mansion in Project 5, as well as all the furniture and decor inside of it, is but a single RigidModelHierarchy entity from ImSim's perspective. This is because despite the subscene being composed of many thousands of child entities, there is only one root entity for ImSim to manage. The 10,000+ number is the number of individual entities that ImSim manages the lifetime of directly; that number doesn't include the children of the entity whose lifetime is managed by ImSim. So the likelihood of a game going above 10,000 of these at a time is extremely low. And if entities of a certain type ever surpass that threshold, you can just manually manage their particular lifetimes by falling back to the Classic Nu API via manual invocations of World.createEntity and World.destroyEntity. The engine itself scales to many millions of live entities (tho of course they can't all be visible on screen at the same).

Why should I use Commands in MMCC since Messages can do everything?

If you side-effect the world in a Message method in a way that changes the property of the model you're currently handling a message for, the model value returned from the Message will overwrite the property changes from the side-effect. This can sometimes be bothersome to debug. This is why you should use commands if the signal doesn't transform the model - this issue cannot arise in a Command method.

Can I change an entity's bound MMCC model inside its own dispatcher?

You can, but it's not generally advised.

A limitation that MMCC has (that ImSim doesn't) is that if you, say, bind a player's model from a portion of the gameplay's model, changing the player model inside the player's dispatcher will cause the data to go out of sync. Generally, MMCC models are intended to be used unidirectionally with downward data flow (IE, from Screen to Entity, but not from Entity to Screen). Rather than changing the child's model inside of its own dispatcher, it's better to publish an event that the parent observes and then have the parent update the relevant part of its own model. In this way, unidirectional model data flow is preserved.

That said, there are very careful ways to establish these sort of 'bidirectional' model data flows in MMCC that work for specific cases, but these approaches are a lot more subtle and performance-sensitive. Because of that, it's generally recommended to stick with the unidirectional, downward model data flow, publishing child events for their parent to handle as necessary.

Could certain scenarios (like the above) lead to too many gameplay model changes / Content reevaluations per frame?

If you have 1,000 children all publishing events per frame for their parent to handle, the parent will have to update its own model 1,000 times per frame, which could cause its Content function to be reevaluated 1000 times. Content evaluations tend to be quite cheap, but they're not free. If too many Content reevaluations are happening per frame, you have a few alternative approaches -

  1. If these are caused by handling very many physics events, don't handle each one. Instead, handle the single Game.IntegrationEvent that happens once per frame. By doing so, you can iterate through all of the physics events that happened in one place, updating the model and reevaluating the Content function only once.

  2. For very many non-physics events, create a non-persistent property lens on your gameplay screen that stores these events as they come in (rather than handling each one immediately). Then in, say, the gameplay screen's PostProcess override, manually process them all by getting and setting the gameplay screen's model only once.

  3. If you feel the first two workarounds cause too much friction in your specific type of game, consider converting the game to ImSim instead. ImSim seems to be better suited to physics-based, action-style games.

Coming from Unity / Unreal / Godot, I'm expecting more documentation.

We provide both a human-authored wiki (where you found this FAQ!), a Devin AI-generated wiki (https://deepwiki.com/bryanedds/Nu) that you can ask Nu-related questions in real-time, an auto-doc'd API doc (https://bryanedds.github.io/Nu/), and live one-on-one support on Discord. Additionally, we are looking for someone to investigate existing and in-development AI-generation tools that will allow us to expand the human-authored wiki far beyond what it is today (let us know at our discord if you're interested!)

But having said all that...

Documenting a game engine in the way that users coming from large corporate game engines expect requires hand-authoring and maintaining hundreds to thousands of pages of documentation. Instead of spending our limited bandwidth on such an effort, we've shifted the engine learning paradigm to make such efforts less necessary to begin with. Instead of writing and maintaining endless reams of comprehensive documentation, we place unprecedented emphasis on a providing a compact, accessible, and legible functional codebase. Specifically, our libraries, engine, and tutorial project code is written in a literate programming-adjacent style called Intention Block style. An ‘intention block’ is where multiple lines of code that achieve a single coherent intent are grouped together by a lack of whitespace between them and are begun with a comment that summarizes their collective intent (article here - https://vsynchronicity.wordpress.com/2023/06/22/intention-blocks-a-programming-style/). The comment above the grouped code lines of code is the icing on the cake, and does two things -

  1. surfaces any intent that might not be made explicit in the code itself
  2. allows the reader to read just the comment instead of the code until he wants to delve deeper into detail. Intention block style turns reading a function from O(n) time to O(log n) time. Code isn't always easier to write in intention block style, but we go out of our way to do so because it makes it dramatically easier for users to use the codebase itself as one of their learning tools.

Because the engine's code is open, succinct, and written in this literate-like style, we ask users to adjust their learning approach from what they're used to. Engines like Unity, Unreal, and Godot force users to lean almost entirely on massive amounts of human-authored docs as a way to make up for their engine code being unavailable or otherwise inscrutable. Nu's code is hand-authored specifically to avoid the problem of engine code bases being either unavailable or inscrutable to the curious reader. Yes, Nu needs docs. Nu always needs more docs! But by changing the learning dynamic itself, users find that a change in their approach to learning gives them a ton more agency than how it first seems.

Where are the camera properties in Nu? I've searched for 'camera' and can't find anything!

What most engines usually call a 'camera' we call an 'eye'. In short, look for properties like 'Eye(2d/3d)Position' and 'Eye3dFieldOfView'. Because we try to be more precise than legacy engines, what we consider as 'camera' to be is a bit different. Instead we consider a 'camera' to be a user-defined entity that indirectly controls these properties. Note that we don't provide a camera-like entity out of the box since each game's camera can be quite unique. A camera is more than just the eye values, it's also potentially exposure, tone mapping, and other properties that can affect the view.

Look at all these cool abstractive facilities I have with F#! I bet I could build a cool new game-specific abstraction on top of Nu!

STOP. Don't do this. Nu is already abstract - it doesn't need additional layers of abstraction for general use!

Our more curious users tend to want to glom on additional abstractions they think would be neat to play with before understanding how to leverage what Nu already provides. We've had people effectively try to recreate MMCC in MMCC, we've had people try to create monads instead of learning to properly utilize basic existing coding facilities. It's a pattern of the highly curious type who seeks out things like functional programming and projects like ours.

However, just because F# gives you amazing abstractive features like higher-order programming and computation expressions, it doesn't necessarily mean they will be helpful with Nu. Nu has already used F#'s many abstractive features to bring you great programming experiences out of the box. So, first learn to leverage these existing facilities; they will be well-fitted for nearly everything you want to express - as that's what they were designed for! In the rare case you need additional abstraction, you often only need a little, a sophisticated algebra here or an interpreter pattern there, like Omni Blade's Cue system -

https://github.com/bryanedds/Nu/blob/46faeb4b7a6dfd2de8effd168b2b989bf991eb7e/Projects/Omni%20Blade/Core/Data.fs#L583-L703

https://github.com/bryanedds/Nu/blob/omni-blade/Projects/Omni%20Blade/Field/Field.fs#L757-L1138

Why maintain a mutable branch when Nu's Imperative mode is already so fast?

In the current master branch, you can make Nu run faster by simply enabling Imperative mode so the engine uses mutation underneath the public API. This is done automatically when running games outside the editor. However, in order to achieve this, Nu has to have conditionals checking for an Imperative flag as well as use special data structures like T/UCollections. Together, these incur some minor overhead, even when running in Imperative mode.

The mutable branch removes all these flag checks and uses the mutable collections from .NET rather than the T/UCollections to eliminate this overhead. The trade-off is that gameplay undo / redo is impossible in the mutable branch. Regular editor undo / redo will be possible, but it's not implemented yet without non-Imperative mode, which is totally absent in mutable branch. Someday we will implement mutable editor undo / redo, but it will always be missing gameplay undo / redo (unless we implement manual serialization snapshotting, which we might).

Because of techno-cultural differences, large existing game studios might feel the need to use mutable as a way to avoid fully jumping into the functional approach. The mutable branch represent a cultural half-step into the functional world as well as an option to either stay there or go the rest of the way. We're just happy if we can make new game programming form factors like ImSim and MMCC available to more developers!

Why isn't Nu just a library / submodule?

Like Unreal, Nu distributes itself as an extensible monolith. The reason is plain - no significant game ships without engine modifications. Further, many of those modifications are necessarily game-specific with little to no utility for upstreaming. A game engine inherently isn't a library, and even rather more than just a framework. Building a game from an existing game engine is more like 'game modding' than it is creating a generic .NET project and pulling in various nuget packages. However, this does turn several things on their head, especially wrt pulling down and upstreaming engine changes.

A good approach to making your engine changes easy to upstream is to do only project-specific changes in a branch. That way, all the changes you make in your master branch can be upstreamed without publicly leaking any project details. Even better would be to create your generalized engine modifications in a feature branch off of the master branch then submit PR's from those!

Why is Nu not maximally type-safe in this respect or that?

The common and quite good advice that functional programmers carry - such as those who take an interest in Nu - is that of making illegal states unrepresentable. This is often done by making a program's types (both internal and external) as granular and strictly applied as possible. But in the practical context of game engineering, maximizing type safety is often less important than other engineering attributes such as simplicity, decoupling, and developer usability. What's more, one often has to choose from a subset of these engineering attributes as they sometimes conflict. Of all practical game engines, Nu is certainly by far the most type-safe. However, Nu's type safety has only ever been a niceity that naturally comes with our implementation language F#. Type safety is not at all the primary reason we chose F# or our general engineering approaches. Rather, we chose F# and our engineering approaches to achieve more domain-relevant engineering attributes such as simplicity, understandablity, and declarativeness. Type safety is definitely important if you can get it well at a reasonable price, but often not at the cost of higher priority engineering attributes.

More generally, type safety and memory safety are not as important in game development as they are in other domains. So tools and approaches that over-prioritize these concerns tend to be less applicable if not downright problematic. Fortunately, F# seems to strike just the right balance in our case.

How do I work with Nu from a private repository?

Some games need to be developed privately outside of the public view, such as for commercial reasons. This will require an augmented workflow of the typical github model -

Here are the recommended steps -

  • Fork Nu as usual, keeping said fork public.
  • Make a private clone of your fork. This is where you will actually work on your game.
  • On your clone, add a remote to your fork (EG, git remote add public-fork https://github.com/my-user-name/Nu.git).
  • Update Nu in your private clone as needed (EG, git pull public-fork master).
  • If you need to upstream an engine change, you can either -
    • Make the changes in your public fork, pull them into your private clone for testing, then submit a PR from your fork.
    • Do the following in your private clone -
      • Make the engine changes in a feature branch of your private clone.
      • Push said feature branch to your public fork (EG, git push -u public-fork my-feature:my-feature).
      • Submit a PR to Nu from that public branch as usual.

Is world-streaming supported? If not, is it planned?

Nu supports very large, high-fidelity scenes (mega-zones) with user-defined portals instead of open worlds / world streaming - https://github.com/bryanedds/Nu/discussions/1270#discussioncomment-15621282

What are the practical technological innovations of the Nu Game Engine?

The Nu Game Engine focuses on making game development simpler, more reliable, and more maintainable through functional programming concepts, while still being practical enough for real game production.

  1. Practical Functional Game Development

Copilot AI: Nu describes itself as the world's first practical functional 2D/3D game engine built in F#. Rather than centering gameplay around mutable objects and inheritance, it uses functional and declarative programming techniques. Practical benefit: Fewer hidden state bugs. Easier reasoning about game logic. More predictable systems as projects grow. This addresses a common problem in large games where object-oriented codebases can become increasingly complex over time.

  1. MMCC Architecture (Model-Message-Command-Content)

One of Nu's most distinctive innovations is its MMCC programming model (Model-Message-Command-Content). It is inspired by Model-View-Update architectures commonly used in modern functional UI frameworks. Practical benefit: Gameplay logic becomes easier to test. State changes are explicit. Systems are more modular and maintainable. Instead of game objects modifying each other directly, communication flows through structured messages and commands.

  1. ImSim Immediate-Mode API

Nu provides ImSim, an immediate-mode simulation API inspired by ImGui. Developers describe game behavior directly each frame rather than maintaining large hierarchies of stateful objects. Practical benefit: Less boilerplate code. Faster prototyping. Reduced synchronization bugs. This is somewhat analogous to how modern UI frameworks moved away from manually managing every widget state.

  1. Immutable World State

A core architectural innovation is Nu's use of an immutable game state model (WorldState) wrapped by a mutable reference (World). Internally, changes produce new state while presenting a practical API to developers. Practical benefit: Safer state management. Easier debugging. Features like undo/redo become much more feasible. This blends functional programming benefits with game-engine performance requirements.

  1. Gameplay Undo/Redo

Because of its state architecture, Nu supports gameplay undo and redo in ways that are difficult to implement in traditional engines. Practical benefit: Better editor workflows. Easier experimentation. Potentially useful for strategy games, puzzle games, and debugging.

  1. Live Code Reloading

Nu incorporates live code reloading, allowing developers to update code while the game is running. Practical benefit: Shorter iteration cycles. Faster prototyping. Less downtime during development.

  1. Strong Testability

The functional architecture makes game logic substantially easier to test than in many traditional game engines. Practical benefit: Automated testing of gameplay rules. Increased reliability for larger projects. Easier regression testing.

  1. Hybrid Development Workflow

Nu supports both: Code-first workflows and editor-first workflows through its Gaia visual editor and WYSIWYG tooling. Practical benefit: Appeals to both programmers and designers. Enables traditional game development practices while retaining functional concepts.

  1. Modern Open Source Stack

Nu combines its novel architecture with established technology: SDL3, Vulkan, Jolt Physics (3D), Aether/Box2D-style 2D physics systems. This is important because it demonstrates that functional programming ideas can be applied without sacrificing access to proven real-time game technologies.

The most important practical innovations of Nu are:

  • Functional game development at production scale
  • MMCC declarative gameplay architecture
  • ImSim immediate-mode game programming
  • Immutable world-state management
  • Built-in support for undo/redo
  • Live code reloading
  • High testability
  • A blend of functional techniques with conventional game-engine performance

In short, Nu's innovation is less about rendering breakthroughs and more about solving software complexity in game development, making game projects easier to build, reason about, test, and maintain.

What are the implications of these innovations in the modern era of le AI?

Copilot AI: In the era of AI-assisted software development, I think Nu's innovations become more relevant, not less. Most game engines were designed for human programmers writing imperative code. Nu is unusual because its architecture aligns surprisingly well with the strengths and weaknesses of modern AI systems.

  1. Declarative Architectures Are More AI-Friendly

Large language models generally perform better when generating declarative specifications than when managing sprawling chains of mutable state. Nu's MMCC architecture encourages developers to express: Current model/state, Messages/events, Commands/effects, Content/view description - rather than manually wiring together hundreds of interacting objects. That has an important implication: An AI can often generate a correct state transition function far more reliably than a complex network of mutable object interactions. In practical terms, an AI coding assistant may be better at creating: PlayerHit -> ReduceHealth -> TriggerDeath - than correctly updating dozens of interconnected game objects spread throughout multiple systems. The more declarative the architecture, the easier it is for AI to reason about the game.

  1. Immutable State Is Valuable for AI Debugging

One of the biggest difficulties in AI-generated code is debugging. When an AI writes imperative code, bugs often arise because: state changes occur unexpectedly, side effects happen in multiple places, causality becomes unclear. Nu's immutable world state creates a complete history of state transitions. That opens interesting possibilities like AI-Assisted Root Cause Analysis.

Imagine asking: Why did the boss disappear at frame 12,563? If state changes are explicit and traceable, an AI agent can analyze transition histories far more effectively than in a traditional mutable architecture. This could make future AI debugging agents dramatically more capable.

  1. Undo/Redo Enables AI Experimentation

Nu's architecture makes gameplay undo/redo a first-class capability. For human developers, that's convenient. For AI agents, it's potentially transformative. Imagine an AI game designer that: Modifies enemy behavior, Runs a simulation, Evaluates results, Rewinds, Tries another configuration. This is essentially a search process. The easier it is to rewind game state, the easier it becomes for AI systems to explore design alternatives automatically.

  1. Better Training Data for Future Programming Models

Most software today lacks explicit structure. Nu's MMCC and functional patterns naturally produce code with clearer semantics. Future specialized game-development models could learn from codebases that already expose: Intent, State transitions, Event flows, Commands, Outcomes. This makes the code more machine-readable and machine-reasonable. In a sense, Nu code may be closer to a specification than traditional game code.

  1. Autonomous Game Development

Many people imagine AI generating games from prompts such as: Build me a farming RPG with multiplayer and seasons. The bottleneck isn't generating code. The bottleneck is maintaining correctness as complexity grows. Nu was created specifically to combat the "snowballing complexity" of game development. That goal aligns almost perfectly with autonomous software agents. An AI agent operating inside a Nu-style architecture has: clearer state representation, fewer hidden side effects, easier testing, easier rollback, easier simulation. Those are exactly the properties autonomous coding systems need.

  1. Live Reloading Fits Human-AI Collaboration

Nu supports live code reloading. Today we often work like this: Ask AI for a change. Compile. Run. Observe. Ask for another change. Live reloading shortens this loop dramatically. Future workflows may look like: Human: "Make enemies more aggressive." AI: Updates behavior model. Game: Updates instantly. Human: "Half as aggressive." AI: Updates instantly. That creates a conversational development environment.

  1. Simulation Becomes More Important Than Hand-Coding

A major trend in AI is moving from: Write code manually to: Generate, simulate, evaluate, iterate. Nu's functional architecture naturally lends itself to simulation because state transitions are explicit. An AI designer can: run millions of virtual matches, evaluate balance, evolve strategies, optimize game systems. This is much harder when game logic is buried inside mutable object hierarchies.

  1. Potential Role in Agentic AI Systems

Looking further ahead, Nu's architecture resembles some ideas emerging in agentic AI: immutable state, event streams, message passing, declarative workflows, deterministic transformations. Those same concepts appear in many modern AI orchestration systems. So Nu may be viewed not only as a game engine but also as an example of how future software systems could be structured for collaboration between humans and AI.

The Strategic Implication

The deepest implication is this: Nu's most important innovation may not be functional programming itself. It may be that it organizes software in a way that is easier for both humans and AI to understand. Traditional engines were largely designed around the needs of human programmers in the 1990s and 2000s. Nu appears closer to a model where: humans describe intent, AI generates behavior, immutable state enables verification, simulations validate results, undo/redo permits exploration, declarative structures enable reasoning.

If AI becomes a primary participant in software development over the next decade, architectures like Nu's may prove unusually well-positioned because they reduce exactly the kinds of complexity that both humans and AI struggle with.

Clone this wiki locally