Forest Logo
search
package_2

rain-particle

By @hakochanjp

Roblox

Mirrored

RainParticle

カメラまたは自キャラの周辺にパーティクルを降らせる Roblox 向け クライアント専用 モジュール。

⚠️ クライアント専用:requireRainParticle.newLocalScript / RunContext = Client のスクリプトからのみ呼び出してください。サーバー側で new を呼ぶと error します。

特徴

  • カメラ / キャラ追従FollowTarget で基準点を切り替え可能(キャラがリスポーン中は自動でカメラにフォールバック)
  • Template ベースの見た目 — Studio Explorer で作り込んだ ParticleEmitter を渡すだけでその見た目を再現
  • Rain / Snow プリセット同梱RainParticle.Preset.Rain(template) / RainParticle.Preset.Snow(template) でいきなり使える
  • 複数インスタンス同時稼働 — クラス設計のため「豪雨+霧+桜吹雪」などのレイヤー演出が可能
  • 落下制御ロックFallSpeed / FallDistance から Lifetime を自動計算し、実際の落下距離が保証される
  • 軽量実装 — パーティクルごとに Part を作らず Attachment を使用
  • Strict モード--!strict、selene / stylua で品質チェック済み

インストール

利用側プロジェクトの wally.toml:

[dependencies]
RainParticle = "hakochanjp/rain-particle@0.2.0"

そして wally installPackages/RainParticle が生成される。

使い方

最小サンプル

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Packages = ReplicatedStorage:WaitForChild("Packages")

local RainParticle = require(Packages.RainParticle)

-- Studio Explorer で作った ParticleEmitter を Template として用意
local template = ReplicatedStorage:WaitForChild("MyRainTemplate") :: ParticleEmitter

local rain = RainParticle.new({
    FollowTarget = RainParticle.Enum.FollowTarget.Character,
    Template     = template,
    Rate         = 100,
    AreaSize     = Vector3.new(60, 1, 60),
    Height       = 25,
    ForwardOffset = 20,
    FallSpeed    = 30,
    FallDistance = 50,
})
rain:Start()

動作中の設定更新

-- Rate だけ変える(ループは止まらない)
rain:Update({ Rate = 500 })

-- 一時停止(破棄せず生成だけ止める)
rain:Update({ Rate = 0 })

-- 見た目だけ差し替え
rain:Update({
    EmitterProperties = {
        Color         = ColorSequence.new(Color3.fromRGB(180, 220, 255)),
        LightEmission = 0.3,
    },
})

EmitterProperties のリセット

差分マージ仕様のため、一度設定した値は同じキーを再指定するまで残ります。「未指定状態に戻す」場合は RainParticle.None sentinel を使ってください。

-- 全クリア(Template 由来の見た目に戻す)
rain:Update({ EmitterProperties = RainParticle.None })

-- 特定キーだけ取り消し
rain:Update({ EmitterProperties = { LightEmission = RainParticle.None } })

なお Update({ EmitterProperties = {} }) は「変更なし」として扱われます。

粒単位オクルージョン(Occlusion)

Occlusion = true を指定すると、生成点の直上 Raycast で屋内判定を行い、屋内なら該当粒をスポーンしません。さらに落下経路上の下向き Raycast で屋根・庇等の遮蔽面に当たった場合は Lifetime をその距離にクランプし、粒が遮蔽面でちょうど消えるようにします(既定 false・完全後方互換)。

-- 粒単位オクルージョン: 屋内にスポーンせず、屋根で粒が止まる
local rain = RainParticle.new(RainParticle.Preset.Rain(nil, {
    Occlusion = true,
}))
rain:Start()

OcclusionParams: RaycastParams? で Raycast のフィルタを上書きできます(省略時の既定: Exclude 空 / IgnoreWater = true / RespectCanCollide = false)。RainParticle.None を渡すと未指定状態に戻せます。

💡 近似・制約:Lifetime クランプは鉛直落下前提のため、SpreadAngle 等で粒を斜めに飛ばすと消える位置は近似になります(既定テンプレートは真下落下)。透明パーツ(ガラス等)も遮蔽として扱われます。下向き Raycast はキャラクターにもヒットします(雨が人に当たって消える見た目)。コスト目安は 1 粒あたり最大 2 Raycast(Rate 600/s で毎フレーム約 20 本)。

プリセット(Rain / Snow)

主要パターン用の工場関数を同梱しています。Template は省略可能で、省略するとリポジトリ同梱のテクスチャ(hakochanjp アカウントにアップロード済み)を使います。

-- もっとも短い書き方:同梱テクスチャでそのまま動く
local rain = RainParticle.new(RainParticle.Preset.Rain())
rain:Start()

-- 同梱テクスチャ + override
local snow = RainParticle.new(RainParticle.Preset.Snow(nil, {
    Rate = 40,
    FallSpeed = 8,
}))
snow:Start()

-- 自前テクスチャを使いたい場合
local myTemplate = Instance.new("ParticleEmitter")
myTemplate.Texture = "rbxassetid://<your_image_id>"
local custom = RainParticle.new(RainParticle.Preset.Rain(myTemplate))
custom:Start()

overrideEmitterProperties はプリセットの EmitterProperties と per-key マージされます(RainParticle.None で削除も可)。override.Template は無視され、常に第 1 引数の Template(または同梱)が採用されます。

同梱テクスチャ

プリセットテクスチャサイズImage ID用途
Preset.Rainassets/rain_streak.png512 × 51297568157179715square 中央に 1 本の雨粒 streak(水平方向に描画 → VelocityParallel で 90° 回転して縦の雨に)
Preset.Snowassets/snow_dot.png128 × 128127825484280482radial フェードの柔らかい白丸

Image ID は RainParticle.Preset.RainTextureId / RainParticle.Preset.SnowTextureId でも参照できます(自作 ParticleEmitter で同じテクスチャを使いたいときに便利)。

⚠️ 本番運用時の注意:同梱テクスチャは「お試し用」です

Preset.Rain() / Preset.Snow()引数なし形式が参照するテクスチャは hakochanjp 個人アカウントにホストされています。Roblox のモデレーション・アカウント凍結・将来的な削除などが起きると、downstream の本番ゲームの雨/雪が黙って消えたり透明な四角になる可能性があります。

本番プロジェクトでは必ず以下のいずれかにしてください

  1. 推奨: assets/rain_streak.png / assets/snow_dot.png を自分のアカウントに再アップロードし、Preset.Rain(myTemplate) の形で自前 Template を渡す
  2. または Preset.RainTextureId / Preset.SnowTextureId を参照しつつ、リスクを自分で受け入れる
-- 推奨パターン
local myTemplate = Instance.new("ParticleEmitter")
myTemplate.Texture = "rbxassetid://<自分でアップロードした image id>"
local rain = RainParticle.new(RainParticle.Preset.Rain(myTemplate))
rain:Start()

💡 Decal ID と Image ID の違い:Asset Manager 経由でアップロードすると Decal(AssetTypeId=13)の ID が表示されますが、ParticleEmitter.Texture が要求するのは内側の Image(AssetTypeId=1)の ID です。Studio 上で Asset Manager から Template にドラッグ&ドロップすると自動的に Image ID が入りますが、ID を手で貼り付ける場合は次のように内側 ID を抽出してください。

-- 編集モードのコマンドバーで実行
local model = game:GetService("InsertService"):LoadAsset(<DECAL_ID>)
print(model:FindFirstChildOfClass("Decal").Texture) -- → rbxassetid://<IMAGE_ID>

複数レイヤー演出

local heavyRain = RainParticle.new(RainParticle.Preset.Rain(rainTemplate))
local snow      = RainParticle.new(RainParticle.Preset.Snow(snowTemplate))
heavyRain:Start()
snow:Start()

すべてのインスタンスは workspace.RainParticleContainers 配下の子 Folder として整理されます。

停止・破棄

rain:Stop()    -- スポーン停止(既存粒は自然消滅)。_accumulator もリセット
rain:Destroy() -- 完全破棄(既存粒も即座削除)

💡 一時停止と「停止」の使い分け

  • 短時間で再開する用途には rain:Update({ Rate = 0 }) を使う。PreRender 接続は維持され、Rate を戻すだけで即時再開できる。
  • 本当に止める(しばらく使わない / リソースを解放したい)場合は rain:Stop() を使う。PreRender 接続が切断され、内部の _accumulator も 0 にリセットされる。次の :Start() までスポーン処理は一切走らない。
  • 完全に捨てる場合は rain:Destroy()。インスタンスを再利用しないなら必ずこれを呼ぶ。

動作中の Template 差し替え

Update({ Template = newTemplate })動作中に Template を差し替え可能です。差し替え後にスポーンされる粒から新しい Template が使われます(既に飛んでいる粒は寿命まで旧 Template の見た目のまま)。

-- 雨 → 桜吹雪に切り替え(既存の雨粒はそのまま落ち切る)
rain:Update({ Template = sakuraTemplate })

なお Template は RainParticle.None での「未指定に戻す」操作はサポートしません(必ず ParticleEmitter インスタンスを渡してください)。

公開API

インスタンス生成

関数説明
RainParticle.new(config: RainInitConfig): RainParticle新しいインスタンスを生成。Template は型レベルで必須

インスタンスメソッド

メソッド説明
rain:Start(override: RainConfig?)生成開始。override を渡すと内部で Update してから起動
rain:Update(override: RainConfig)設定を差分マージ(起動状態は変えない)。値に RainParticle.None を渡すと未指定状態に戻る
rain:Stop()スポーン停止(container 保持、既存粒は自然消滅、_accumulator リセット)
rain:Destroy()リソース完全破棄

Enum / sentinel

  • RainParticle.Enum.FollowTarget.Camera — カメラ基準
  • RainParticle.Enum.FollowTarget.Character — 自キャラ HumanoidRootPart 基準
  • RainParticle.NoneUpdate / Preset override で「未指定状態に戻す」ことを表す sentinel(EmitterProperties のリセット参照)

プリセット工場関数

関数シグネチャ戻り値
RainParticle.Preset.Rain(template: ParticleEmitter?, override: RainConfig?) -> RainInitConfigマルチドロップ雨用の RainInitConfig
RainParticle.Preset.Snow(template: ParticleEmitter?, override: RainConfig?) -> RainInitConfigふんわり雪用の RainInitConfig
RainParticle.Preset.RainTextureIdnumber 定数同梱 rain_streak.png の Image asset ID
RainParticle.Preset.SnowTextureIdnumber 定数同梱 snow_dot.png の Image asset ID

第 1 引数 template(任意): ベースとなる ParticleEmitter省略または nil を渡すと同梱テクスチャを Texture にした ParticleEmitter を自動生成して使う

第 2 引数 override(任意): プリセットのデフォルト値を per-key で上書きする差分。

  • top-level(Rate / Height 等)は nil 安全に上書き(Rate = 0 も尊重される)
  • EmitterProperties は base と incoming を per-key マージ
  • EmitterProperties = RainParticle.None で base の emitter props を完全クリア
  • EmitterProperties = { Color = RainParticle.None } で個別キーだけ削除
  • override.Template は無視(常に第 1 引数の template が採用される)

デフォルト値

プロパティPreset.RainPreset.Snow
FollowTarget"Camera""Camera"
Rate40080
AreaSizeVector3.new(80, 1, 80)Vector3.new(100, 1, 100)
Height3550
ForwardOffset1520
FallSpeed12012
FallDistance8080
EmitterProperties.ColorColorSequence.new(Color3.fromRGB(220, 235, 255))ColorSequence.new(Color3.fromRGB(255, 255, 255))
EmitterProperties.SizeNumberSequence.new(2)NumberSequence.new(0.5)
EmitterProperties.TransparencyNumberSequence.new(0.2)NumberSequence.new(0.2)
EmitterProperties.LightEmission0.10.2
EmitterProperties.LightInfluence0.50.3
EmitterProperties.RotationNumberRange.new(0, 360)
EmitterProperties.RotSpeedNumberRange.new(-30, 30)
EmitterProperties.SpreadAngleVector2.new(15, 15)
EmitterProperties.OrientationEnum.ParticleOrientation.VelocityParallelEnum.ParticleOrientation.FacingCamera

💡 Preset.RainVelocityParallelテクスチャの U 軸を velocity 方向に揃える 仕様です。assets/rain_streak.png は streak を 水平方向に描画している ため、落下時に 90° 回転して画面上は縦の雨として描画されます。キャラ移動時に少し傾く motion-aligned な見え方が得られます(縦長 streak テクスチャを使う場合は FacingCamera を選んでください)。

💡 Preset 専用のモジュールが RainParticle.Preset(= src/Preset.luau)に分離されているため、local Preset = require(RainParticle.Preset) のように直接 require して Preset.Rain(...) / Preset.Snow(...) を呼ぶこともできます。

型エクスポート

用途
RainParticle.RainInitConfignew() 用。Template 必須
RainParticle.RainConfigUpdate / Start 用。全項目任意
RainParticle.RainParticleインスタンス型
RainParticle.FollowTarget"Camera" | "Character"

RainConfig プロパティ一覧

プロパティ説明
FollowTarget"Camera" | "Character"追従対象(既定: Camera)。それ以外の値は error
Ratenumber毎秒の生成数(既定: 300)。0 で一時停止、負数は error
AreaSizeVector3水平生成範囲(X/Z のみ使用、Y は無視)
Heightnumber基準点からの上方オフセット(負値で下方)
ForwardOffsetnumber基準点からの前方オフセット(負値で後方)
FallSpeednumber落下速度(スタッド/秒)。正の数
FallDistancenumber落下距離(スタッド)。正の数。Lifetime を自動計算
EmitterProperties{[string]: any}?ParticleEmitter の任意プロパティ辞書上書き。RainParticle.None でリセット
Occlusionboolean?粒単位オクルージョン(既定 false)。屋内ならスポーンせず、落下経路上の遮蔽面で Lifetime をクランプして粒を消す
OcclusionParamsRaycastParams?オクルージョン Raycast のフィルタ上書き。既定: Exclude 空 / IgnoreWater=true / RespectCanCollide=falseRainParticle.None でリセット
TemplateParticleEmitternew() で必須 ベース ParticleEmitter

自動上書き(ロック)されるプロパティ

RainParticle の落下制御に必須のため、以下は Template / EmitterProperties で指定しても無視されます(警告が出ます)。

プロパティ固定値理由
Rate0単発 Emit(1) で生成するため
LifetimeFallDistance / FallSpeed落下挙動と一致させる
SpeedFallSpeed放出速度 = 落下速度
LockedToPartfalse自然落下
VelocityInheritance0基準点の移動を継承しない
Drag0FallDistance 精度維持
AccelerationVector3.zero等速落下(workspace.Gravity の影響なし)
WindAffectsDragfalseGlobalWind の影響なし
EmissionDirectionBottom下向き放出(RainParticle 仕様)
EnabledtrueEmit(1) のため。停止は Stop() または Rate = 0 を使う

挙動を変えたい場合は FallSpeed / FallDistance で調整してください。

開発

rokit install    # ツールチェーン(rojo / wally / stylua / selene)を導入
wally install    # 依存パッケージを取得
rojo serve dev.project.json   # Studio と同期

ディレクトリ構成

RobloxRainParticle/
├── src/                 # ライブラリ本体(wally で配布)
│   └── init.luau
├── tests/               # 動作確認スクリプト(wally 配布対象外)
│   └── RainParticleTest/
├── assets/              # 推奨テクスチャ PNG(wally 配布対象外、要手動アップロード)
│   ├── rain_streak.png  # Preset.Rain 用
│   └── snow_dot.png     # Preset.Snow 用
├── default.project.json # リリース用 Rojo 設定(src のみ)
├── dev.project.json     # 開発用 Rojo 設定(src + tests + Packages)
├── wally.toml
├── rokit.toml
├── stylua.toml
├── selene.toml
├── LICENSE
└── README.md

ライセンス

MIT License © 2026 hakochanjp

Package Details

Install command (Click to copy)


Version

0.3.0

License

MIT

check_circle

Safe for commercial use

Automated license review — not legal advice.