Multi-file Camera Scripts
So far we've treated a camera as a single .luau file. As a camera grows, it's often nicer to split it across several files - inputs in one place, math helpers in another, and so on. To do this, a camera can instead be a folder containing a package.json and as many .luau files as you like.
The game treats any folder in Behaviors that contains a package.json as a single camera. Everything else works exactly as before: the camera still shows up in the Cameras panel, still has a config, and still defines the same tick, onGui, and friends.
The built-in Free Camera is a good example of this layout:
Behaviors
└───aa.freecam.luau
├───package.json
├───main.luau
├───inputs.luau
├───util.luau
└───emotes.luau
Note
The folder name is up to you, but using the same author.cameraname convention as single-file scripts helps avoid collisions.
The folder itself behaves just like a single script file would - drop it into your user camera folder (C:\Users\[USERNAME]\Documents\Another-Axiom\A2\Cameras\Behaviors) and the game will pick it up and hot-reload it on save.
The package.json
The package.json tells the game how to load your camera and carries some descriptive metadata about it. Here is the Free Camera's:
{
"name": "anotheraxiom.freecam",
"displayName": "Free Camera",
"version": "0.0.1",
"description": "A floating camera that can be manually controlled with keyboard and gamepad.",
"main": "main.luau",
"keywords": ["freecam", "controller", "keyboard"],
"author": "Another Axiom",
"defaultKeybind": "X"
}
| Field | Required | Description |
|---|---|---|
main |
Yes | The entry-point file, relative to the package folder. This is the file the game loads and where it looks for tick, onGui, etc. The package won't load without it. |
name |
Yes | A unique identifier for the camera. Use a reverse-domain-style id like anotheraxiom.freecam to avoid colliding with other authors' cameras. |
displayName |
No | The human-friendly name shown in the Cameras panel. |
description |
No | A short summary of what the camera does. |
version |
No | A version string for your own tracking. Prefer semantic versioning (e.g., "1.0.0"). |
keywords |
No | A list of tags describing the camera. |
author |
No | Who made the camera. |
defaultKeybind |
No | A key to bind the camera to by default (e.g. "X"). Leave it as "" for no default. |
url |
No | A link to the camera's homepage or source. |
Splitting code across files
Inside the package, your entry file can pull in other files with require. Each required file is its own module: it builds up a table (or any other value) and returns it, and require hands that value back to the caller.
require takes a path relative to the file doing the requiring. Sibling files are referenced by name, and you can organize deeper layouts with subfolders.
The same globals you use in a single-file script (camera, config, Vec3, Gui, and so on) are available in every file of the package - you don't need to pass them around or re-import them.
Warning
require() acts like a copy of the module. Any changes to variables made in an imported script will not be reflected in a different script that requires the same module.
Subfolders
Paths are relative to the file calling require, so a file inside lib/ would reach a sibling with require("helpers"), not require("lib/helpers").
Converting an existing script
Turning the single-file myname.mycamera.luau from Getting Started with Scripting into a package is straightforward:
- Make a new folder named
myname.mycamera.luauin yourBehaviorsfolder. - Move your existing script into it and rename it
main.luau. -
Add a
package.jsonnext to it: -
Save. The camera will reload, and you can now start pulling helper code out of
main.luauinto sibling files as it grows.
Experiment
Move a self-contained piece of your camera - say a helper function or a table of constants - into its own file, return it, and require it back into main.luau.
What's next?
- Review the Configuration page to see how config files pair with your camera.
- Examine the built-in cameras for real multi-file examples - the
aa.freecampackage is a good place to start.