Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
TinySnail
A tiny snail crawls toward the nearest player. Touch = death. Killable. Steals valuables. Investigates gunshots. Scared of flashlights. Permanent slime trail. Hot-cold HUD. Procedural audio. Difficulty presets. Multiplayer-synced.
By Beet
| Date uploaded | 5 months ago |
| Version | 1.9.0 |
| Download link | Beet-TinySnail-1.9.0.zip |
| Downloads | 113 |
| Dependency string | Beet-TinySnail-1.9.0 |
This mod requires the following mods to function
BepInEx-BepInExPack
BepInEx pack for Mono Unity games. Preconfigured and ready to use.
Preferred version: 5.4.2305README
🐌 TinySnail
You finish generating the level. You hear nothing. You see nothing. Somewhere on the map, a snail begins to move.
A tiny, slimy, photorealistically uncomfortable snail spawns on your level. It crawls toward the nearest player at a snail's pace. If it touches you, you die.
It is not in a hurry. It does not need to be.
By default: one snail per level. It will investigate gunshots. It will recoil from a flashlight. It will steal your shiniest valuable. You can kill it with a thrown bottle or a crouch-stomp. If a single snail isn't enough fun, flip on [Difficulty] Preset = Inevitable (or Snailpocalypse) and the population starts doubling every minute — an opt-in "extra mode."
Mechanics
| Mechanic | Detail |
|---|---|
| Movement | Constant pursuit of the nearest player. Cruises ~0.30 u/s, accelerates to ~1.20 u/s inside RageDistance (snail rage). |
| Smart targeting | The snail picks the nearest of all players to its own position. Switches target if someone gets closer. Re-evaluates 4× per second. |
| Investigates noises | Gunshots and player damage (≥10 HP) attract the snail if within 60 units. It diverts for ~4 seconds when the noise is meaningfully closer than its chase target. |
| Scared of flashlights | Direct flashlight beam, 30° cone, within 15 units, for >0.5 seconds — the snail retracts into its shell and freezes for 3 seconds. Stall mechanic. |
| Steals valuables | The snail crawls over a loose valuable (PhysGrabObject, mass <4) — it sticks to its slime. Carried on its back until killed, grabbed back, or the level ends. |
| Killable | Throw a valuable at it at >3 m/s, or crouch within KillRadius, and the snail dies in a slime burst + wet squelch. Default HP = 1. |
| Doubling (opt-in extra mode) | OFF by default. Every 60s (configurable) the snail population doubles up to CountMax. Newcomers spawn at random valid points across the map. |
| Permanent slime trail | Bright, glowing slime decals dropped every 0.6s. Persist for the level (global cap 600). Lights up dark corridors via REPO's bloom — you can see where the snail's been from across the map. Tune [Visual] SlimeGlowIntensity (default 1.0, range 0–8). |
| Kill = death | Player takes 9999 damage via REPO's PlayerHealth.Hurt, networked. Everyone sees the death. |
| Walls don't matter to the snail. | The snail clips through geometry. The snail is patient. The snail is geometric in nature. |
The HUD heat meter
A small, soft-glowing panel in the corner. Snail icon, a heat word, and a colored bar that fills as the snail closes in. No numeric distance by default — you're supposed to feel it.
| Distance | Word | Vibe |
|---|---|---|
| > 50 m | Ice cold | safe |
| 30–50 m | Cool | fine |
| 18–30 m | Tepid | huh |
| 10–18 m | Warm | uh |
| 5–10 m | Hot | uh oh |
| 2–5 m | Burning | RUN |
| < 2 m | SCORCHING | (pulses red; you are already dead) |
A 2D heartbeat thump layers in once the meter goes Warm or higher and gets faster as the snail closes. Set [HUD] ShowDistance = true if you'd rather see a real "12.3 m" readout.
Difficulty presets
[Difficulty] Preset is the only knob you usually need:
| Preset | Speed | Rage | Cap | Doubling |
|---|---|---|---|---|
| Cute | 0.18 → 0.45 | 3m | 4 | off |
| Standard (default) | 0.30 → 1.20 | 5m | 8 | off |
| Inevitable | 0.45 → 2.00 | 8m | 16 | on, every 90s |
| Snailpocalypse | 0.55 → 3.00 | 12m | 64 | on, every 45s, starts with 3 |
| Custom | use individual fields |
Configuration
All settings live in BepInEx/config/TinySnail.cfg after first launch.
Tip: install REPOConfig (used by 1600+ REPO mods) and TinySnail's settings will appear in the in-game Mods menu as sliders + dropdowns — no need to edit the .cfg by hand. All TinySnail numeric fields declare proper AcceptableValueRange and enum fields declare AcceptableValueList, so REPOConfig renders them correctly automatically.
- [Difficulty]
Preset— pick one of the above. - [Behavior]
BaseSpeed,MaxSpeed,RageDistance,KillRadius,InvestigateNoises,ScaredByFlashlight,StealValuables. - [Killable]
Enabled(true),Health(1),ImpactDamageThreshold(3.0 m/s),CrouchStompKills(true). - [Visual]
Scale(0.12),SlimeTrail,PermanentTrail,DecalInterval(0.6),SlimeGlowIntensity(1.0, range 0–8),GlowingEyes,WobbleAnimation. - [Spawning]
CountBase,CountPerLevel,CountMax,MinSpawnDistance(20),MaxSpawnDistance(80),DoubleEachMinute(false),DoublingIntervalSeconds(60). - [Audio]
Enabled,SlitherSound,SlitherVolume(0.5),SlitherAudibleRange(15),HeartbeatSound,HeartbeatVolume(0.7),SquelchOnDeath. - [Networking]
UpdateRateHz(15, range 1–30). - [HUD]
Enabled,ShowDistance(false),Position(TopRight/TopLeft/BottomLeft/BottomRight/BottomCenter).
How it works (technical)
For the curious and for fellow modders:
- No Unity asset bundle, no custom prefabs. The snail is built entirely at runtime from primitives (
GameObject.CreatePrimitive) with procedurally generatedTexture2Dmaterials — polar-coordinate spiral on the shell, Perlin-noise mottling on the body. Audio is generated procedurally withAudioClip.Create+SetData. Optionally, atinysnail.bundleUnity asset bundle next to the DLL overrides the procedural visual with a sculpted prefab. - Spawning is hooked via Harmony postfix on
LevelGenerator.GenerateDone. Master client picksLevelPoints viaSemiFunc.LevelPointsGetAll()biased toward[MinSpawnDistance, MaxSpawnDistance]from the player. - Targeting uses
SemiFunc.PlayerGetList()to consider every player. The snail re-evaluates ~4× per second. - Noise investigation is a
SnailSensesstatic registry; Harmony postfixes onItemGun.ShootandPlayerHealth.Hurtpush noise events that decay after 10 seconds. The snail checks the registry and diverts if a noise is meaningfully closer than its chase target. - Flashlight detection uses
PlayerAvatar.flashlightController.{active, spotlight}— cone test against each player's flashlight spotlight transform. - Item theft uses
Physics.OverlapSphereforPhysGrabObjectcomponents not currently grabbed (checked viaSemiFunc.PhysGrabObjectIsGrabbed), sets the rigidbody to kinematic, and lerps it to the snail's back. - Killable mechanics add a
SphereCollidertrigger to the snail.OnTriggerEnterchecks incoming rigidbodies' velocity againstImpactDamageThreshold. Crouch-stomp checksPlayerAvatar.isCrouchinginside the kill range. - Networking uses
PhotonNetwork.RaiseEvent(codes 180–183) for spawn/despawn/pose/despawn-all. Pose broadcasts at 15 Hz with unreliable transport; spawns/despawns are reliable. Payload validation: finite floats, position bounds ≤10000, ID range, receive-side cap at 2×SafeCountMax. Photon subscription is retried each frame until ready. - Material leaks are prevented by the
MaterialCleanupMonoBehaviour, which explicitly destroys all per-instance material clones on snail destruction. - All Update loops are wrapped in try/catch. A single bad frame won't crash the snail, much less the game.
Multiplayer
Fully synchronized. The host (master client) simulates the snail; everyone else sees it in the same place. Sync uses Photon events (no PhotonView registration, no REPOLib dependency) at 15 Hz by default. The killing blow uses REPO's own networked damage RPC. Singleplayer: the network layer detects singleplayer and skips broadcasts entirely.
Compatibility
- REPO built around the May 2026 game build
- BepInEx 5.4.2305 required (auto-installed by Thunderstore Mod Manager / r2modman)
- Render pipeline: Built-in (no URP/HDRP dependency)
- No REPOLib dependency — intentionally avoided to keep the mod self-contained
Known limitations
- Built from Unity primitives + procedural textures, not a sculpted 3D model. Adorable in a programmer-art way. A real model is on the roadmap (or ship your own via the asset-bundle path — see
unity/UNITY_SETUP.mdin the source repo). - The snail clips through walls. This is intentional.
- Master-handoff when the host leaves mid-run isn't yet smooth — the snail freezes until the next level. On the roadmap.
Roadmap
See PROJECT_PLAN.md in the source repo. Highlights for upcoming releases:
- v1.9: Master-handoff for hot-swapping the simulation when the host leaves
- v1.10: Per-snail varieties (boss snail, slug, albino), per-player snail color sync
Found a bug? Want a feature?
Open an issue on the repo or post on the Thunderstore comments. PRs welcome.
Stay slow.
CHANGELOG
Changelog
1.9.0
REPO modding best-practices pass.
- REPOConfig integration: every numeric config now declares a proper
AcceptableValueRange<float>/AcceptableValueRange<int>and every enum-like string declaresAcceptableValueList<string>. This makes the mod's config render as proper sliders and dropdowns in the in-game REPOConfig menu (used by 1600+ mods), AND gives BepInEx native bounds-validation instead of relying on post-hoc clamping. TheDifficulty.Presetfield becomes a dropdown listing the four presets + Custom;HUD.Positionbecomes a dropdown of the five anchor strings. - F6 hot-reload support:
Plugin.OnDestroynow properly tears everything down —Harmony.UnpatchSelf(), despawns all managers (network, HUD, reproduction, snails), clears decals, invalidates shared materials, and clears the noise registry. You can now drop the DLL intoBepInEx/scripts/instead ofplugins/for iterative dev and hit F6 to reload without restarting REPO. - All
SafeXaccessor clamping is preserved as a belt-and-suspenders safety net even with the new validators.
1.8.2
Bright glowing slime.
- All slime visuals (permanent floor decals, the live trail behind the snail, slime drip particles, and the death burst) now use an emissive
Standardshader. REPO's bloom post-process turns the emission into actual glow — slime trails light up dark corridors and read at a glance across the map. - Bigger decals: scale factor doubled (decals are now
clamp(scale × 10, 0.18, 1.6)instead ofclamp(scale × 6, 0.10, 1.0)). - Brighter, more saturated slime palette: hot-white-yellow core fading through saturated lime to a deeper green halo. The blob texture upgraded from 64×64 to 128×128 with a two-stop alpha (core + halo) for that glow look.
- Trail behind the snail lasts longer (10s, was 6s) and is thicker at the head (0.45u, was 0.30u) so the fresh glow segment lingers.
- New
[Visual] SlimeGlowIntensityconfig (default1.0, clamp[0, 8]) — multiplier on the emissive intensity. Set 0 for non-glowing matte slime; crank to 4+ for "this map has been sprayed." - All slime materials are shared (one decal material, one trail material, one particle material) so 600 decals still draw efficiently.
1.8.1
Bug sweep + singular framing.
- Fixed:
TinySnailSpawnercould NPE when the local player'splayerTransformwas null at spawn time (anchor was checked, transform wasn't). - Fixed:
SnailNetworkwould silently miss all Photon events ifPhotonNetwork.NetworkingClientwas null at plugin Awake time. Subscription now retries every frame until ready. - Fixed:
SnailReproductionManagercould spam hundreds of no-op doubling calls (and log lines) in one frame after a long pause. Hard ceiling of 12 doublings/level applied. - Fixed: HUD pulse-rate lerp
twas unclamped; could produce out-of-range pulse speeds in edge cases. - Cleaned: Removed a no-op
velocity = Vector3.zerowrite on the kinematic rigidbody of carried valuables. - Cleaned: Default-mode framing is now singular ("the snail") throughout configs, log messages, manifest description, and README — since by default there is one snail per level. The doubling mode is opt-in (
[Spawning] DoubleEachMinute = trueor presetInevitable/Snailpocalypse). - Manifest description shortened to 226 chars (Thunderstore limit is 256).
1.8.0
Optional asset bundle support.
- The plugin now loads a Unity asset bundle from
BepInEx/plugins/<TeamName-TinySnail>/assets/tinysnail.bundleif present, and uses the embeddedTinySnailprefab in place of the runtime-built primitive snail. If the bundle is missing or fails to load, the procedural snail is used — nothing breaks. - The bundle is opt-in: the package ships without one (the procedural snail is still the default). To build your own, see
unity/UNITY_SETUP.mdin the source repo (Unity Editor 2022.3 + Built-in Render Pipeline; anEditor/BuildBundle.cshelper is included). - No changes to existing config, behavior, audio, or networking — this is purely a visual upgrade path for modders who want to ship a sculpted snail.
1.7.0
Smart snails.
- Investigate noises. Gunshots (
ItemGun.Shoot) and player damage (PlayerHealth.Hurtwith damage ≥ 10) register as noise events. Snails within 60 units divert toward the noise for 4 seconds, abandoning their chase target if the noise is meaningfully closer. Slow, but listening. - Scared by flashlight. If a player's active flashlight is pointed within a 30° cone of a snail for >0.5 seconds at <15 units range, the snail retracts into its shell and freezes for 3 seconds. Stall tactic.
- Steal valuables. Snails crawl over loose valuables (PhysGrabObjects with mass < 4) and carry them on their backs. The valuable stays stuck until you grab it back, the snail dies, or the level ends.
- New
[Behavior] InvestigateNoises,ScaredByFlashlight,StealValuablestoggles, all defaulttrue. - New Harmony hooks:
ItemGun.Shoot,PlayerHealth.Hurt(postfix).
1.6.0
Difficulty + killable + audio.
- Difficulty presets. New
[Difficulty] Preset = Cute / Standard / Inevitable / Snailpocalypse / Custom. One knob overrides speed, rage, kill radius, count, and doubling. UseCustomto fall back to individual fields. - Killable snails. New
[Killable]section. Throwing a valuable hard enough (ImpactDamageThreshold3 m/s default) kills the snail. Crouching within the kill radius now stomps the snail instead of dying. Default snail HP = 1 (one-shot anything). - Death VFX. Slime particle burst on snail death.
- Procedural audio. Looping 3D slither sound on each snail (range 15u, configurable). 2D heartbeat thump that speeds up from 1.5s → 0.3s as the nearest snail closes. Squelch one-shot when a snail dies. All audio generated procedurally — no asset files ship in the DLL.
1.5.0
Multiplayer networking. Hardened.
- Snails are now synchronized across all clients. The master client owns the simulation and broadcasts snail positions to everyone else via Photon events (no PhotonView registration needed). All players see the same set of snails moving in the same places. Pose updates default to 15 Hz (configurable
[Networking] UpdateRateHz, range 1–30). - Authority model: master client simulates chase + kill detection. Clients are display-only and lerp received poses for smoothness. Kill is still routed through
PlayerHealth.Hurt, which uses the game's own networked damage RPC. - Singleplayer: unchanged. The network layer detects singleplayer and skips all broadcasts.
- Security pass: received Photon payloads are validated for length, finite floats, position bounds, and sane ID range. Ghost-snail count is capped at
2× SafeCountMaxon the receiving side to prevent flooding. All event handlers wrapped in try/catch. - Material leak fixed: new
MaterialCleanupMonoBehaviour explicitly destroys each per-instance material clone when a snail dies, preventing slow GPU memory growth. - Full audit doc: see
SECURITY_AUDIT.mdin the repo for the complete review.
1.4.1
DoubleEachMinuteis now OFF by default. The default experience is one snail per level. Doubling is opt-in for users who want escalating dread.
1.4.0
Big release.
- Doubling mechanic (opt-in): when
[Spawning] DoubleEachMinute = true, the snail population doubles every minute on the level clock (1→2→4→8→…), capped byCountMax(default 32). Off by default — the default experience is one tiny snail per level. Flip the toggle if you want escalating dread. - Permanent slime decals: snails leave sticky-looking slime quads on the floor wherever they crawl. Persists for the rest of the level. Global cap of 600 decals to keep performance sensible.
- Smart multi-target snails: each snail picks the nearest player to its own position as its target, and switches target if another player gets closer. They're slow, but they're smart.
- HUD heat meter: subtle on-screen proximity warning with a heat word (Ice cold → Cool → Tepid → Warm → Hot → Burning → SCORCHING) and a colored bar that fills as the nearest snail closes in. Rounded panel, cute snail icon, raw distance is hidden by default for atmosphere (toggle
HUD.ShowDistance). - Cuter snail visuals: bigger expressive eyes with catchlight glints, soft pastel body color, smile mouth, softer shell stripe palette.
- Robustness pass: all Update loops wrapped in try/catch (one bad frame won't crash the snail or the game), config values clamped, ground raycasts use a safer layer mask, cleanup on level change and main-menu exit.
1.3.0
- HUD heat meter (initial)
- Robustness/security pass
1.2.0
- Procedural shell + body textures, eye tracking, breathing, shell spin, slime particle drips
1.1.0
- Multi-part snail, slime trail, wobble, ground-stick, multi-snail spawning, snail rage
1.0.0
- Initial release.