Forest Logo
search
package_2

rain-system

By @hakochanjp

Roblox

Mirrored

RainSystem

雨が降ることに特化した 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.Atmospherenil を返す)。
  • 雨粒・雲・着水・水たまり・波紋・雨音・雷の 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役割
AtmosphereLighting / Atmosphere の色・密度・空ティント
Audio屋外/屋内別の雨音 BGM クロスフェード
CameraDrop画面に張り付く水滴 GUI
CloudWorkspace.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 seleneselene src tests を実行(src と tests の静的解析)
task lintselene src testsstylua src tests --check(CI 向けの非破壊チェック)
task lint-fixstylua 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.pydeterministic に生成 されています。テクスチャを微調整したい場合は 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.luauasphalt.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.mdWally publish の手順(lint / version bump / Unreleased 置換 / tag / publish)
docs/superpowers/specs/2026-05-25-rain-system-design.mdv1 設計仕様(ゴール・原則・アーキテクチャ・レイヤー差し込み口)
docs/superpowers/plans/2026-05-25-rain-system-v1.md初期実装計画(タスク分解 / 受け入れ条件)
tests/Unit/init.client.luauStudio Play Solo で走る pure-logic スモークテスト(PASS/FAIL を Output に出力)
tests/RainSystemTest/init.client.luauDebug UI 起動 + テンプレ適用 + 落雷ハンドラ配線の統合シナリオ

両テストは dev.project.jsonStarterPlayer.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

check_circle

Safe for commercial use

Automated license review — not legal advice.