Skip to content

Projects

A Feather 2 project holds every authored setting: scene objects, landscape, environment, materials, scripts, Blueprints, prefabs, levels and the configuration of each game system. An assets/ folder beside it holds the imported files the project uses. A project is saved in one of two layouts.

A project folder (<Name>.feather) is the editor’s default. The .feather file is a small manifest, and everything else is split into readable files under content/, so changes are easy to review in version control:

My Game/
My Game.feather manifest: name, seed, player start, level list
content/
levels/<level>/objects.json each level's objects, landscape.json and environment.json
scripts/<name>.rhai world scripts as plain Rhai
ui/screens/<name>.html, .css game UI screens; also ui/widgets/, ui/templates/, ui/stylesheet.css
data/<section>.json content: assets, materials, sounds, prefabs, items, story…
data/tables/<name>.json data tables
config/<section>.json settings: physics, weather, input, game, build…
assets/
imported/
<sha256>.glb
tex-<sha256>.png
snd-<sha256>.ogg

In the manifest and the JSON files, a value saved elsewhere is replaced by a reference such as {"$file": "content/levels/main/objects.json"} (or $text for scripts and screens). Saving rewrites only the files that changed and removes the ones the project no longer needs. Keep one .feather project per folder: saving refuses a folder that already holds another one.

A single file (project.feather.json) holds the whole project in one JSON file. The examples and game builds use this layout, and older projects open unchanged.

Imported files are named by their SHA-256 hash, so identical content is stored once.

  1. Choose File → New project… to start from an empty level with a procedural meadow landscape.
  2. Choose File → Open project… to open a .feather or .feather.json file, or File → Open example to open one of the bundled examples.
  3. Press Cmd/Ctrl+S, or choose File → Save project, to save. The first save of a new project asks for a location and offers Feather project (.feather) or Single-file project (JSON).

When you save a new <Name>.feather into a folder that already holds other files, the editor puts it in its own <Name>/ folder there. To convert a single-file project, save it with project.save to a path ending in .feather; a path ending in .json converts it back.

With the macOS app installed, double-clicking a .feather file in Finder opens it in the editor. On any platform you can also pass the file to the editor: feather-editor "My Game/My Game.feather".

Opening runs in the background. The editor shows its progress and keeps the current project until the new one has loaded and passed validation. Cancelling or a failed load leaves the current project and its undo history untouched.

Saving validates the whole project first, then copies every referenced asset into the assets/ folder beside the destination and writes each file atomically. A crash during a save never leaves a half-written file. Opening verifies each asset’s hash before loading it, so a project never depends on the editor’s private cache. A standalone texture that is missing from assets/, such as a library texture left out of version control, does not stop the project from opening: it logs a warning and the texture does not show until you import it again.

These are the top-level sections of a single-file project. A project folder keeps the same sections, split into the files shown above.

Section Contents
schema_version, name, seed Format version, display name and terrain seed
objects Scene objects of the open level; see Objects and groups
landscape, environment, spawn_position, spawn_yaw Terrain, sky and lighting, and the player start of the open level
assets, textures, sounds, fonts, materials Imported content and material assets
prefabs The prefab library; see Prefabs
levels, start_level Other levels and the level the game starts in
world_scripts, data, game Game logic, data tables and game settings
System sections One section per engine system, for example physics, weather, combat, input, navigation, ai, items, story and localization

System sections are written only when they differ from their defaults, so a small project stays small.

New projects use schema 2, which supports Groups and parent relationships. Flat schema 1 projects still open, and upgrade to schema 2 when you first add a Group or parent an object. Fields added in later engine versions load with default values.

A project can contain several levels. Each level has its own objects, landscape, environment and player start. Assets, materials, sounds, data tables, scripts, story, combat and input settings are shared by every level.

The open level is the one the editor shows and the one all scene, landscape and environment commands edit. The other levels wait in the levels section (in a project folder, under content/levels/).

  1. Open Window → Levels.
  2. Enter an id and a name, choose a Flat or Meadow base, and create the level. Alternatively, duplicate an existing level.
  3. Click a level to open it for editing. Opening a level is an undoable edit.
  4. Use Make start to choose where the game begins, and Rename or Delete to manage levels. The open level cannot be deleted. If no start level is set, the game starts in the open level.

At runtime, scripts switch levels with load_level(id).

Example: a door that takes the player to a second level

Section titled “Example: a door that takes the player to a second level”

You’ll add a cellar level and a sensor in the first level that loads it when the player walks in. Start from a new project (File → New project…). Its only level has the id main.

  1. Choose Add → Cube, name it Cellar door and set Location to 0, 0, 2, between the player start and the direction it faces.

  2. In Details → Physics, turn on Sensor so the player can walk into it.

  3. In Details → Script, click Add script, replace the source with the script below and click Apply script.

    fn trigger_enter(other) {
    if other_is_player() {
    print("Down to the cellar");
    load_level("cellar");
    }
    }
  4. Open Window → Levels. Under New level, enter cellar as the id and The Cellar as the name, choose Flat, and click Create and open.

  5. Choose Add → Crystal so the cellar has something in it.

  6. In the Levels list, click Make start next to Main · main, then click Main · main to open it again.

  7. Press Cmd/Ctrl+S to save, then Play and walk forward into the cube.

Step 6 matters: while no start level is chosen, the game starts in whichever level is open, so without it the game would start in the cellar.

Do the same from the command line:

Terminal window
feather-cli --workspace ./two-rooms command project.create \
--json '{"name":"Two Rooms"}' --save project.feather.json
feather-cli --workspace ./two-rooms --project project.feather.json command scene.add \
--json '{"kind":"Cube","name":"Cellar door","position":[0,0,2]}' --save project.feather.json
feather-cli --workspace ./two-rooms --project project.feather.json command scene.update --json '{
"id": 1,
"patch": {
"physics": {"sensor": true},
"script": {"source": "fn trigger_enter(other) {\n if other_is_player() {\n print(\"Down to the cellar\");\n load_level(\"cellar\");\n }\n}"}
}
}' --save project.feather.json
feather-cli --workspace ./two-rooms --project project.feather.json command level.create \
--json '{"id":"cellar","name":"The Cellar","base":"Flat","open":true}' --save project.feather.json
feather-cli --workspace ./two-rooms --project project.feather.json command scene.add \
--json '{"kind":"Crystal","name":"Cellar crystal","position":[0,0,0]}' --save project.feather.json
feather-cli --workspace ./two-rooms --project project.feather.json command level.update \
--json '{"id":"main","start":true}' --save project.feather.json
feather-cli --workspace ./two-rooms --project project.feather.json command level.open \
--json '{"id":"main"}' --save project.feather.json

Check it worked:

Terminal window
feather-cli --workspace ./two-rooms --project project.feather.json command level.list

The result has "open": "main" and "start": "main", and lists cellar and main with one object each. To check the trigger, simulate walking forward:

Terminal window
feather-cli --workspace ./two-rooms --project project.feather.json command game.simulate \
--json '{"frames":180,"inputs":[{"frame":0,"key":"W","pressed":true}]}'

The report’s logs include Cellar door [Script]: Down to the cellar. The simulation runs one level and does not perform the switch itself; press Play in the editor to see the cellar load.

Limit Value
Single-file project 16 MiB
Project folder 16 MiB per file, 64 MiB in total
Objects in a project 100,000
Levels 64
Level ids Lowercase letters, digits, - and _; up to 48 characters

Every change to the project is a transaction: it is validated as a whole, applied atomically and recorded as one undo step. Each change also advances the document’s revision number, which automation uses to detect conflicting edits. Opening a project clears the undo history. See Agents overview.

Terminal window
# Create a level, open it and save the project.
feather-cli --workspace ./my-game --project project.feather.json command level.create \
--json '{"id":"caves","name":"The Caves","base":"Flat","open":true}' \
--save project.feather.json
feather-cli --workspace ./my-game --project project.feather.json command level.list
# Convert the single-file project into a project folder (written into ./my-game).
feather-cli --workspace ./my-game --project project.feather.json command project.save \
--json '{"path":"My Game.feather"}'

project.open and --project accept either layout. The editor can also validate a project without opening a window:

Terminal window
cargo run --bin feather-editor -- --project my-game/project.feather.json --check