@rbxts/weather
v0.1.0
Published
Rain, snow, fog and storms for roblox-ts: one call to change the weather, zones for local weather, shelter under roofs
Maintainers
Readme
@rbxts/weather
Weather for roblox-ts: rain, snow, fog and storms in one call.
Weather.rain();
Weather.snow({ intensity: 0.4, transition: 20 });
Weather.zone(marshPart).fog();- One call per weather. Nine presets, every field adjustable, smooth transitions between any two.
- Server-driven, no remotes. Set the weather on the server and every client follows. A player who joins mid-transition picks it up where it is. Lightning flashes at the same moment for everyone.
- Local weather. Zones give a region weather of its own (fog in the marsh, snow on the peak), fading into the surrounding weather at the edge.
- Shelter. Rain stops on roofs instead of falling through them, nothing falls in caves, and sounds are muffled indoors.
- No assets to upload, no dependencies. Rain and snow use textures that ship with every Roblox client, the default sounds come from Roblox's public audio library, and the autumn leaves are the package's own images, already on Roblox.
Install
npm install @rbxts/weatherQuick start
On the server, set the weather:
import { Weather } from "@rbxts/weather";
Weather.rain({ transition: 10 });
task.wait(120);
Weather.storm();On every client, start drawing it once:
import { Weather } from "@rbxts/weather";
Weather.start();Presets
| Call | Looks like | intensity sets |
| -------------------- | -------------------------------------------- | ---------------- |
| Weather.clear() | A few white clouds, light breeze | - |
| Weather.cloudy() | Broken cloud | clouds |
| Weather.overcast() | Grey sky, slightly dim | clouds |
| Weather.fog() | Thick fog | fog |
| Weather.drizzle() | Light rain, grey sky | rain |
| Weather.rain() | Steady rain, dark clouds | rain |
| Weather.storm() | Heavy rain, strong wind, lightning | rain |
| Weather.snow() | Falling snow, white haze | snow |
| Weather.blizzard() | Driving snow, strong wind, little visibility | snow |
Each takes the same options:
Weather.rain({
intensity: 0.4, // the preset's main amount, 0-1
transition: 15, // seconds to blend in (default 5, 0 = at once)
wind: new Vector3(20, 0, 0), // and any weather field below
});Weather.set takes a preset name, or some fields to change on the current weather:
Weather.set("storm", { transition: 30 });
Weather.set({ fog: 0.6 }); // everything else staysWeather fields
| Field | Range | Drives |
| -------------- | ---------------- | ------------------------------------------------------- |
| rain | 0-1 | Rain particles, splashes, rain sound |
| snow | 0-1 | Snow particles |
| clouds | 0-1 | Clouds.Cover |
| cloudDensity | 0-1 | Clouds.Density |
| cloudColor | Color3 | Clouds.Color |
| fog | 0-1 | Atmosphere density, haze and colour |
| fogColor | Color3 | The colour fog tints towards |
| darkness | 0-1 | A colour grade that darkens and desaturates the scene |
| wind | Vector3, studs/s | Tilts rain and snow, Workspace.GlobalWind, wind sound |
| lightning | 0-1 | How often lightning flashes |
Weather.get() is the weather right now (partway through a transition), Weather.getTarget() where it is heading. PRESETS holds the presets' values and lerpParams blends two weathers.
Seasons
The season is separate from the weather: picking a preset keeps it, and zones do not have one.
Weather.setSeason("autumn", { intensity: 0.7, transition: 30 });
Weather.rain({ season: "autumn" }); // also accepted alongside any weather call
Weather.set({ season: "winter", seasonIntensity: 0.5 });
Weather.getSeason(); // { season: "autumn", intensity: 0.7 }| Season | Drawn |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| autumn | Leaves blow through the view near the ground, tumbling with the wind, then settle and fade. Each starts out of sight and blows in. More in a strong wind; intensity sets how many. |
| spring, summer, winter | Nothing yet: available to read for gameplay. |
seasonIntensity (0-1, default 1) is how strongly the season shows. Changing season fades the old one out, then the new one in. The default is summer. Like the weather, it is set on the server for everyone, or on a client for that player (reset() drops it too), and Weather.sample() includes season and seasonIntensity.
Zones
A zone gives a region its own weather. Inside it, its weather replaces the global one; outside, it fades out over blend studs.
const marsh = Weather.zone(workspace.Marsh, { blend: 30 }).fog();
const peak = Weather.zone({ position: new Vector3(0, 400, 0), radius: 150 }).blizzard();
const valley = Weather.zone({ cframe: valleyCFrame, size: new Vector3(300, 200, 300) }).clear();- A region is a part (its box; followed while it moves), a
{ cframe, size }box or a{ position, radius }sphere. The part does not have to replicate or stream in, and while it is invisible (orCanQueryis off) it does not stop rain. - A zone has no effect until its weather is set. Change it like the global weather:
marsh.rain({ transition: 10 }). - Where zones overlap, higher
prioritywins; equal priorities apply in the order they were made. setRegion,setBlend,setPriorityanddestroychange it later.
Server and client
Called on the server, everything changes the weather for all players.
Called on a client, it changes the weather for that player only, over the server's: a cutscene, an indoor dream, a per-player setting. Weather.reset() hands the player back to the server's weather. Client zones work the same way.
Any client-side call starts drawing; otherwise call Weather.start().
Gameplay
Weather.sample(position) is the weather at a point right now, zones included, on either side. Use it for rules that depend on the weather: crops watered by rain, fires that will not light, cold in a blizzard.
if (Weather.sample(field.Position).rain > 0.3) waterCrops(field);On a client, Weather.sample() with no position is what is being drawn at the camera, and Weather.getExposure() is how exposed the camera is to the sky: 0 under a roof, 1 in the open.
How it is drawn (client)
- Rain and snow fall from a grid of columns that follows the camera: 5 x 5 (80 studs across) for rain, 13 x 13 (208 studs) for slow-falling snow, so you cannot walk out of it. Each column finds the first thing below it and gives its particles just enough life to reach it: rain lands on roofs and treetops, not inside houses. A column with something above it (a cave, an overhang) stays dry. Parts that are almost invisible are ignored, as are player characters.
- Splashes on the ground near the camera while it rains.
- Sky. Fog is laid over the game's own
Atmosphere(or one the package adds), clouds are set onTerrain.Clouds(added if missing), and aColorCorrectionEffectdarkens the scene.Lighting.BrightnessandClockTimeare left alone, so a day/night cycle keeps working. - Wind sets
Workspace.GlobalWind, which sways terrain grass and moves clouds. - Screen drops (opt in with
screenDrops: true): water lands on the lens while the camera is out in the rain, most when looking up or into the wind, none under a roof. The drops are small glass balls just in front of the camera, so they refract the scene behind them, blurred out of focus by aDepthOfFieldEffectthat only reaches the first stud. Some run down the screen; all fade. The blur is only enabled while drops are showing. Refraction needs a graphics quality that renders glass; on low settings the drops are plain translucent blobs. - Storm clouds: Roblox's own clouds turn into a flat sheet when the sky is fully covered, so dark, cloudy weather adds two drifting layers of real storm-cloud texture overhead (the lower one faster, for depth). They fade in with the weather: faint when overcast, solid in rain, a heavy sky in a storm, lit from within by lightning. Under them the fog is kept thin enough to see them. Turn off with
stormClouds: false;appearance.cloudTextureswaps the texture. - Lightning flashes the colour grade; thunder follows a moment later if you gave it a sound.
Weather.stop() puts everything back as it was.
Configuration
Weather.configure({
sky: true, // drive Clouds, Atmosphere and the colour grade
wind: true, // drive Workspace.GlobalWind
particles: 1, // rate multiplier (default 0.5 on touch devices)
shelter: true, // stop rain at roofs, keep caves dry
screenDrops: false, // water drops on the screen in the rain
stormClouds: true, // storm cloud layers overhead in dark weather (needs sky)
focus: () => character.GetPivot().Position, // where weather is drawn around (default: camera)
ignore: [workspace.Effects], // more instances that do not stop rain
sounds: {
rain: "rbxassetid://...",
wind: "rbxassetid://...",
thunder: ["rbxassetid://...", "rbxassetid://..."], // one is picked per strike
volume: 0.5,
},
appearance: {
rainTexture: "rbxassetid://...", // a streak texture; then set rainSquash to 0
rainColor: Color3.fromRGB(190, 200, 215),
rainSize: 0.15,
rainSquash: -3, // negative stretches drops into streaks
rainTransparency: 0.85,
snowTexture: "rbxassetid://...",
snowColor: Color3.fromRGB(255, 255, 255),
snowSize: 0.22,
splashColor: Color3.fromRGB(205, 215, 228),
leaves: [{ texture: "rbxassetid://...", size: 1, tint: Color3.fromRGB(255, 230, 200) }], // replaces the default leaves
cloudTexture: "rbxassetid://...", // the storm cloud layers: tileable, seen from below
leafSize: 1, // studs, before each picture's own size
leafMeshes: ["rbxassetid://..."], // curved cards the pictures are drawn on, one picked per leaf
},
});Turn sky off if your game manages its own Atmosphere and Clouds and only wants precipitation, wind and sound from the package. Read the weather with Weather.sample() and drive your sky from it.
Sounds default to recordings from Roblox's public audio library, free for every experience: a heavy rain loop and four thunder strikes from Pro Sound Effects, and a howling wind from DistroKid's official account. Pass your own ids to replace them (thunder takes one id or a list to pick from at random), or "" to turn one off. Each strike is pitched a little differently.
Licence
ISC
