In a topdown game with 3D weather, how could one fast forward weather particles (especially snow which is slow and takes a while to fill the area) outside the player screen? Even in Dont Starve Together, the snow lags behind you, so you have to stay still for it to reach its peak coverage. This is especially problematic when a player is travelling at high speed, and my project has fast vehicles.
So far I have tried to just offset the start of the snow to a calculated point in the direction the player is moving. But if the player changes directions rapidly, this cannot keep up, and I have to be conservative with the amount of snow coverage to not get to millions of particles. It is expensive since it has high quality collisions to not go through buildings etc.
As I understand, prewarm is only for filling the start of the system - but to simulate the noise, external forces, and collisions all the way to each particle’s death, I need to use the simulation speed setting, but that is not localised to particles.
I am thinking I’ll have to stitch together many particle systems in chunks with controlled simulation speed to allow the player to move freely, or applying the velocities myself in code. I currently Emit() my weather particles myself through code, but found no emit parameter to help with this. Any ideas?
Store the max saturation value of the weather and unless the area is modified then you can assume it is the max saturation.
Are you saying to have a grid/chunk/tile lookup table for areas so that they can be prewarmed well enough without simulating the collisions wind and noise? To account for buildings and trees, maybe it should be more of a 3D volume of spaces deemed full of falling snow?
It’s probably going to be expensive, but, if you want, you can do your own “prewarm”.
At some point in code where you want to perform the prewarm (Awake?) you can temporarily take over the simulation of the particles:
var ps = m_ParticleSystem;
var main = ps.main;
main.simulationSpeed = optimizedPrewarmFactor; // this will make the operation faster, but the simulation less precise. eg 2.0f means twice as less CPU time.
ps.Simulate(t: prewarmTimeInSeconds / optimizedPrewarmFactor, withChildren: false, restart: false, fixedTimeStep: true);
main.simulationSpeed = 1.0f; // restore normal playback speed
ps.Play(); // calling Simulate leaves the system in a paused state. Call this to re-enable default playback
Good luck!
Simulate() sounds nice, but still isn’t local to a set of particles (the ones outside the screen), so to keep the ones already in the screen smooth as the player moves, would it be efficient to transfer (re-emit) particles from an invisible sped up system to the visible screen system, when they enter the screen? (Could be 2D planes at the edges of the player screen, that send a callback when the particles enter them, or a trigger, or manual looping in code)
Edit: Maybe I should switch to somehow generated 2D planes instead of 3D collisions for my existing particle system (most buildings could technically be expressed in planes, and only something like trees would be harder), or use the VFX graph if that supports collisions.
Oh sorry i thought you maybe had a bunch of Particle Systems, each responsible for its own area of the level.
A common trick for handling rain/snow is to just have 1 system in front of the screen, and teleport particles between the left/right planes when they go out of the view. This doesn’t handle the case if snow needs to settle on geometry, but, it does solve a quick move of the camera causing the snow to “go missing”. you can also teleport particles that go through the front plane, to the far plane, as long as there is no visible popping.
You can do the teleporting really efficiently by attaching a Burst compiled job to the ParticleSystem:
I don’t know how to do either of these but if VFX graph can take a shape (the outdoors for example) or even collision shapes (the house boxes or roof heights?) then that could be good for weather… Some renderer feature or way to mask away particles that are deemed in homes, without actually running collisions, also sounds good (I don’t mean indoors in screen space - I mean indoors in 3D volumes. So a custom job is possible, if I could make something cheaper than the actual collision module).
But spawning things in the 3D area they should be in, might be good for prewarming CPU particles. I shouldn’t be a perfectionist… A raycast from the sky to see if the area is free should be cheap, or even cheaper if I only bother to check lookup table of roof coverage.
I also don’t know if triggers module with callback is faster than full collision. Anyone know?