ParticleManager API Reference
GPU-instanced particle system for efficient visual effects rendering.Overview
The ParticleManager provides a unified interface for managing all particle effects in Hyperscape. It uses GPU instancing and TSL NodeMaterials to render thousands of particles with minimal CPU overhead. Location:packages/shared/src/entities/managers/particleManager/
Performance:
- 4 draw calls total (vs. ~150 before refactor)
- GPU-driven animation (zero CPU cost)
- Supports 264+ concurrent particle instances
Architecture
ParticleManager
Central router that dispatches particle events to specialized sub-managers.Constructor
scene- Three.js scene to add particle meshes to
Methods
register()
Register a new particle emitter.id- Unique identifier for this emitterconfig- Particle configuration (discriminated union)
unregister()
Remove a particle emitter and free its instances.id- Emitter identifier to remove
- Automatically routes to correct sub-manager via ownership map
- Frees all particle instances
- No type hint required
move()
Move an existing emitter to a new position.id- Emitter identifier to movenewPos- New world position
- Updates all particle instances to new position
- Automatically routes to correct sub-manager
- No type hint required
update()
Update all particle managers (call once per frame).dt- Delta time in secondscamera- Active camera for billboard orientation
- Updates camera right/up vectors for billboarding
- Advances particle ages and respawns expired particles
- Updates InstancedBufferAttributes (GPU upload)
- Triggers burst effects for fishing spots
dispose()
Clean up all particle resources.- Removes all meshes from scene
- Disposes geometries and materials
- Disposes textures
- Clears ownership map
WaterParticleManager
Manages fishing spot particle effects (splash, bubble, shimmer, ripple).Particle Types
Splash:- Parabolic arc motion
- 0.6-1.2s lifetime
- 0.05-0.3 tile radius
- 0.12-0.32 tile peak height
- Burst effects every 3-10 seconds
- Rising motion with wobble
- 1.2-2.5s lifetime
- 0.04-0.2 tile radius
- 0.3-0.55 tile rise height
- Drift with sine wave
- Surface wandering
- 1.5-3.0s lifetime
- 0.15-0.6 tile radius
- Twinkle effect (sine wave)
- Circular motion
- Expanding ring
- Continuous loop
- 0.15-1.45 tile scale
- Ring texture with fade
Fishing Spot Variants
Net Fishing:GlowParticleManager
Manages instanced glow billboard particles (fires, altars, torches).Glow Presets
Fire Preset
Rising embers with heat distortion.- Particles rise from base position
- Chaotic motion with turbulence
- Orange/yellow color gradient
- Suitable for campfires, furnaces
Altar Preset
Geometry-aware sparks rising from altar mesh.- Particles spawn on altar mesh surface
- Rise upward with slight outward drift
- Three-tone color gradient (core → mid → outer)
- Requires
meshRootfor bounds detection
Torch Preset
Tight flame cluster for wall-mounted torches.- 6 particles per torch
- Tight spread (0.08 radius)
- Concentrated flame effect
- Minimal horizontal drift
Color Configuration
Single Color:TSL NodeMaterials
Particles use Three.js Shading Language (TSL) for GPU-driven animation.Vertex Shader
Billboard Orientation:Fragment Shader
Opacity Envelopes:Instance Attributes
Particle Layers (Splash, Bubble, Shimmer)
Vertex Buffer Layout (7 of 8 max):position(vec3) - Base geometry vertex positionuv(vec2) - Texture coordinatesinstanceMatrix(mat4) - Instance transform (unused, identity)spotPos(vec3) - Emitter world positionageLifetime(vec2) - Current age (x), total lifetime (y)angleRadius(vec2) - Polar angle (x), radial distance (y)dynamics(vec4) - Peak height (x), size (y), speed (z), direction (w)
Ripple Layer
Vertex Buffer Layout (5 of 8 max):position(vec3) - Base geometry vertex positionuv(vec2) - Texture coordinatesinstanceMatrix(mat4) - Instance transform (unused, identity)spotPos(vec3) - Emitter world positionrippleParams(vec2) - Phase offset (x), ripple speed (y)
Integration with ResourceSystem
The ResourceSystem automatically manages particle lifecycle for resource entities.Resource Spawning
Resource Despawning
Resource Movement
Event Routing
Integration with DuelArenaVisualsSystem
The DuelArenaVisualsSystem uses ParticleManager for torch fire effects.Torch Placement
Torch Cleanup
Performance Considerations
Instance Limits
Hard Limits:- Splash: 96 instances
- Bubble: 72 instances
- Shimmer: 72 instances
- Ripple: 24 instances
register() will use fewer particles than requested. The system gracefully degrades by allocating as many instances as available.
Memory Usage
Per Particle Layer:- Geometry: ~2KB (PlaneGeometry with 2 triangles)
- Material: ~1KB (TSL NodeMaterial)
- Instance Data: ~100 bytes per instance
- Total: ~10KB per layer + (100 bytes × instance count)
- 4 particle layers × 10KB = 40KB base
- 264 instances × 100 bytes = 26KB instance data
- Textures: 64×64×4 × 2 = 32KB
- Total: ~100KB
GPU Bandwidth
Per Frame Upload:- Only dirty attributes are uploaded
- Typical: 2-3 attributes per frame
- Splash: ~1KB (96 instances × 2 floats × 4 bytes)
- Bubble: ~750 bytes
- Shimmer: ~750 bytes
- Total: ~2.5KB per frame
Draw Calls
Before Refactor:- 1 draw call per fishing spot
- 30 fishing spots = 30 draw calls
- 5 particles per spot = 150 draw calls total
- 4 draw calls total (4 InstancedMeshes)
- 97% reduction in draw calls
Extending the System
Adding New Particle Types
To add a new particle type (e.g., snow, rain, magic effects):- Create Specialized Manager:
- Add Config Type:
- Update ParticleManager:
Custom Glow Presets
To add a new glow preset:- Define Preset Configuration:
- Update Preset Type:
- Use New Preset:
Best Practices
Registration
- Unique IDs: Use entity ID or unique identifier
- Cleanup: Always unregister when entity is destroyed
- Position: Use world coordinates, not local
- Type Safety: Use discriminated union for config
Performance
- Batch Operations: Register multiple emitters before first update
- Avoid Churn: Don’t register/unregister every frame
- Reuse IDs: Unregister before re-registering same ID
- Limit Instances: Stay within hard limits (96/72/72/24)
Visual Quality
- Color Choice: Use hex colors matching game aesthetic
- Preset Selection: Choose preset matching effect type
- Position Height: Adjust Y position for visual alignment
- Scale: Use modelScale for size adjustment
Debugging
Enable Particle Debug Logging
Visualize Instance Allocation
Inspect Particle Attributes
Migration Guide
From ResourceEntity Particles
Before (per-entity particles):- No per-entity particle code
- Automatic GPU instancing
- Centralized particle management
- Consistent visual quality
From Manual Particle Meshes
Before (manual mesh creation):- No manual animation code
- Automatic billboarding
- GPU-driven updates
- Shared geometry/material