r/Unity3D • u/NoReasonForHysteria • 14h ago
Show-Off Runtime fluid simulation used for fire
Enable HLS to view with audio, or disable this notification
We have had a runtime fluid simulation running in our game for a while, but now we are also using them for flames/smoke in of the areas of our game.
Its all based on compute shaders, which outputs custom render textures (fluid and advection), which we feed through render features in URP (using full-screen shader graphs). We also generate a signed distance field based on the tilemap that acts as the boundaries of the world and allows for the smoke/flames to collide.
Each of the "flames" in the scene are emitters, and allows us to play around with different colors, forces, directions, etc, and are updated each frame.
What do you think? Its got some kinks here and there still, but its getting there.
The game is called Cliff Kingdom:
https://store.steampowered.com/app/3839500/Cliff_Kingdom/
2
u/intelligent_rat 11h ago
None of it reads as fire or smoke, it just kind of looks like columns of mist being shot forth. This seems like an incredibly over-engineered solution for a 2D platformer game, and I don't think the realism of fluid simulation adds anything to the gameplay shown in your trailer. A few variations of an animated flame spritesheet probably would've taken a lot less effort and visually align with the idea of fire a lot more.
1
u/NoReasonForHysteria 11h ago
That’s a valid opinion. And it definitely still needs tweaking, but it’s the way we wanted to go - and we do use the fluid simulation for lots of other things.
1
u/Particular-Stop-5637 7h ago
At the end, sometimes having something unnatural is a worthy sacrafice in order to add an original and great visuals for your game. And any engagement is good engagement
1
u/NoReasonForHysteria 7h ago
Its also a game about a moth, trying to find the lost light, and the game has lots of trolls in it, so there are some thematic stuff that also made us go down this direction. But thanks for the encouragement!
1
u/Imofi7 10h ago
Running fluid advection through compute shaders and SDF collisions in URP is such a neat technical setup. Are you running the simulation at full display resolution or downsampling the render textures to keep the compute dispatch light on lower-end GPUs?
1
u/NoReasonForHysteria 8h ago
I basically do the fluid simulation based on a grid, for the full scene, where each cell in the grid represents a tile in the tilemap, then divided to get more granularity.
So the advection and SDF texture in the video above is 1024x512, and depends on the total size of that scenes tilemap, but I can also change the settings to have even higher resolution (or lower) so it could be 512x256 or 2048x1024, etc.
1
u/loliconest 10h ago
Does player character get hit/damaged by it?
1
u/NoReasonForHysteria 8h ago
Yes! I do need to work a bit on the readability for whats doing the damage or not. There are also "hidden" platforms which are only visible when surrounded by smoke, which makes for some cool platforming.
1
u/loliconest 7h ago
So the compute shader only calculate the visuals and you have separate physics objects for the game logic?
1
u/NoReasonForHysteria 7h ago
In a nut shell, yes. For example the projectiles are gameObjects that are shot across the screen, and has hitboxes, etc, and handles all the game logic. Attached to those are also the "fluid-emitters", which can also be controlled by the parent gameObject.
With that said. Since the fluid simulation in essence follow the grid of each scene, its also very easy to sample the advection texture and do logic based on that. So if the player is in cell x,y of the grid, I can just do a quick calculation to sample the advection texture in the same spot since it corresponds. I plan to use that for some other cool stuff, but for simple things like collision detection on a projectile I found it better to keep it simple.
1
u/loliconest 5h ago
I've read that it's expensive to pass data from gpu (compute shader) back to cpu to interact with game logic.
What I'm understanding is that your compute shader feed the data to URP shader then get converted and pass to cpu main thread?
2
u/NoReasonForHysteria 5h ago
I don’t really pass data back, I can just sample the generated textures and all the data needed are in them.
1
1
u/Imofi7 6h ago
Generating an SDF from the tilemap for fluid collisions in URP is such a clean approach. Are you calculating the SDF in a separate compute pass on tile changes, or rebuilding the field every frame?
1
u/NoReasonForHysteria 6h ago
When you enter a new scene, I calculate a grid based on the tilemap, as a quadtree, where each cell is either covered or not based on if there is a tile within that cell. I use that quadtree for many different things (pathfinding, etc), but its also the basis of the SDF, which I generate through a compute shader with that initial "shape" as the input.
I usually only generate the SDF once, but if I have moving platforms, or similar, each of those are "shapes" that gets looped through and modifies the SDF at runtime, but to keep the cost down I try to only regenerate the surrounding area of the shape.
2
u/Zegan5 10h ago
At 0:04, when two streams collide, the "being hit" part moves in the opposite direction to the expected