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>.oggIn 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.
Create, open and save
Section titled “Create, open and save”- Choose File → New project… to start from an empty level with a procedural meadow landscape.
- Choose File → Open project… to open a
.featheror.feather.jsonfile, or File → Open example to open one of the bundled examples. - 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.
What a project contains
Section titled “What a project contains”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.
Schema versions
Section titled “Schema versions”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.
Levels
Section titled “Levels”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/).
- Open Window → Levels.
- Enter an id and a name, choose a Flat or Meadow base, and create the level. Alternatively, duplicate an existing level.
- Click a level to open it for editing. Opening a level is an undoable edit.
- 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.
-
Choose Add → Cube, name it
Cellar doorand set Location to0,0,2, between the player start and the direction it faces. -
In Details → Physics, turn on Sensor so the player can walk into it.
-
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");}} -
Open Window → Levels. Under New level, enter
cellaras the id andThe Cellaras the name, choose Flat, and click Create and open. -
Choose Add → Crystal so the cellar has something in it.
-
In the Levels list, click Make start next to Main · main, then click Main · main to open it again.
-
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:
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.jsonfeather-cli --workspace ./two-rooms --project project.feather.json command level.open \ --json '{"id":"main"}' --save project.feather.jsonCheck it worked:
feather-cli --workspace ./two-rooms --project project.feather.json command level.listThe result has "open": "main" and "start": "main", and lists cellar and main with one object
each. To check the trigger, simulate walking forward:
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.
Limits
Section titled “Limits”| 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 |
Undo and revisions
Section titled “Undo and revisions”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.
Automate it
Section titled “Automate it”# 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:
cargo run --bin feather-editor -- --project my-game/project.feather.json --check