Releases / v0.98.0

v0.98.0 Stays Smooth

2026-09-26 Latest

Exported games with animated characters run for as long as you play them, models load without stopping the game, and a settings screen can reach the effects players most often want turned off.

Exported games keep running

A game with animated characters (first-person arms, animated enemies) slowed down steadily as an export, then stopped drawing parts of the level and closed after a minute or two. Play in the editor was unaffected, so it only showed up in builds. Exported games now run as smoothly at the hour mark as at the start.

Two more things reach exported games now. The project's vsync setting and app.setVsync apply; a build used to keep vsync on whatever they said. And a game that crashes writes crash.txt into its save folder, beside its save.* files, saying what went wrong. On Windows, where a game has no console, that file is the only record of a crash.

Models load without freezing the game

Giving a node a model with node.model, or spawning a prefab that brings one, loaded the model on the spot, and spawning several at once could freeze the game for a moment. Models now load in the background: the game keeps running, and the node appears as soon as its model is in. Loading is faster too, since a model's textures are now decoded once instead of twice.

When a model has to be there on the very frame it is used, the parts of a ragdoll for example, load it earlier, on a menu or a loading screen:

lua
assets.preload({ "models/arm.glb", "models/leg.glb" }, function(failed)
  -- every model is in; `failed` lists any that could not load
end)

perf.ms("models") shows how much of a frame loading models takes.

A settings screen that turns off what players ask for

getComponent("PostProcess") now reads and writes chromatic aberration, lens distortion and film grain (aberration, distortion, grain; 0 is off), and the whole colour grade: exposure, contrast, saturation, temperature, tint, lift, gradeGamma and gain. Setting the grade back to neutral is 0 for the first four and 1 for the rest.

Dragging a slider fires onChanged (and ui.changed) on every frame its value moves, with the new value already on the slider. It never fired before, so a volume slider moved but saved nothing. A slider also stays where the player dragged it when the screen redraws, while a Reset button that changes the value still moves it.

ui.make builds a list with no items as an empty element instead of raising an error, so a leaderboard or a replay list with nothing in it yet needs no special case.

The signed-in player is there from the first frame

account.state() finds a player who signed in, in your game or in the Hub, the first time you ask, in any scene, without a network call. While it looks it answers "starting" rather than "signedOut", so a Sign in button shown only to signed-out players never flashes at somebody who is signed in.

Ambient occlusion leaves the distance alone

Screen-space ambient occlusion laid dark patches over faraway ground that shimmered as the camera moved, and showed through fog. It now fades out with distance and with fog. Contact shadows up close look the same as before.

Smaller fixes

  • A body teleported by another script calling its function (a Restart button, say) reads its new position from node.tickPos on the very next physics step, including while physics.pause is on. It could read the old spot for a step or two, long enough for a check there to fire.
  • floptle shot and floptle run use the project's UI style sheets, so a headless screenshot shows menus as the game does. A sheet with an error in it is reported by floptle run.

Upgrading

Nothing to do. A node given a model mid-game now draws nothing for the few frames the model takes to load; if that shows, preload the model. If you were loading models yourself on a menu to avoid a freeze, assets.preload does the same and tells you when it is done.

Floptle Hub

Linux x86_64 7.9 MB Download → sha256 14e2e93d9f6566056e840558925bb02deed6439af6a8707bbd2c75b3cc4d0a62
macOS Apple Silicon 5.9 MB Download → sha256 c52a3913aa27c82574e9384e9af11d1d3ec8edd9a4c532c82f96c0521bdc4892
macOS Intel 6.4 MB Download → sha256 8a3ba7c147e3b69b8a06b67776cf1a53772ca04a3127ec23bb9097462f1fccde
Windows x86_64 7.3 MB Download → sha256 e89a7cceb0d53e79749abc6a13ab435c98849ebbb49a98a3c48e42a03b666063

Engine

Linux x86_64 34.2 MB Download → sha256 ff6ac07615c2856a07d4646a56df7b85593c197ccfd914c8e0b450b08bc2a2b9
macOS Apple Silicon 27.9 MB Download → sha256 a1c6536244647517168b77562e9013efe62638ee761df2cb746ba4a8b06761d8
macOS Intel 30.0 MB Download → sha256 005feb9de38d7abbdd4389224e941f05512a7d1465bd356e274b8d272abbcbc8
web 4.4 MB Download → sha256 ab2c7649a31cd32618ae6b50a2fe40d983da48f3503d40828801ae2560ba6de3
Windows x86_64 34.0 MB Download → sha256 237d26e49e82c55e4f08f33674d4f443999f069f534568eeb9b78b3aea0e3368

The binaries are not signed yet. On macOS, right-click the app and pick Open the first time. On Windows, if SmartScreen appears, pick More info then Run anyway.