Execution model¶
Asset management¶
A useful pattern is to keep all assets within your project for immediate access. Let's say a project is structured like such:
- src/
- Assets/
- Character.rbxm (Model)
- Controllers/
- MyController.lua (ModuleScript)
- Util/
- Signal.lua (ModuleScript)
- Date.lua (ModuleScript)
- Thread.lua (ModuleScript)
- init.meta.json (Renames 'src' to 'MyProject')
- Assets/
We can get other modules and assets in MyController.lua
with this code:
-- MyProject/Controllers/MyController.lua
local myProject = script:FindFirstAncestor("MyProject")
local Signal = require(myProject.Util.Signal)
local Date = require(myProject.Util.Date)
local Thread = require(myProject.Util.Thread)
local character = myProject.Assets.Character
Tip
If you need a specific file, scripts run with Rostruct contain the _ROOT
and _PATH
globals to access the root directory and the current file location, respectively.
Catching Rostruct errors¶
Functions like Rostruct.fetch
and Package:require
use Promises to manage yielding and error handling.
Errors thrown during runtime can be caught using the Promise:catch()
method:
package:start()
:catch(function(err)
if Promise.Error.isKind(err, Promise.Error.Kind.TimedOut) then
warn("Script execution timed out!")
else
warn("Something went wrong: " .. tostring(err))
end
end)
Best practices¶
- Only one LocalScript, if any, should manage module runtime
- Code should not rely on services like CollectionService that expose you to the client, so use an alternative
- LocalScripts should try to finish ASAP and avoid yielding the main thread if possible
- The codebase should never be exposed to the
game
object to prevent security vulnerabilities