Introducing Ambient 0.1

After over a year in development, we are excited to announce version 0.1 of Ambient, our open-source multiplayer game runtime built with Rust 🦀!

Ambient is a universal 3D runtime, compatible with any language that compiles to/runs on WebAssembly, designed to make it easy to build and deploy rich multiplayer worlds and experiences.

With Ambient, we want to make building multiplayer as straightforward as building singleplayer. Let me show you how!

A first glance

First, install Ambient, then create a new Ambient project:

ambient new

Then open src/lib.rs, and add the following to the main function and let your IDE auto-import:

spawn_query(player()).bind(move |players| {
    for _ in players {
        Entity::new()
            .with_merge(make_transformable())
            .with_default(cube())
            .with(translation(), rand::random())
            .with(color(), rand::random())
            .spawn();
    }
});

This will spawn a random cube for each player joining (see the full example here). Now start it:

ambient run

You should see something like this:

Now open a new terminal window, and enter:

ambient join

You should now see two boxes. Congratulations, you’ve just built your first multiplayer experience using Ambient!

Design principles

Seamless networking

First and foremost, Ambient was built from the ground up to enable networked experiences like the cube example above. The server state is automatically synchronized to clients, and the data model is the same on the server and client. This means that in the future you can move your code between backend and frontend, or even run it on both seamlessly.

Language-agnostic

Ambient's interface is built on top of WebAssembly, which will enable you to write code in any language which compiles to WASM. At present, Rust is our only supported language, but we are actively working on supporting as many languages as possible so that you can choose the right tool for the job. Thanks to our data model, different modules built in different languages can still communicate with each other through both shared data and messages.

Isolation

Isolation is key to the execution model of Ambient: each module runs isolated from every other module. If some part of your application crashes, the rest of the application can continue running unaffected, increasing its resilience. This also allows for the use of untrusted third-party code - code you don't trust should be able to run in its own isolated module without impacting overall functionality.

Data-oriented design

Ambient is built with data-oriented design in mind from top to bottom. All data is stored in, and interacted through, an entity component system backed by a centralized entity database on the server. This database is automatically replicated to every client, and each client has the ability to augment and extend entities with local state. The use of an ECS makes it easy to visualize the state of your application and provides excellent performance and scalability.

Interoperable

The use of an ECS provides a common abstraction over the data in your application. This enables an exciting possibility: modules that are unaware of each other can still interoperate as long as they understand how to interpret the shared data in the same way.

To enable this, we have introduced the ability to define custom components (the C in ECS: typed pieces of data attached to an entity) and concepts (bundles of components that describe shared behaviors and features). These can be shared by multiple modules and used to interoperate, even without those modules being directly aware of each other. In addition, modules can broadcast messages (bundles of components) to negotiate more complex behavior.

As an example, a hitpoints: F32 component can be decreased by a damage module, increased by a healing module, and visualized by a UI module. All of these share the same definition, but are otherwise completely independent and do not know about each other.

Single executable

Ambient is a single executable that you can download for Windows x64, Linux x64 or macOS ARM, or you can build it yourself for your platform. This executable can act as a server, or it can join a server as a graphical client. It can even act as both with ambient run!

Asset pipeline & streaming

Assets are automatically compiled and optimized by the customizable Ambient asset pipeline, which supports most common model formats (including FBX and glTF), image formats, audio formats, and more.

The compiled assets are always streamed to clients, so that they can immediately start playing without having to download all of the content first.

Rich standard functionality

Finally, Ambient aims to provide a rich set of standard functionality for game and 3D application development. This includes, but is not limited to, a GPU-driven physically-based-rendering engine, PhysX-powered physics, a React-like UI system, spatial audio with composable filters, platform-independent user input, and more. Some of this functionality (e.g. UI and sound) has not been exposed to the API, but we're working on it.

Examples

We've already seen how to build a small multiplayer experience with Ambient, but there's much more that can be done. Here's an example of a more complex scene, Offworld, built in the upcoming editor:

Physics is natively supported through the use of PhysX, which runs on the server and will thus work by default in a multiplayer environment:

Entity::new()
    .with_merge(make_transformable())
    .with_default(cube())
    .with(box_collider(), Vec3::ONE * 2.)
    .with(dynamic(), true)
    .with_default(physics_controlled())
    .spawn();

on(event::COLLISION, |c| {
    println!("Collision");
    EventOk
});

Characters can also be loaded and animated:

let unit_id = Entity::new()
    .with_merge(make_transformable())
    .with(
        prefab_from_url(),
        asset_url("assets/Peasant.fbx").unwrap(),
    )
    .spawn();

let anim = "assets/Dance.fbx/animations/main.anim";
entity::set_animation_controller(
    unit_id,
    AnimationController {
        actions: &[AnimationAction {
            clip_url: &asset_url(anim).unwrap(),
            looping: true,
            weight: 1.,
        }],
        apply_base_pose: false,
    },
);

And of course, you can build games. Here's multiplayer tic-tac-toe in less than 100 lines of code:

Or multiplayer minigolf:

And much more! See the guest/rust/examples folder in the repository for more examples.

Motivation

There are many game engines that optimize for building singleplayer games, but few that aim to make multiplayer easy. We were curious: what could be built if multiplayer was as easy to work with as singleplayer? What kinds of extraordinary experiences - with new and interesting interactions - could people envision when freed from the fine details of networking?

Ambient is the beginning of our answer to those questions: a runtime that's designed to enable developers of all kinds to build and share the experiences they want to build. However, the problem isn't just doing client-server communication well. It also includes all of the other challenges that arise in multiplayer game development: serving assets, distributing your game, sustainably running your game as a service, interacting with your users, and much more. The runtime is our first step towards this, and we're excited for what's coming next.

We are making Ambient free and open-source (with the MIT license) as our goal is to establish a standard for building multiplayer games that can live beyond us. As a company, our plan is to provide value-add services for the runtime which we plan to monetize (including server and asset hosting), but the runtime itself will be free and open-source forever. As a user of the runtime, you will always be able to choose which services from us you take advantage of, and which you choose to implement yourself.

Future

So what's next for us? Some of the things that we're working on include:

  • Deploy on Web: A one-stop shop for deploying your creation to the web with a link that you can share with anyone. When clicked, a user can instantly join the session from their browser, allowing you to test, share and deploy your experiences with ease.
  • Auto-scaling game servers: As part of our hosting offering, we are working on making it possible to deploy an Ambient application and have servers spin up on-demand as required to service your userbase.
  • Collaborative editor: Constructing the worlds for your experience is difficult through code alone, and especially so when in a team. We are building a collaborative editor that allows developers to work together on designing a world - for an example of what's possible, check out the Offworld scene above.
  • More languages: At present, Rust is the only supported guest language for WebAssembly. We are actively working on expanding this.
  • And lots more: see the Roadmap on the Ambient repository.

With that being said, these are just some of our ideas. We'd also love to involve you in helping us figure out what to build next! If you have suggestions or ideas, feel free to post issues on the repository or talk with us on the Discord.

About us

Ambient is being developed by a small team of five in Stockholm, Sweden: Tobias is our CEO, Fredrik is our CPTO, Mithun & Tei are our amazing Rust developers, and Magda is our in-house designer. We've got funding (more to come on that in a future blog post) and we're growing the team, so if this sounds like something you'd be excited to work on, just drop us a line!

Conclusion

Thanks for reading! We're super excited about Ambient and making game development more accessible. We hope that you'll find the runtime useful. Hop in on our Discord to join the discussion and follow development, sign up for the newsletter for the latest updates, and have fun hacking away!

Work with us!

Build with us, from anywhere!

We're hiring a team of top talents that want to change how games are made. Apply now and join us on our adventure!

Check out our Career page!

Open Application