Comment créer une cascade physique 2D

8

J'essaie de créer une cascade qui ressemble à la première image ci-dessous (veuillez vérifier cette vidéo pour une meilleure idée de ce que je veux réaliser) avec des propriétés physiques afin qu'elle puisse déplacer ou contourner des objets avec des collisionneurs sur son parcours (similaire à la deuxième image ci-dessous). Bien que la cascade liée soit 3d, je suis intéressé par une implémentation 2D.

Notez que les objets sont dynamiques et certains se déplacent fréquemment, la cascade doit donc remodeler chaque image. Les objets se déplacent lentement en se déplaçant vers différentes positions ou en tournant. Comment cela peut-il être fait?

entrez la description de l'image ici

entrez la description de l'image ici

OnlyCodeMatters
la source

Réponses:

13

Je voulais voir si je pouvais retirer cela sans régénérer dynamiquement le maillage de la cascade à chaque image. Il s'avère qu'il y a un moyen. :RÉ

Animation de cascades en cascade

Chaque objet qui peut bloquer la cascade (objets portant un WaterCatcherscript dans mon prototype) a un maillage de contour qui entoure son périmètre. (Cela peut être généré automatiquement à l'avance en utilisant la forme du collisionneur)

Ce maillage de contour rend l'eau qui coule le long de l'objet. J'utilise un shader pour clipsortir la partie sous l'objet. Je trace également un point de capture gauche et droit où une cascade atterrit sur l'objet et coule respectivement à gauche ou à droite, donc je peux clipsortir la partie qui est à gauche de la cascade de droite et à droite de la cascade de gauche.

Animation montrant le maillage de la peau de l'eau

Les chutes verticales ne sont alors que des primitives quadruples de base, étirées à la longueur appropriée. J'utilise un autre shader pour faire défiler la texture de la cascade sur les chutes et l'effacer aux extrémités supérieure et inférieure. Ensuite, je couche sur un système de particules de mousse au point d'impact pour aider à couvrir le mélange.

Voici un gros plan pour voir les composants.

Gros plan de l'effet cascade

Au sommet, j'ai une cascade "racine" pour lancer les choses. Chaque image, après que tous les Update()scripts ont été exécutés pour déplacer les choses, il tire CircleCastvers le bas, pour voir si son eau frappe quelque chose. S'il frappe un WaterCatcher, il lui indique de montrer sa peau d'eau en aval du point de coup.

Je détermine «en aval» en utilisant la normale de frappe - si elle est très proche de la verticale, ou si la cascade entrante s'étend sur des bords qui s'inclinent dans les deux directions, alors nous renversons à gauche et à droite.

Chacun WaterCatchera sa propre cascade gauche et droite, qu'il active et positionne sur son bord éloigné s'il se déverse dans cette direction - sinon ils restent cachés. Ces chutes d'eau à leur tour tirent CircleCastvers le bas pour trouver ce qu'elles renversent, et ainsi de suite ...

Le prototype a encore quelques problèmes visuels qui pourraient être améliorés - le flux d'eau le long d'un objet apparaît tout d'un coup au lieu de s'animer, et les règles de flux pourraient utiliser un peu de tolérance ou d'hystérésis supplémentaires afin de ne pas couper aussi facilement sur objets en rotation. Je pense cependant que ces problèmes devraient être assez résolubles.

Fond, roches et textures de plate-forme tournante via Kenney


Voici les astuces que j'utilise dans mon shader de fragment de capteur d'eau:

// My wraparound geometry is build so the "x+" UV direction
// points "outward" from the object.
// Using derivatives, I can turn this into a vector in screen space.
// We'll use this below to clip out water hanging off the bottom.
float2 outward = float2(ddx(i.uv.x), ddy(i.uv.x));

// i.worldX is the worldspace x position of this fragment
// (interpolated from the vertex shader)

// _LeftX is a material property representing the worldspace x coordinate
// of the rightmost water flow that's spilling left,
// and _RightX the wold x of the leftmost water flow that's spilling right.
float left = _LeftX - i.worldX;   // +ve if we're to the left of a left spill.
float right = i.worldX - _RightX; // +ve if we're to the right of a right spill.

float limit = max(left, right); // +ve if we're in the path of either flow.

// If the "outward" vector is pointing down, make this negative.
limit = min(limit, outward.y + 0.001f);

// If any of the conditions above make limit <= 0, abort this fragment.
clip(limit);

// Otherwise, scroll the water texture!
// Counter-clockwise if we're in the left flow, clockwise otherwise.
i.uv.y -= sign(left) * _Time.y;
DMGregory
la source
C'est bien. Avez-vous l'intention de fournir le code ici ou sur GitHub afin que la communauté puisse contribuer à apporter des améliorations? Sinon, veuillez envisager de le faire.
Confinement du
Pas de tels plans à l'heure actuelle. Les images ci-dessus ont été créées avec une preuve de concept rapide et hacky, pas un package autonome qui conviendrait à ce type d'utilisation. Faites-moi savoir si vous avez besoin d'une main pour reproduire tout cela et je peux vous expliquer ce dont vous avez besoin.
DMGregory
J'ai pu fabriquer la particule de mousse, mais j'ai besoin d'aide pour créer le shader d'eau et deuxièmement, couper le shader d'eau autour des formes (WaterCatcher).
Confinement
J'ai ajouté un extrait de code de shader montrant comment fonctionne le shader d'écrêtage.
DMGregory
@DMGregory WoooW !!! Désolé, je ne suis pas ici depuis un moment. Je travaillais sur d'autres trucs. Je passe maintenant en
revue
1
  1. Vous pouvez déformer le maillage en cascade lors de la collision d'objets pour correspondre au modèle de collisionneur requis.

  2. Le système de particules à usage intensif le plus simple et le plus précis, mais le plus performant - crée un système de particules avec collisionneurs et utilise chaque particule comme une goutte d'eau. Mais cela semble un peu étrange si vous avez un sprite par défaut et si le nombre de particules est petit et trop grand. Mais ses performances sont lourdes, vous ne voulez donc pas de simulation de molécules dans votre jeu.

J'irais avec 1.

  • Mais CPU de déformation de maillage - c'est lent, mais peut fonctionner pour vous.
  • J'utiliserais des shaders pour y parvenir - exemple de shader d'eau - le maillage a des effets comme il entre en collision avec d'autres maillages et il est beaucoup plus rapide que les méthodes précédentes. Je suppose qu'il est possible de faire du maillage pour arrêter le rendu dans une forme projetée - c'est le changement que vous devez apporter au shader à eau normal, c'est compliqué à réaliser si vous n'êtes pas familier avec les shaders.

Pas de solution facile avec de bonnes performances.

Résultat du système de particules: (Pour changer les valeurs j'ai dû attendre environ 3-4s, c'est lent) Résultat de collision du système de particules

Candid Moon _Max_
la source
Une alternative au point 1, mais qui pourrait être un peu plus complexe, est d'avoir votre propre système de "particules" qui laisse tomber les collisionneurs de points / sphères et respecte la physique. Et puis "simplement" générer un maillage basé sur ces points. à peu près comment fonctionne le rendu de ligne. La seule chose qui doit être résolue est de savoir comment vous diviseriez les points pour aller dans 2 directions lorsque vous heurtez un collisionneur comme dans votre capture d'écran. Mais ne pensez pas que cela doit être difficile. OU vous pouvez simplement placer les points statiquement et tracer une ligne entre eux. Tu as juste besoin d'un joli shader.
Sidar
@Sidar Ouais, approche intéressante. L'une des méthodes consisterait également à créer plusieurs rendus de piste et à les déplacer relativement du point de partage. Et vérifiez les collisions via un composant collisionneur - mais ce n'est qu'une solution de contournement.
Candid Moon _Max_
Quoi qu'il en soit, si OP ne souhaite pas le configurer manuellement, les données doivent être dynamiques ou statiques. Je me demande si vous pourriez utiliser un système de particules normal avec collision activée, puis à proximité entre les points pour dessiner une bande quadruple. Le nombre de particules n'a pas besoin d'être élevé pour cela.
Sidar
N'est-ce pas par particule? Je suppose qu'en fonction du style que vous recherchez, cela pourrait très bien fonctionner.
Sidar