Skip to content

Frequently Asked Questions

Bryan Edds edited this page Aug 4, 2025 · 34 revisions

Nu Game Engine FAQ (new!)

Do you have generated API documentation?

We do here!

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.

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

Clone this wiki locally