Come creare una cascata di fisica 2D


8

Sto cercando di creare una cascata che assomigli alla prima immagine in basso (controlla questo video per un'idea migliore di ciò che voglio ottenere) con proprietà fisiche in modo che possa spostarsi o aggirare oggetti con collettori sul suo percorso (simile al seconda immagine in basso). Anche se la cascata collegata è 3d, sono interessato a un'implementazione 2D.

Si noti che gli oggetti sono dinamici e alcuni si muovono frequentemente, quindi la cascata deve rimodellare ogni frame. Gli oggetti si muovono lentamente o spostandosi in posizioni diverse o ruotando. Come si può fare?

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Risposte:


13

Volevo vedere se potevo farlo senza rigenerare dinamicamente la mesh per la cascata ogni frame. Si scopre, c'è un modo. : D

Animazione di cascate

Ogni oggetto che può bloccare la cascata (oggetti che portano un WaterCatchercopione nel mio prototipo) ha una maglia di contorno che avvolge il suo perimetro. (Questo può essere generato automaticamente in anticipo usando la forma del collider)

Questa maglia di contorno rende l'acqua che scorre lungo l'oggetto. Uso uno shader per clipestrarre la parte che si trova sotto l'oggetto. Traccio anche un punto di "cattura" sinistro e destro in cui una cascata atterra sull'oggetto e scorre rispettivamente a sinistra oa destra, in modo da poter clipuscire dalla parte che è a sinistra della cascata a destra e a destra della cascata a sinistra.

Animazione che mostra la maglia della pelle dell'acqua

Quindi le cadute verticali sono solo quad primitive di base, allungate alla lunghezza appropriata. Uso un altro shader per scorrere la trama della cascata sopra le cascate e la dissolvo alle estremità superiore e inferiore. Quindi strato su un sistema di particelle di schiuma nel punto di impatto per aiutare a coprire la miscela.

Ecco un primo piano in modo da poter vedere i componenti.

Primo piano ancora di effetto cascata

In cima ho una cascata "radice" per dare il via alle cose. Ogni fotogramma, dopo che tutti gli Update()script sono stati eseguiti per spostare le cose in giro, spara CircleCastverso il basso, per vedere se la sua acqua colpisce qualcosa. Se colpisce a WaterCatcher, gli dice di mostrare la sua pelle a valle del punto ferita.

Determino "a valle" usando il colpo normale - se è molto vicino alla verticale, o se la cascata in arrivo attraversa i bordi che si inclinano in entrambe le direzioni, quindi versiamo sia a sinistra che a destra.

Ognuno WaterCatcherha una cascata a sinistra e una a destra, che abilita e posiziona sul suo lato più lontano se si rovescia in quella direzione - altrimenti rimangono nascosti. Queste cascate a loro volta CircleCastscendono verso il basso per trovare ciò su cui si riversano, e così via ...

Il prototipo presenta ancora alcuni problemi visivi che potrebbero essere migliorati: il flusso d'acqua lungo un oggetto si apre contemporaneamente invece di animare, e le regole del flusso potrebbero usare un po 'più di tolleranza o isteresi in modo che non si interrompano facilmente oggetti rotanti. Penso che questi dovrebbero essere problemi abbastanza risolvibili.

Texture di sfondo, rocce e piattaforme rotanti via Kenney


Ecco i trucchi che uso nel mio shader di frammenti del collettore d'acqua:

// 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;

Questo è fantastico Hai in programma di fornire il codice qui o su GitHub in modo che la community possa contribuire a migliorare? Altrimenti, considera di farlo.
Contenimento

Nessun piano al momento attuale. Le immagini sopra sono state create con una prova del concetto veloce e confusa, non un pacchetto autonomo che sarebbe adatto per quel tipo di utilizzo. Fammi sapere se hai bisogno di una mano per replicare qualcosa e posso guidarti attraverso ciò che è necessario.
DMGregory

Sono stato in grado di creare la particella di schiuma, ma ho bisogno di aiuto per creare lo shader dell'acqua e, in secondo luogo, ritagliare lo shader dell'acqua attorno alle forme (WaterCatcher).
Contenimento

Ho aggiunto uno snippet di codice shader che mostra come funziona lo shader di ritaglio.
DMGregory

@DMGregory WoooW !!! Mi dispiace, non sono qui da un po '. Stava lavorando su altre cose. Ora sto
esaminando la

1
  1. È possibile deformare la mesh a cascata in caso di collisione dell'oggetto in modo che corrisponda al modello di collisione richiesto.

  2. Il più semplice e preciso, ma più performante - il sistema di particelle per uso intensivo - crea un sistema di particelle con collettori e usa ogni particella come una goccia d'acqua. Ma sembra un po 'strano se hai uno sprite predefinito e se il conteggio delle particelle è piccolo e sono troppo grandi. Ma le prestazioni sono elevate, quindi non vuoi la simulazione di molecole nel tuo gioco.

Vorrei andare con 1.

  • Ma la CPU di deformazione della mesh - è lenta, ma potrebbe funzionare per te.
  • Userei gli shader per raggiungere questo obiettivo - Esempio di shader d'acqua - la mesh ha effetti come se si scontrasse con altre mesh ed è molto più veloce dei metodi precedenti. Suppongo che sia possibile creare mesh per interrompere il rendering in una forma proiettata: questo è il cambiamento che dovresti apportare al normale shader d'acqua, è complicato da realizzare se non hai familiarità con gli shader.

Nessuna soluzione facile con buone prestazioni.

Risultato del sistema particellare: (Per modificare i valori ho dovuto attendere circa 3-4 secondi, è lento) Risultato della collisione del sistema particellare


Un'alternativa al punto 1, ma potrebbe essere un po 'più complessa, è avere il proprio sistema di "particelle" che rilascia punti / collisori di sfere e rispetta la fisica. E poi "semplicemente" genera una mesh basata su quei punti. praticamente come funziona il renderizzatore di linee. L'unica cosa che deve essere risolta è come dividere i punti per andare in 2 direzioni quando si colpisce un collider come fa nello screenshot. Ma non pensare che debba essere difficile. O potresti semplicemente posizionare i punti staticamente e tracciare una linea tra di loro. Hai solo bisogno di un bel shader.
Sidar,

@Sidar Sì, approccio interessante. Uno dei metodi sarebbe anche quello di creare più renderer di traccia e spostarli relativamente dal punto di divisione. E controlla le collisioni tramite alcuni componenti del collider, ma questa è solo una soluzione alternativa.
Candid Moon _Max_

In ogni caso, se OP non vuole configurarlo manualmente, i dati devono essere dinamici o staticamente cotti. Mi chiedo se potresti usare un normale sistema di particelle con la collisione abilitata e quindi avvicinarti tra i punti per disegnare una striscia quadrupla. Il conteggio delle particelle non deve essere elevato per questo.
Sidar,


Non è per particella? Immagino che, a seconda dello stile che stai cercando, potrebbe funzionare abbastanza bene.
Sidar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.