Start typing to search packages!
rain-system
By @hakochanjp
Roblox
MirroredRainSystem
雨が降ることに特化した Roblox 向け ウェザーシステム モジュール。
ℹ️ パーティクル単体の制御は別モジュール
hakochanjp/rain-particleを参照。RainSystem はそれらをまとめて「雨を降らせる体験」全体を扱う上位レイヤーを目指します。
ステータス
✅ v1 実装中 — クライアント完結型の Init / SetState / Preset / Layers API が利用可能。
アセット(雨粒テクスチャ・雨音)は次の手順で同梱:UploadFiles/asphalt/ に配置 → task asphalt-sync。
インストール(予定)
利用側プロジェクトの wally.toml:
[dependencies]
RainSystem = "hakochanjp/rain-system@0.1.0"
wally install 後に Packages/RainSystem が生成されます。
使用例
local RainSystem = require(ReplicatedStorage.Packages.RainSystem)
-- クライアントスクリプトで一度だけ呼ぶ
RainSystem.Init({ shelterTarget = "Character" })
-- プリセットで天候を切り替え(fade duration 秒)
RainSystem.Preset.HeavyRain(3.0)
-- 雲の量と雨の強さを個別指定(独立制御)
RainSystem.SetState({ cloud = 0.8, rain = 0.45 }, 2.0)
-- intensity ショートカットは cloud と rain を同値にセット(後方互換)
RainSystem.SetState({ intensity = 0.45 }, 2.0)
-- 状態変化を購読
RainSystem.StateChanged:Connect(function(new, old)
print(string.format("cloud %.2f rain %.2f", new.cloud, new.rain))
end)
-- パワーユーザー向け: レイヤー個別制御
RainSystem.Layers.Atmosphere:SetEnabled(false) -- 大気効果だけ切る(manageLighting=false 時は nil なので注意)
-- 落雷をカスタム VFX にフック(Thunder.Struck シグナル)
RainSystem.Layers.Thunder.Struck:Connect(function(info)
print(string.format("[Strike] dist=%.1f pos=%s", info.distance, tostring(info.position)))
end)
-- 雨粒テンプレートを差し替え(Particle)/着水テンプレートを差し替え(Splash)
RainSystem.Layers.Particle:SetTemplate(myCustomRainDropEmitter)
RainSystem.Layers.Splash:SetTemplate(myCustomSplashEmitter)
-- 終了
RainSystem.Destroy()
Lighting をホストに委譲する(manageLighting)
利用側が Lighting / Atmosphere / 明るさを独自の環境システムで完全管理したい場合、
manageLighting = false を指定すると RainSystem は Lighting サービスと Atmosphere
インスタンスの定常状態を一切変更しない。
RainSystem.Init({ manageLighting = false })
falseのとき:Lighting.Brightness/Atmosphere.Density/RainSystem_ColorCorrectionを作成も変更もしない。Thunder のグローバル Brightness フラッシュも行わない (RainSystem.Layers.Atmosphereはnilを返す)。- 雨粒・雲・着水・水たまり・波紋・雨音・雷の PointLight / 3D 音・画面水滴は従来どおり動作する。
- Cloud(
Workspace.Terrain.Clouds)は対象外。rain 固有の視覚として RainSystem が管理を継続する。 - 既定は
true(省略時は現状の挙動を維持)。
Atmosphere の見た目を調整する(atmosphere)
Atmosphere レイヤーの補間端点(晴れ *Clear / 嵐 *Storm 時の値)を Init で上書きできる。
省略したフィールドは既定値(brightnessClear=2.0 / brightnessStorm=0.6 / saturationClear=0.0 /
saturationStorm=-0.3 / densityClear=0.0 / densityStorm=0.45)が使われる。
RainSystem.Init({ atmosphere = { brightnessStorm = 0.4, densityStorm = 0.6 } })
manageLighting = false 時は Atmosphere レイヤー自体を生成しないため、この設定は無視される。
雨音・雷音を SoundGroup に流す(soundGroup)
雨音(outdoor/indoor)と雷音を、利用側が用意した SoundGroup 配下に接続できる。
設定画面の音量スライダー等でグループ Volume を一括制御している場合、雨/雷の音も
それに追従するようになる(RainSystem 内部の音量計算とグループ Volume が乗算で効く)。
-- SoundGroup インスタンスを直接渡す
RainSystem.Init({ soundGroup = SoundService.SFX })
-- もしくは SoundService 直下の SoundGroup 名(string)で渡す
RainSystem.Init({ soundGroup = "SFX" })
-- ランタイムに変更 / 解除も可能
RainSystem.SetSoundGroup(SoundService.BGM)
RainSystem.SetSoundGroup("SFX")
RainSystem.SetSoundGroup(nil) -- 未接続に戻す
print(RainSystem.GetSoundGroup()) -- 現在の SoundGroup(未設定なら nil)
SetSoundGroup後は生成済みの常設 Sound(outdoor/indoor)にも反映され、以後の落雷 Sound も最新の group を読む。- string が
SoundService:FindFirstChildで解決できなければ warn のみで未接続のまま継続(クラッシュしない)。 - 省略 /
nilのときは SoundGroup 未設定(従来どおりの挙動)。
屋内/屋外の雨表現
雨粒自体は RainParticle の粒単位オクルージョン(Raycast)で制御される: 屋内ではスポーンせず、屋根面でちょうど消えるため、屋内にいても窓越しに外の雨が見える。天候全体が屋内で止まることはない。
音・カメラ水滴・水たまり・波紋・着水・雷の減衰などの演出は、ShelterState.smoothed(頭上遮蔽率 ratio を時定数 τ=1 秒で時間平滑化した連続値。毎 Heartbeat 更新)を参照し、屋内外の境界をなめらかに遷移する(瞬時切替・チラつきなし)。
遮蔽判定の追跡対象(頭上 Raycast の起点)はランタイムに切り替え可能。ファーストパーソン / 自由視点カメラの上方判定にも使える。
RainSystem.Init({ shelterTarget = "Character" }) -- 既定はキャラクター
RainSystem.SetShelterTarget("Camera") -- カメラ位置で遮蔽判定
print(RainSystem.GetShelterTarget()) -- "Camera"
Debug UI(Vide ベース)
開発時に天候パラメータをリアルタイム操作できるフローティングパネルを表示。 ScrollingFrame 内に State / Preset / Cloud / Rain / Fade / Wind / ShelterTarget / Layer toggle / Strike / Recent log を一覧。
RainSystem.ShowDebug() -- パネル表示
RainSystem.HideDebug() -- パネル非表示
公開レイヤー一覧
RainSystem.Layers.* 経由でアクセス可能(全レイヤーが :SetEnabled(bool) を持つ):
| Layer | 役割 |
|---|---|
Atmosphere | Lighting / Atmosphere の色・密度・空ティント |
Audio | 屋外/屋内別の雨音 BGM クロスフェード |
CameraDrop | 画面に張り付く水滴 GUI |
Cloud | Workspace.Terrain.Clouds 連動 |
Particle | 雨粒 ParticleEmitter(SetTemplate / SetTexture / SetShelterTarget) |
Puddle | 地面の水たまり Part 散布(距離ベース despawn 対応) |
Ripple | 水面着水時の同心円 Decal |
Splash | 着水パーティクル(SetTemplate / GetTemplate) |
Thunder | 落雷フラッシュ + 3D 音響、Struck シグナル + TriggerStrike() |
開発
rokit install # ツールチェーン(rojo / wally / stylua / selene / asphalt / task)を導入
wally install # 依存パッケージを取得
task serve # dev.project.json で Rojo serve + sourcemap watch
Lint / Format
| サブコマンド | 用途 |
|---|---|
task selene | selene src tests を実行(src と tests の静的解析) |
task lint | selene src tests + stylua src tests --check(CI 向けの非破壊チェック) |
task lint-fix | stylua src tests でフォーマット差分を自動修正(selene 警告は手動対応) |
task lint がフォーマット差分で fail したら task lint-fix で一括解消できます(selene の警告は別途コード修正が必要)。
アセット管理(Asphalt)
画像・音声などのアセットは Asphalt で管理しており、
UploadFiles/asphalt/ 配下のファイルを Roblox クラウドにアップロードして
src/Assets.luau を自動生成します。生成された Assets.luau は wally 配布対象に含まれます。
パーティクル画像の再生成(Python + PIL)
UploadFiles/asphalt/images/ 配下の PNG(raindrop / splash_ground / splash_water / splash_metal / camera_drop)は scripts/gen_assets.py で deterministic に生成 されています。テクスチャを微調整したい場合は Python スクリプトを編集して再実行 → task asphalt-sync の順で反映します。
python scripts/gen_assets.py # 5 つの PNG を 512x512 で再生成
task asphalt-sync # Roblox クラウドに反映 + Assets.luau 更新
依存: Python 3 + Pillow (
pip install Pillow)。出力は乱数を使わないので何度実行してもバイト同一です([[asset-generation]] の 1:1 方針を尊守)。
cp .env.example .env # ASPHALT_API_KEY を埋める(Roblox Creator Dashboard で発行)
task asphalt-dry-run # アップロード予定を確認
task asphalt-sync # 実アップロード + src/Assets.luau 再生成
| サブコマンド | 用途 |
|---|---|
task asphalt-sync | クラウドへアップロードし src/Assets.luau と asphalt.lock.toml を更新 |
task asphalt-dry-run | 変更予定のみ確認(実アップロードしない) |
task asphalt-debug | .asphalt-debug/ にローカル出力(クラウド・Studio 不要) |
ℹ️
asphalt.tomlの[creator]はデフォルトで rain-system 配布主体のユーザー ID を指しています。グループ運用に切り替える場合はtype = "group"に変えた上で、Roblox Creator Dashboard 側で API キーの Eligible Creators にそのグループを追加してください。
ディレクトリ構成
RobloxRainSystem/
├── src/ # ライブラリ本体(wally で配布)
│ ├── init.luau # 公開 API(Init / SetState / Preset / Layers / Debug 等)
│ ├── Assets.luau # Asphalt が自動生成(コミット推奨/手動編集禁止)
│ ├── Debug.luau # Vide ベースの開発者パネル
│ ├── Types.luau # 公開・内部型定義(WeatherState / LayerDeps 他)
│ ├── State/ # Rodux Store + fade Manager + Preset
│ ├── Shelter/ # 屋内/屋外判定(CheckPoint / Track)
│ └── Layers/ # 9 レイヤー(Atmosphere / Audio / CameraDrop /
│ # Cloud / Particle / Puddle / Ripple /
│ # Splash / Thunder)
├── tests/ # 動作確認スクリプト(wally 配布対象外)
│ ├── RainSystemTest/ # Studio Play Solo 用の統合シナリオ
│ │ ├── init.client.luau
│ │ ├── LightningEffect.model.json # 落雷 VFX テンプレ
│ │ └── RainParticles.model.json # 雨粒 / 着水テンプレ
│ └── Unit/ # pure-logic スモークテスト(21+ checks)
│ └── init.client.luau
├── docs/superpowers/
│ ├── specs/2026-05-25-rain-system-design.md # v1 設計仕様
│ └── plans/2026-05-25-rain-system-v1.md # 初期実装計画
├── UploadFiles/
│ └── asphalt/ # Asphalt アップロード対象(images/ sounds/)
├── CHANGELOG.md # バージョン別変更履歴
├── default.project.json # リリース用 Rojo 設定(src のみ)
├── dev.project.json # 開発用 Rojo 設定(src + tests + Packages)
├── asphalt.toml # Asphalt 設定
├── asphalt.lock.toml # アセットIDロック(コミット必須)
├── Taskfile.yaml # 開発タスク(serve / lint / asphalt-sync 等)
├── wally.toml
├── rokit.toml
├── stylua.toml
├── selene.toml
├── .env.example # ASPHALT_API_KEY テンプレート
├── LICENSE
└── README.md
リファレンス
| ドキュメント | 内容 |
|---|---|
CHANGELOG.md | バージョン別の Added / Changed / Fixed / Performance / Tests |
docs/release-flow.md | Wally publish の手順(lint / version bump / Unreleased 置換 / tag / publish) |
docs/superpowers/specs/2026-05-25-rain-system-design.md | v1 設計仕様(ゴール・原則・アーキテクチャ・レイヤー差し込み口) |
docs/superpowers/plans/2026-05-25-rain-system-v1.md | 初期実装計画(タスク分解 / 受け入れ条件) |
tests/Unit/init.client.luau | Studio Play Solo で走る pure-logic スモークテスト(PASS/FAIL を Output に出力) |
tests/RainSystemTest/init.client.luau | Debug UI 起動 + テンプレ適用 + 落雷ハンドラ配線の統合シナリオ |
両テストは
dev.project.jsonでStarterPlayer.StarterPlayerScripts.Tests配下に配置されるため、Play Solo 1 回で同時に実行されます。Output ウィンドウに[PASS] / [FAIL](Unit)と[Scenario](RainSystemTest)の両方のログが混在して出ます。
ライセンス
MIT License © 2026 hakochanjp
Package Details
Install command (Click to copy)
Version
0.11.5
License
MIT
Safe for commercial use
Automated license review — not legal advice.
