Advanced particle system plugin for the Hytopia SDK featuring TRUE entity pooling, physics forces, spatial optimization, and simplified initialization.
- ๐ฏ TRUE Entity Pooling - Entities stay spawned, just move between positions!
- ๐ Zero Spawn/Despawn Overhead - Particles teleport instead of recreating
- ๐ Gradual Pool Building - Builds 1000 entities at 10 per tick to avoid FPS drops
- ๐จ Parking System - Inactive particles hide at y=-1000 with physics disabled
- โก Fixed Velocity Application - Particles explode properly when activated from pool
- ๐ Object Pooling - Reuse particles for massive performance gains
- ๐ Physics Forces - Global wind, turbulence, and vortex effects
- ๐ฏ Spatial Optimization - Update only particles near players
- โก TypedArray Buffers - Efficient particle data storage
- ๐ฎ Simplified API - Works with minimal code, powerful when needed
- ๐ง Backwards Compatible - ParticleSystemV1 still available
npm install [email protected]import { ParticleSystem } from 'hytopia-model-particles';
// Just works with minimal setup!
const particles = new ParticleSystem(world);
// Spawn with built-in effects
particles.spawn('explosion', position);
particles.spawn('smoke', position);
particles.spawn('spark', position);
// Or quickly register your own
particles.quickEffect('magic', {
model: 'default', // Uses built-in particle model
count: 30,
pattern: 'spiral'
});
particles.spawn('magic', position);const particles = new ParticleSystem(world, {
poolSize: 200, // Pre-create 200 particles
performance: {
enablePooling: true // Default: true
}
});
// Check pool efficiency
const stats = particles.getPerformanceReport();
console.log(stats.poolStats);
// {
// available: 150,
// active: 50,
// totalCreated: 200,
// poolEfficiency: 1.0 // 100% reuse!
// }const particles = new ParticleSystem(world, {
physics: {
globalWind: { x: 5, y: 0, z: 0 }, // Constant wind
turbulence: 0.3 // Add randomness
}
});
// Change wind dynamically
particles.setGlobalWind({ x: -10, y: 2, z: 0 });
particles.setTurbulence(0.5);// Add a tornado at position
particles.addVortex(
{ x: 10, y: 0, z: 10 }, // Position
20, // Strength
15 // Radius
);
// Particles will spiral around vortex centers!const particles = new ParticleSystem(world, {
performance: {
enableSpatialOptimization: true,
updateRadius: 50 // Only update particles within 50 units of players
}
});
// Particles far from all players automatically skip updates
// Great for large worlds with many effects!v2.2 uses TypedArray buffers internally for particle metadata:
- 75% less memory usage than objects
- Faster access to particle data
- Better CPU cache utilization
particles.registerEffect({
name: 'fire',
config: {
modelUri: 'models/fire_particle.fbx',
lifetime: 2000,
tintColor: {
type: 'smooth',
keyframes: [
{ time: 0, color: { r: 255, g: 200, b: 100 } },
{ time: 0.5, color: { r: 255, g: 150, b: 50 } },
{ time: 1.0, color: { r: 200, g: 50, b: 20 } }
]
},
animations: {
scaleOverTime: { start: 0.3, end: 0.8 },
opacityOverTime: { start: 1, end: 0 }
}
},
count: 40,
pattern: 'fountain',
velocityMin: { x: -1, y: 3, z: -1 },
velocityMax: { x: 1, y: 6, z: 1 }
});
// Add wind effect
particles.setGlobalWind({ x: 3, y: 0, z: 0 });
particles.setTurbulence(0.4);
// Spawn fire
particles.spawn('fire', campfirePosition);particles.registerEffect({
name: 'portal',
config: {
modelUri: 'models/magic_particle.fbx',
lifetime: 3000,
useGravity: false,
animations: {
colorOverTime: {
type: 'smooth',
keyframes: [
{ time: 0, color: { r: 100, g: 50, b: 255 } },
{ time: 1, color: { r: 255, g: 100, b: 255 } }
]
},
rotationOverTime: { velocity: 360 }
}
},
count: 50,
pattern: 'ring'
});
// Add vortex at portal center
particles.addVortex(portalPosition, 15, 10);
// Spawn portal particles
particles.spawn('portal', portalPosition);// Built-in explosion already supports physics!
particles.spawn('explosion', position);
// Or customize it
particles.spawn('explosion', position, {
count: 100, // More particles
velocity: { x: 0, y: 10, z: 0 } // Upward bias
});const report = particles.getPerformanceReport();
console.log(report);
// {
// currentFPS: 59,
// particleCount: 245,
// poolStats: {
// available: 55,
// active: 245,
// poolEfficiency: 0.95
// },
// bufferStats: {
// capacity: 1000,
// used: 245,
// utilization: 0.245
// }
// }v2.2 is fully backwards compatible! Your existing code will work without changes.
To use new features:
// Old way (still works)
const particles = new ParticleSystem(world, {
maxParticles: 1000
});
// New way (with v2.2 features)
const particles = new ParticleSystem(world, {
maxParticles: 1000,
poolSize: 200, // Enable pooling
physics: { // Enable physics
globalWind: { x: 2, y: 0, z: 0 },
turbulence: 0.3
},
performance: { // Enable optimizations
enableSpatialOptimization: true,
updateRadius: 60
}
});const particles = new ParticleSystem(world, {
// Limits
maxParticles: 2000,
// Pooling
poolSize: 500,
// Physics
physics: {
globalWind: { x: 0, y: 0, z: 0 },
turbulence: 0,
enableForces: true
},
// Performance
performance: {
enableAdaptiveQuality: true,
targetFPS: 60,
enablePooling: true,
enableSpatialOptimization: true,
updateRadius: 50,
qualityLevels: {
high: { maxParticles: 2000 },
medium: { maxParticles: 1000 },
low: { maxParticles: 500 }
}
},
// Entity factory (for custom entity creation)
entityFactory: (config) => new Entity(config),
// Debug mode
debug: true
});import { ParticleSystemV1 } from 'hytopia-model-particles';
// Use old system if needed
const particles = new ParticleSystemV1(world, options);// In your game's weapon system
class WeaponEffects {
private particles: ParticleSystem;
constructor(world: World) {
this.particles = new ParticleSystem(world, {
poolSize: 300,
physics: {
globalWind: { x: 2, y: 0, z: 0 },
turbulence: 0.2
}
});
// Register weapon effects
this.particles.quickEffect('muzzle_flash', {
count: 5,
lifetime: 200,
pattern: 'explosion'
});
this.particles.quickEffect('bullet_impact', {
count: 15,
pattern: 'explosion',
scale: 0.2
});
}
onWeaponFire(position: Vector3Like) {
this.particles.spawn('muzzle_flash', position, {
priority: 10 // High priority
});
}
onBulletHit(position: Vector3Like) {
this.particles.spawn('bullet_impact', position);
this.particles.spawn('smoke', position);
}
}- Use Object Pooling - Biggest performance win, enabled by default
- Set Appropriate Pool Size - Based on your max concurrent particles
- Enable Spatial Optimization - For large worlds
- Use Priority System - Important effects spawn first
- Monitor Performance - Check poolEfficiency and adjust
See API Documentation for complete reference.
- Added object pooling system
- Added physics forces (wind, turbulence, vortex)
- Added spatial optimization
- Added TypedArray buffers
- Simplified initialization API
- Improved performance monitoring
- Added particle animations
- Added new patterns
- Added performance monitoring
- Added YAML configuration
- Initial release with entity factory pattern
MIT