{"id":145,"date":"2025-08-18T09:20:21","date_gmt":"2025-08-18T09:20:21","guid":{"rendered":"https:\/\/blog.gabrielescaggiante.com\/?p=145"},"modified":"2025-08-18T09:20:23","modified_gmt":"2025-08-18T09:20:23","slug":"come-creare-un-effetto-acqua-dinamico-in-unity-2d","status":"publish","type":"post","link":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/","title":{"rendered":"Come creare un effetto acqua dinamico in Unity 2D"},"content":{"rendered":"\n<p>Un effetto particolarmente interessante presente in molti videogiochi \u00e8 la deformazione degli specchi d&#8217;acqua in reazione al movimento del giocatore o alla caduta di oggetti.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-29-1024x576.png\" alt=\"\" class=\"wp-image-146\" srcset=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-29-1024x576.png 1024w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-29-300x169.png 300w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-29-768x432.png 768w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-29-1536x864.png 1536w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-29.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Ori And The Blind Forest: quando il giocatore cade in acqua la superficie del liquido si deforma producendo onde che si disperdono lentamente.<\/figcaption><\/figure>\n\n\n\n<p>In questo articolo vedremo come realizzare un effetto di questo tipo in Unity, analizzando alcune soluzioni possibili.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Le basi &#8211; un sistema a molle<\/h2>\n\n\n\n<p>Nella vita reale il movimento dei fluidi \u00e8 un argomento parecchio complesso. Riprodurlo fedelmente richiede tecniche avanzate di simulazione. Questo, a sua volta, implica un utilizzo intenso di risorse computazionali per un risultato che in molti casi non vale la pena ricercare. <\/p>\n\n\n\n<p>In questo articolo esamineremo una tecnica alternativa, usatissima in molti giochi 2D di successo, basata sulle <strong>molle<\/strong>.<\/p>\n\n\n\n<p>Nella vita reale, le molle sono oggetti di tipo elastico: se una molla viene allungata e poi lasciata libera, torner\u00e0 alla sua lunghezza originale.<\/p>\n\n\n\n<p>La legge fisica che descrive il comportamento dei materiali elastici \u00e8 la <strong>legge di Hooke<\/strong>.<\/p>\n\n\n\n<p>Essa afferma che un corpo elastico subisce una deformazione direttamente proporzionale allo sforzo&nbsp;a esso applicato. In formule, questo equivale a dire:<\/p>\n\n\n\n<p>$$F=-k\\cdot\\Delta x$$<\/p>\n\n\n\n<p>Dove \\(F\\) \u00e8 la forza elastica, \\(k\\) \u00e8 la costante elastica e \\(\\Delta x\\) \u00e8 l&#8217;allungamento o l&#8217;accorciamento della molla rispetto alla posizione di riposo.<\/p>\n\n\n\n<p>Una molla, dopo essere stata allungata, in assenza di smorzamento non solo ritorna alla propria lunghezza originaria, ma addirittura la supera per via della forza accumulata. Se non ci sono forze esterne che agiscono sulla molla, questa comincer\u00e0 ad allungarsi e ad accorciarsi in un ciclo infinito, in un modo oscillatorio.<\/p>\n\n\n\n<p>Questo \u00e8 perfetto per i nostri scopi: vogliamo infatti simulare le onde attraverso una lunga fila di molle che reagiscono a forze esterne deformando la superficie dell&#8217;acqua.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setup: creiamo la mesh<\/h2>\n\n\n\n<p>Il nostro obiettivo \u00e8 avere una mesh generata in maniera dinamica che possa essere modificata dalla compressione e dilatazione delle molle.<\/p>\n\n\n\n<p>La mesh in questione \u00e8 molto semplice: un piano 2D, suddiviso un numero arbitrario di volte. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private void generateMesh() {\n    Mesh mesh = new Mesh();\n    Vector3[] vertices = new Vector3&#091;(resolution + 1) * 2&#093;;\n    int[] triangles = new int&#091;resolution * 6&#093;;\n    Vector2[] uv = new Vector2&#091;vertices.Length&#093;;\n\n    for(int x = 0; x &lt;= resolution; x++) {\n        int index = x * 2;\n        float normalizedX = (float)x \/ resolution;\n        vertices&#091;index&#093; = new Vector3(normalizedX, 0, 0);\n        vertices&#091;index + 1&#093; = new Vector3(normalizedX, 1, 0);\n\n        uv&#091;index&#093; = new Vector2(normalizedX, 0);\n        uv&#091;index + 1&#093; = new Vector2(normalizedX, 1);\n    }\n\n    int triangleIndex = 0;\n    for(int x = 0; x &lt; resolution; x++) {\n        int bottomLeft = x * 2;\n        int topLeft = bottomLeft + 1;\n        int bottomRight = bottomLeft + 2;\n        int topRight = bottomLeft + 3;\n\n        triangles&#091;triangleIndex++&#093; = bottomLeft; \n        triangles&#091;triangleIndex++&#093; = topLeft; \n        triangles&#091;triangleIndex++&#093; = topRight;\n        triangles&#091;triangleIndex++&#093; = bottomLeft; \n        triangles&#091;triangleIndex++&#093; = topRight; \n        triangles&#091;triangleIndex++&#093; = bottomRight;\n    }\n\n    mesh.vertices = vertices;\n    mesh.uv = uv;\n    mesh.triangles = triangles;\n    mesh.RecalculateNormals();\n    mesh.RecalculateBounds();\n\n    GetComponent&lt;MeshFilter>().mesh = mesh;\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">generateMesh<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">Mesh<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Mesh<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">&#091;(<\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Length<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topLeft<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">bottomRight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topRight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">topLeft<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">topRight<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">topRight<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">bottomRight<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateNormals<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateBounds<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">GetComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">MeshFilter<\/span><span style=\"color: #D4D4D4\">&gt;().<\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Il codice in questione crea un piano con un numero di suddivisioni pari al valore della variabile <code><code data-enlighter-language=\"csharp\" class=\"EnlighterJSRAW\">resolution<\/code><\/code><\/p>\n\n\n\n<p>I vertici su cui lavoreremo sono i vertici superiori<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creiamo le molle<\/h2>\n\n\n\n<p>Iniziamo specificando 3 variabili:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">public int springsCount<\/code>: il numero di molle uniformemente posizionate lungo la superficie dell&#8217;acqua<\/li>\n\n\n\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">public static float elasticFactor<\/code>: la costante elastica nella legge di Hooke, comune a tutte le molle che usiamo.<\/li>\n\n\n\n<li><code>public static float dampingFactor<\/code>: un numero da 0 a 1 che indica quanto viene smorzato il movimento della molla, ovvero quanto velocemente la molla torna alla propria posizione originale<\/li>\n<\/ul>\n\n\n\n<p>Per comodit\u00e0, definiamo una classe <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Spring<\/code> le cui istanze rappresenteranno una singola molla. Ogni molla deve memorizzare:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Posizione (verticale)<\/li>\n\n\n\n<li>Posizione iniziale, intesa come posizione in cui la molla si trova a riposo. <\/li>\n\n\n\n<li>Velocit\u00e0 (verticale)<\/li>\n<\/ul>\n\n\n\n<p>All&#8217;interno della classe Spring definiamo due metodi void:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">public void ApplyForce(float force)<\/code>: lo useremo per applicare la forza a una specifica istanza di molla<\/li>\n\n\n\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">public void Update()<\/code>: metodo che chiameremo per aggiornare la posizione della molla<\/li>\n<\/ul>\n\n\n\n<p>Calcoliamo ora la relazione tra forza elastica, velocit\u00e0 e posizione della molla (d&#8217;ora in avanti, per posizione della molla indichiamo la posizione del punto pi\u00f9 distante dalla posizione di riposo della molla)<\/p>\n\n\n\n<p>$$F=-k\\cdot\\Delta x \\quad F=ma$$<\/p>\n\n\n\n<p>\\(m\\), la massa, possiamo considerarla pari a 1 in modo da semplificare i conti. Da qui otteniamo:<\/p>\n\n\n\n<p>$$-k\\cdot\\Delta x = a$$<\/p>\n\n\n\n<p>da cui<\/p>\n\n\n\n<p>$$v_{n+1}=v_{n}-k\\cdot\\Delta x \\cdot dt$$<\/p>\n\n\n\n<p>e<\/p>\n\n\n\n<p>$$P_{n+1}=P{n}+v_{n+1} \\Delta \\cdot dt$$<\/p>\n\n\n\n<p>Dove \\(v_{i}\\) e \\(P_{i}\\) rappresentano rispettivamente la velocit\u00e0 e la posizione all&#8217;istante i.<\/p>\n\n\n\n<p>Tutto ci\u00f2 si riduce al seguente codice:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private class Spring {\n    public float position = 1, startPosition = 1, velocity = 0;\n\n    public void ApplyForce(float force) {\n        velocity += force;\n    }\n\n    public void Update() {\n        float positionDelta = startPosition - position;\n        float force = positionDelta * elasticFactor;\n        ApplyForce(force);\n        position += velocity;\n        velocity *= dampingFactor;\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Spring<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">startPosition<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Update<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">positionDelta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">startPosition<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">positionDelta<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">elasticFactor<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> *= <\/span><span style=\"color: #9CDCFE\">dampingFactor<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Si noti che il codice in questione non include la moltiplicazione per <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Time.DeltaTime<\/code>. Questo perch\u00e9 chiameremo <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Update()<\/code> da FixedUpdate, che ha un deltaTime fisso. Nel caso in cui si voglia adattare questo sistema a  un gioco pi\u00f9 grande, in cui ci si aspetta di modificare <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Time.FixedDeltaTime<\/code>, allora \u00e8 conveniente aggiungerlo.<\/p>\n\n\n\n<p>Introduciamo poi un metodo per generare le molle e un metodo per ripristinare la situazione di equilibrio iniziale, che torner\u00e0 utile dopo. Le istanze create dal generatore saranno aggiunte a una lista <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">private List&lt;Spring&gt;<\/code> che le conterr\u00e0.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private void generateSprings() {\n    for(int i = 0; i &lt; springsCount; i++) {\n        springs.Add(new Spring());\n    }\n}\n\nprivate void resetSprings() {\n    for(int i = 0; i &lt; springs.Count; i++) {\n        springs&#091;i&#093;.velocity = 0f;\n        springs&#091;i&#093;.position = springs&#091;i&#093;.startPosition;\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">generateSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Add<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Spring<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">resetSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">startPosition<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Interagiamo con le molle<\/h2>\n\n\n\n<p>Vediamo ora di fare in modo che, quando un oggetto entra a contatto con l&#8217;acqua, applichi una forza alle molle mettendole in movimento. Utilizzeremo il movimento delle molle per deformare l&#8217;acqua.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>public void displace(float x, float force = 0.15f) {\n    if(springs.Count == 0) return;\n\n    Vector3 localPos = transform.InverseTransformPoint(new Vector3(x, 0, 0));\n    float scaledX = Mathf.Clamp01(localPos.x) * (springs.Count - 1);\n    float rightWeight = scaledX % 1;\n    float leftWeight = 1 - rightWeight;\n    int leftIndex = Mathf.FloorToInt(scaledX);\n    int rightIndex = leftIndex + 1;\n\n    if(leftIndex >= 0) {\n        springs&#091;leftIndex&#093;.ApplyForce(force * leftWeight);\n    }\n    if(rightIndex &lt;= springs.Count - 1) {\n        springs&#091;rightIndex&#093;.ApplyForce(force * rightWeight);\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">displace<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.15f<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">localPos<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">transform<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">InverseTransformPoint<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">scaledX<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Clamp01<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">localPos<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">) * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rightWeight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">scaledX<\/span><span style=\"color: #D4D4D4\"> % <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">leftWeight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">rightWeight<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">FloorToInt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">scaledX<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rightIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\"> &gt;= <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">leftWeight<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rightIndex<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">rightIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">rightWeight<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Il metodo displace prende in input la posizione <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">x<\/code> a cui applicare la forza in input. La posizione \u00e8 trasformata nello spazio locale e usata per trovare le due molle pi\u00f9 vicine a cui applicare la forza. La forza applicata alle molle \u00e8 proporzionale alla distanza tra x e la molla. Cos\u00ec facendo applicare il displacement a met\u00e0 tra due molle equivale ad applicare due forze equivalenti alle due molle, la cui somma \u00e8 pari alla forza originale.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"447\" height=\"278\" src=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-30.png\" alt=\"Applicare una forza tra due molle equivale ad applicare met\u00e0 forza a una molla e met\u00e0 forza all'altra\" class=\"wp-image-167\" srcset=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-30.png 447w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-30-300x187.png 300w\" sizes=\"auto, (max-width: 447px) 100vw, 447px\" \/><\/figure>\n\n\n\n<p>Questo sistema non tiene conto n\u00e9 della dimensione n\u00e9 della forma dell&#8217;oggetto che determina il displacement. In un&#8217;implementazione pi\u00f9 completa, un&#8217;idea potrebbe essere inserire un parametro <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">width<\/code> che specifica l&#8217;area di deformazione spalmando la forza su una superficie arbitrariamente larga.<\/p>\n\n\n\n<p>Possiamo gestire la chiamata a displace per gli oggetti che interagiscono con l&#8217;acqua in questo modo:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private void OnTriggerEnter2D(Collider2D collision) {\n    float force = defaultDisplacementForce;\n    Rigidbody2D rigidbody = collision.GetComponent&lt;Rigidbody2D>();\n    if(rigidbody != null) {\n        float t = Mathf.Clamp01(rigidbody.linearVelocity.magnitude \/ maxImpactVelocity);\n        force = -Mathf.Lerp(defaultDisplacementForce, maxDisplacementForce, t);\n    }\n    displace(collision.transform.position.x , force);\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">OnTriggerEnter2D<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">Collider2D<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">collision<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">defaultDisplacementForce<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">Rigidbody2D<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rigidbody<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">collision<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">Rigidbody2D<\/span><span style=\"color: #D4D4D4\">&gt;();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rigidbody<\/span><span style=\"color: #D4D4D4\"> != <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Clamp01<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rigidbody<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">linearVelocity<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">magnitude<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">maxImpactVelocity<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = -<\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Lerp<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">defaultDisplacementForce<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">maxDisplacementForce<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">displace<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">collision<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">transform<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> , <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Definiamo due campi pubblici:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">defaultDisplacementForce<\/code>: la forza base (minima) da applicare in caso di collisione<\/li>\n\n\n\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">maxDisplacementForce<\/code>: la massima forza applicabile<\/li>\n<\/ul>\n\n\n\n<p>Il codice in questione, quando un oggetto colpisce l&#8217;acqua, verifica se l&#8217;oggetto ha un componente <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Rigidbody2D<\/code>, e in caso usa la sua velocit\u00e0 assoluta per modificare la forza da applicare. In caso contrario viene usata direttamente la forza di default.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Aggiorniamo la mesh<\/h2>\n\n\n\n<p>Ora che il movimento delle molle \u00e8 implementato correttamente, possiamo aggiornare la mesh in relazione alla loro posizione.<\/p>\n\n\n\n<p>Innanzitutto vediamo di creare due riferimenti: uno alla mesh e uno ai vertici che la costituiscono, e di generare rispettivamente la mesh e le molle:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private Vector3[] vertices;\nprivate Mesh mesh;\n\nprivate void Start() {\n    generateMesh();\n    mesh = GetComponent&lt;MeshFilter>().mesh;\n    vertices = mesh.vertices;\n    generateSprings();\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Mesh<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Start<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">generateMesh<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">GetComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">MeshFilter<\/span><span style=\"color: #D4D4D4\">&gt;().<\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">generateSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Dopodich\u00e9 dobbiamo aggiornare la mesh sulla base delle posizioni delle molle.<\/p>\n\n\n\n<p>Vedremo due modi per farlo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Assegnando una molla a ciascun vertice della mesh<\/li>\n\n\n\n<li>Mantenendo indipendenza tra il numero di molle e la risoluzione della mesh<\/li>\n<\/ul>\n\n\n\n<p>Il primo metodo \u00e8 il pi\u00f9 semplice, ma, come vedremo, anche il meno versatile.<\/p>\n\n\n\n<p>Nel codice sopra abbiamo definito due variabili:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">resolution<\/code> (il numero di suddivisioni)<\/li>\n\n\n\n<li><code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">springsCount<\/code> (il numero di molle)<\/li>\n<\/ul>\n\n\n\n<p>Per usare il primo metodo, facciamo in modo che resolution e springCount abbiano lo stesso esatto valore. <\/p>\n\n\n\n<p>A quel punto, possiamo semplicemente assegnare a ogni vertice sulla superficie dell&#8217;acqua la posizione della rispettiva molla.<\/p>\n\n\n\n<p>Ecco come:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/METODO 1: resolution = springsCount\n\nprivate void FixedUpdate() {\n    if(vertices == null || springs == null) return;\n\n    for(int i = 0; i &lt; springs.Count; i++) {\n        springs&#091;i&#093;.Update();\n    }\n\n    updateMeshFromSprings();\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/METODO 1: resolution = springsCount<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">FixedUpdate<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> || <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">Update<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">FixedUpdate<\/code> aggiorniamo le posizioni di ogni molla ciclando sulla lista di molle e chiamando <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Update()<\/code> su ogni istanza. Dopodich\u00e9 chiamiamo un nuovo metodo <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">updateMeshFromSprings()<\/code>, responsabile dell&#8217;aggiornamento della mesh in base alla posizione delle molle. Questo metodo \u00e8 implementato come segue:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/METODO 1: resolution = springsCount\n\nprivate void updateMeshFromSprings() {\n    for(int i = 0; i &lt; resolution; i++) {\n        int topIndex = i * 2 + 1;\n        vertices&#091;topIndex&#093;.y = springs&#091;i&#093;.position;\n    }\n    mesh.vertices = vertices;\n    mesh.RecalculateBounds();\n    mesh.RecalculateNormals();\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/\/METODO 1: resolution = springsCount<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">topIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateBounds<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateNormals<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Molto semplicemente, assegnamo alla coordinata y di ciascun vertice la posizione della rispettiva molla. Questo richiede che il numero di molle sia pari al numero di suddivisioni, altrimenti ci sarebbero vertici senza molle.<\/p>\n\n\n\n<p>Usciti dal ciclo, assegnamo i nuovi vertici alla mesh. <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"444\" height=\"331\" src=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-31.png\" alt=\"Ogni molla agisce solamente su un vertice. Il numero di molle \u00e8 pari al numero di vertici in superficie.\" class=\"wp-image-170\" srcset=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-31.png 444w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-31-300x224.png 300w\" sizes=\"auto, (max-width: 444px) 100vw, 444px\" \/><figcaption class=\"wp-element-caption\">Ogni molla agisce solamente su un vertice. Il numero di molle \u00e8 pari al numero di vertici in superficie.<\/figcaption><\/figure>\n\n\n\n<p>Possiamo creare uno spawner di oggetti in modo da verificare che tutto funzioni correttamente. Creiamo un oggetto vuoto in Unity, chiamiamolo SphereSpawner, e assegnamogli il seguente script:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using UnityEngine;\n\npublic class SphereSpawner : MonoBehaviour\n{\n    public Sprite spriteImage;\n\n\n    void Update()\n    {\n        if(Input.GetMouseButtonDown(0)) {\n            SpawnAtMouse();\n        }\n    }\n\n    void SpawnAtMouse() {\n        Vector3 mouseScreen = Input.mousePosition;\n        Vector3 worldPos = Camera.main.ScreenToWorldPoint(mouseScreen);\n        worldPos.z = 0f;\n        GameObject sphere = new GameObject(\"Sphere\");\n        sphere.transform.position = worldPos;\n        SpriteRenderer renderer = sphere.AddComponent&lt;SpriteRenderer>();\n        if(spriteImage != null) {\n            renderer.sprite = spriteImage;\n        }\n        sphere.AddComponent&lt;CircleCollider2D>();\n        sphere.AddComponent&lt;Rigidbody2D>();\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">UnityEngine<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">SphereSpawner<\/span><span style=\"color: #D4D4D4\"> : <\/span><span style=\"color: #4EC9B0\">MonoBehaviour<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Sprite<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">spriteImage<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Update<\/span><span style=\"color: #D4D4D4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Input<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetMouseButtonDown<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">SpawnAtMouse<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">SpawnAtMouse<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mouseScreen<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Input<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">mousePosition<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">worldPos<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Camera<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">main<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">ScreenToWorldPoint<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">mouseScreen<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">worldPos<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">z<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">GameObject<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sphere<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">GameObject<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;Sphere&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">sphere<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">transform<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">worldPos<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">SpriteRenderer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">renderer<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">sphere<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">AddComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">SpriteRenderer<\/span><span style=\"color: #D4D4D4\">&gt;();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">spriteImage<\/span><span style=\"color: #D4D4D4\"> != <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">renderer<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">sprite<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">spriteImage<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">sphere<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">AddComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">CircleCollider2D<\/span><span style=\"color: #D4D4D4\">&gt;();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">sphere<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">AddComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">Rigidbody2D<\/span><span style=\"color: #D4D4D4\">&gt;();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In questo modo, ogni volta che cliccheremo il tasto sinistro del mouse, comparir\u00e0 uno sprite con Rigidbody in corrispondenza del puntatore.<\/p>\n\n\n\n<p>A questo punto dovreste vedere le onde formarsi quando una sfera colpisce la superficie dell&#8217;acqua. L&#8217;unico problema \u00e8 che le onde non si propagano, ma rimangono fisse nella loro posizione originale. <\/p>\n\n\n\n<p>Prima di vedere come implementare il secondo metodo di aggiornamento della mesh, \u00e8 conveniente lavorare alla propagazione delle onde. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Propagazione delle onde<\/h2>\n\n\n\n<p>Per fare in modo che le onde si propaghino lungo la superficie dell&#8217;acqua, dobbiamo immaginare che ciascuna molla, spostandosi dalla propria posizione di equilibrio, tiri con s\u00e9 le molle vicine, che vedranno variare la loro velocit\u00e0 e posizione sulla base della molla in movimento.<\/p>\n\n\n\n<p>Definiamo allora una variabile pubblica <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">spreadFactor<\/code>, che indica quanto il movimento di ogni molla si propaga alle molle vicine. Questo valore andr\u00e0 tenuto basso, perch\u00e9 altrimenti si corre il rischio di avere un sistema in cui, se si applica una forza a una molla, le molle vicine subiscono una forza superiore. Un sistema del genere \u00e8 instabile e non funzionante.<\/p>\n\n\n\n<p>Nel <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">FixedUpdate<\/code>, definiamo due liste di float: <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">leftDeltas<\/code> e <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">rightDeltas<\/code>. Ognuna di queste liste manterr\u00e0, in ogni indice, la differenza di posizione tra la molla con quell&#8217;indice e la molla rispettivamente a sinistra e a destra.<\/p>\n\n\n\n<p>Quello che dobbiamo fare \u00e8 popolare queste liste e, contemporaneamente, aggiornare le velocit\u00e0 delle molle in relazione alle loro differenze di posizione. Dopodich\u00e9, in un secondo passaggio, modificheremo la posizione delle molle in base ai valori memorizzati in <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">leftDeltas<\/code> e <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">rightDeltas<\/code>.<\/p>\n\n\n\n<p>Questo equivale ad applicare una forza proporzionale alla differenza di posizione tra le varie molle, andando cos\u00ec a &#8220;spalmare&#8221; la forza iniziale lungo l&#8217;intera superficie dell&#8217;acqua.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private void FixedUpdate() {\n    if(vertices == null || springs == null) return;\n\n    for(int i = 0; i &lt; springs.Count; i++) {\n        springs&#091;i&#093;.Update();\n    }\n\n    updateMeshFromSprings();\n\n\n      for(int i = 0; i &lt; springs.Count; i++) {\n          if(i > 0) {\n              leftDeltas&#091;i&#093; = spreadFactor * (springs&#091;i&#093;.position - springs&#091;i - 1&#093;.position);\n              springs&#091;i - 1&#093;.velocity += leftDeltas&#091;i&#093;;\n          }\n\n          if(i &lt; springs.Count - 1) {\n              rightDeltas&#091;i&#093; = spreadFactor * (springs&#091;i&#093;.position - springs&#091;i + 1&#093;.position);\n              springs&#091;i + 1&#093;.velocity += rightDeltas&#091;i&#093;;\n          }\n      }\n\n      for(int i = 0; i &lt; springs.Count; i++) {\n          if(i > 0) {\n              springs&#091;i - 1&#093;.position += leftDeltas&#091;i&#093;;\n          }\n\n          if(i &lt; springs.Count - 1) {\n              springs&#091;i + 1&#093;.position += rightDeltas&#091;i&#093;;\n          }\n      }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">FixedUpdate<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> || <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">Update<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Questo metodo propaga la forza una molla alla volta. Per velocizzare la propagazione possiamo aggiungere una variabile <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">wavePropagationPasses<\/code> che indica quante volte ripetere la propagazione:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>for(int j = 0; j &lt; wavePropagationPasses; j++) {\n    for(int i = 0; i &lt; springs.Count; i++) {\n        if(i > 0) {\n            leftDeltas&#091;i&#093; = spreadFactor * (springs&#091;i&#093;.position - springs&#091;i - 1&#093;.position);\n            springs&#091;i - 1&#093;.velocity += leftDeltas&#091;i&#093;;\n        }\n\n        if(i &lt; springs.Count - 1) {\n            rightDeltas&#091;i&#093; = spreadFactor * (springs&#091;i&#093;.position - springs&#091;i + 1&#093;.position);\n            springs&#091;i + 1&#093;.velocity += rightDeltas&#091;i&#093;;\n        }\n    }\n\n    for(int i = 0; i &lt; springs.Count; i++) {\n        if(i > 0) {\n            springs&#091;i - 1&#093;.position += leftDeltas&#091;i&#093;;\n        }\n\n        if(i &lt; springs.Count - 1) {\n            springs&#091;i + 1&#093;.position += rightDeltas&#091;i&#093;;\n        }\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">wavePropagationPasses<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Volendo possiamo fermarci qui. Tuttavia, poich\u00e9 l&#8217;aggiornamento della mesh richiede che il numero di molle sia uguale alla risoluzione, una risoluzione maggiore automaticamente implica una propagazione pi\u00f9 lenta delle onde, dato che in ogni <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">FixedUpdate<\/code> la propagazione coinvolge <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">wavePropagationPasses<\/code> molle.<\/p>\n\n\n\n<p>Ci sono due modi per risolvere: uno \u00e8 impostare <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">wavePropagationPasses<\/code> come frazione del numero di molle, ad esempio <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">wavePropagationPasses = springs.Count \/ 8<\/code>.<\/p>\n\n\n\n<p>Questo sistema, tuttavia, fa assumere al loop di propagazione delle onde una complessit\u00e0 computazionale pari a \\(O(n^2)\\), il che non \u00e8 ottimale.<\/p>\n\n\n\n<p>Una soluzione migliore \u00e8 quella di eliminare il vincolo che forza il numero di molle ad essere pari al numero di vertici in superficie, e rivedere la generazione della mesh per permettere di avere poche molle anche con un gran numero di vertici. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Aggiornamento della mesh tramite spline Catmull-Rom<\/h2>\n\n\n\n<p>Per fare in modo che le onde siano generate da un numero di molle inferiore al numero di vertici in superficie possiamo ragionare per interpolazione. Supponiamo di avere 500 vertici e 5 molle.<\/p>\n\n\n\n<p>Per poter associare ogni vertice a una posizione nello spazio, dobbiamo trovare una funzione che interpoli le 5 molle in modo naturale. Questo significa trovare una funzione \\(f(x)\\) che in corrispondenza delle molle assuma come valore la loro posizione sull&#8217;asse y, e negli altri punti un valore che indica la y che devono assumere i vertici per seguire l&#8217;andamento delle molle:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"529\" height=\"209\" src=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-32.png\" alt=\"La funzione passa tra le molle definendo una forma liscia e continua\" class=\"wp-image-172\" srcset=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-32.png 529w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-32-300x119.png 300w\" sizes=\"auto, (max-width: 529px) 100vw, 529px\" \/><figcaption class=\"wp-element-caption\">I punti rossi sono le molle, la curva nera \u00e8 la rappresentazione grafica della funzione che stiamo cercando<\/figcaption><\/figure>\n\n\n\n<p>La curva che useremo si chiama Spline Catmull-Rom. Si tratta di una funzione polinomiale definita a tratti, ovvero di una sequenza di polinomi legati insieme in modo che il loro grafico appaia coeso e continuo.<\/p>\n\n\n\n<p>Un singolo polinomio usato per costruire la spline \u00e8 un polinomio \\(P(x)\\) di terzo grado, ovvero un polinomio nella forma \\(P(x)=ax^3+bx^2+cx+d\\), ma con le seguenti caratteristiche:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\\(P(c_i)=y_i\\): il polinomio passa per il primo punto di controllo \\(c_i\\)<\/li>\n\n\n\n<li>\\(P(c_{i+1})=y_{i+1}\\): il polinomio passa per il secondo punto di controllo \\(c_{i+1}\\)<\/li>\n\n\n\n<li>\\(P'(c_i)=(y_{i+1}-y_{i-1}) \/ (c_{i+1} &#8211; c_{i-1})\\): il valore della derivata prima nel primo punto di controllo \u00e8 pari al coefficiente della retta che collega i due punti adiacenti<\/li>\n\n\n\n<li>\\(P'(c_{i+1})=(y_{i+2}-y_{i+1}) \/ (c_{i+2} &#8211; c_{i})\\): il valore della derivata prima nel secondo punto di controllo \u00e8 pari al coefficiente della retta che collega i due punti adiacenti<\/li>\n<\/ul>\n\n\n\n<p>Risolvendo il corrispettivo sistema lineare possiamo trovare i coefficienti del polinomio espressi in funzione delle posizioni di 4 molle:<\/p>\n\n\n\n<p>\\begin{aligned}<br>a &amp;= \\frac{1}{2}\\left(-p_0 + 3p_1 &#8211; 3p_2 + p_3\\right), \\\\<br>b &amp;= \\frac{1}{2}\\left( 2p_0 &#8211; 5p_1 + 4p_2 &#8211; p_3\\right), \\\\<br>c &amp;= \\frac{1}{2}\\left(-p_0 + p_2\\right),\\\\<br>d &amp;= p_1<br>\\end{aligned}<\/p>\n\n\n\n<p>Dove \\(p_i\\) indica la posizione della i-esima molla.<\/p>\n\n\n\n<p>Possiamo allora definire un metodo <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">SampleSplineAt(float localX)<\/code> usato per ottenere il valore dalla spline a una certa posizione. La posizione in questione \u00e8 espressa in un range \\([0,1]\\) che rappresenta la larghezza dell&#8217;intero specchio d&#8217;acqua.<\/p>\n\n\n\n<p>Il metodo \u00e8 implementato come segue:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private float SampleSplineAt(float localX) {\n    int segmentCount = springsCount - 1;\n    int i = Mathf.FloorToInt(localX * segmentCount);\n    i = Mathf.Clamp(i, 1, springsCount - 3);\n\n    float u = localX * segmentCount - i;\n\n    float p0 = springs&#091;i - 1&#093;.position;\n    float p1 = springs&#091;  i  &#093;.position;\n    float p2 = springs&#091;i + 1&#093;.position;\n    float p3 = springs&#091;i + 2&#093;.position;\n\n    return 0.5f * (u * (u * (u * (-p0 + 3f * p1 - 3f * p2 + p3) +\n                            (2f * p0 - 5f * p1 + 4f * p2 - p3)) +\n                       (-p0 + p2)) +\n                  (2f * p1));\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">SampleSplineAt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">segmentCount<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">FloorToInt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">segmentCount<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Clamp<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">segmentCount<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;  <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">  &#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p3<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">0.5f<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> * (-<\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">3f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">3f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">p3<\/span><span style=\"color: #D4D4D4\">) +<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                            (<\/span><span style=\"color: #B5CEA8\">2f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">5f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">4f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">p3<\/span><span style=\"color: #D4D4D4\">)) +<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                       (-<\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\">)) +<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                  (<\/span><span style=\"color: #B5CEA8\">2f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Si noti il modo in cui \u00e8 scritto il polinomio. In questo caso \u00e8 infatti possibile usare la <a href=\"https:\/\/en.wikipedia.org\/wiki\/Horner%27s_method\">Regola di Horner<\/a> per ridurre il numero di operazioni necessarie per calcolare il polinomio.<\/p>\n\n\n\n<p>L&#8217;algoritmo di Horner, infatti, permette di esprimere polinomi nella forma<\/p>\n\n\n\n<p>$${\\displaystyle P_{N}(x)=a_{0}x^{N}+a_{1}x^{N-1}+\u2026+a_{N-1}x+a_{N}}$$<\/p>\n\n\n\n<p>Come<\/p>\n\n\n\n<p>$${\\displaystyle P_{N}(x)=a_{N}+x(a_{N-1}+x(a_{N-2}+\\ldots +x(a_{1}+a_{0}x)\\ldots ))}$$<\/p>\n\n\n\n<p>Essenzialmente, nidificando l&#8217;espressione, \u00e8 possibile usare un numero minore di moltiplicazioni rispetto al metodo tradizionale. Siccome chiameremo questa funzione moltissime volte, questa ottimizzazione \u00e8 sensata.<\/p>\n\n\n\n<p>Ora possiamo aggiornare la mesh in questo modo:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private void updateMeshFromSprings() {\n    float deltaX = 1 \/ (float)resolution;\n    float localX = 0;\n    for(int i = 0; i &lt; resolution; i++) {\n        int topIndex = i * 2 + 1;\n        vertices&#091;topIndex&#093;.y = SampleSplineAt(localX);\n        localX += deltaX;\n    }\n    mesh.vertices = vertices;\n    mesh.RecalculateBounds();\n    mesh.RecalculateNormals();\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">deltaX<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> \/ (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">topIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SampleSplineAt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">deltaX<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateBounds<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateNormals<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Sleeping system<\/h2>\n\n\n\n<p>Supponiamo ora di utilizzare questo sistema in un gioco vero e proprio, e di avere vari specchi d&#8217;acqua in un&#8217;unica schermata. Supponiamo ora che il giocatore sia in grado di interagire solamente con un ristretto sottoinsieme di questi specchi d&#8217;acqua. Che cosa accade? I calcoli fisici e il sampling delle spline continuano anche per gli oggetti d&#8217;acqua che sono completamente privi di deformazioni in corso. Questo \u00e8 uno spreco.<\/p>\n\n\n\n<p>Per ottimizzare tutto ci\u00f2 possiamo introdurre un sistema di sleeping.<\/p>\n\n\n\n<p>Aggiungiamo una variabile privata booleana <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">isAwake<\/code>, che indica se l&#8217;oggetto acqua \u00e8 &#8220;dormiente&#8221; o meno.<\/p>\n\n\n\n<p>Vogliamo che l&#8217;acqua si risvegli quando un oggetto entra in collisione, e che si addormenti quando le onde si sono completamente dissipate.<\/p>\n\n\n\n<p>Per fare ci\u00f2, possiamo impostare <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">isAwake<\/code> a <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">true<\/code> quando un oggetto entra in collisione, e prevedere un intervallo di controllo periodico che valuta se \u00e8 necessario addormentare l&#8217;acqua in base a quante onde sono presenti.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>private bool isAwake = false;\n\nprivate void Start() {\n    \/\/ ...\n    StartCoroutine(checkDisplacementEnd());\n}\n\nprivate void FixedUpdate() {\n    if(vertices == null || \n       springs  == null || \n       isAwake  == false) return;\n   \/\/...\n}\n\nIEnumerator checkDisplacementEnd() {\n    const float CHECK_INTERVAL = 2.5f;\n    const float MIN_VELOCITY_THRESHOLD = 0.00025f;\n    yield return new WaitForSeconds(CHECK_INTERVAL);\n\n    float maxAbsoluteVelocity = 0;\n    for(int i = 0; i &lt; springs.Count; i++) {\n        if(Mathf.Abs(springs&#091;i&#093;.velocity) > maxAbsoluteVelocity) {\n            maxAbsoluteVelocity = Mathf.Abs(springs&#091;i&#093;.velocity);\n        }\n    }\n\n    if(maxAbsoluteVelocity &lt; MIN_VELOCITY_THRESHOLD) {\n        isAwake = false;\n        resetSprings();\n    }\n    StartCoroutine(checkDisplacementEnd());\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Start<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ ...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">StartCoroutine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">checkDisplacementEnd<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">FixedUpdate<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> || <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">  == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> || <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\">  == <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   \/\/...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4EC9B0\">IEnumerator<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">checkDisplacementEnd<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">CHECK_INTERVAL<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2.5f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">MIN_VELOCITY_THRESHOLD<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.00025f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">yield<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">WaitForSeconds<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">CHECK_INTERVAL<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Abs<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\">) &gt; <\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Abs<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">MIN_VELOCITY_THRESHOLD<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">resetSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">StartCoroutine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">checkDisplacementEnd<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Ogni <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">CHECK_INTERVAL<\/code> secondi si cerca la massima velocit\u00e0, in valore assoluto, tra tutte le molle. Se questa velocit\u00e0 \u00e8 inferiore di <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">MIN_VELOCITY_THRESHOLD<\/code> si assume che l&#8217;acqua non abbia onde e che sia possibile &#8220;addormentarla&#8221;.<\/p>\n\n\n\n<p>Quando <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">isAwake<\/code> \u00e8 <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">true<\/code>, in <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">FixedUpdate<\/code> abbiamo un early return che evita di aggiornare le molle e di fare il sampling della spline.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Shader<\/h2>\n\n\n\n<p>Per colorare l&#8217;acqua in maniera convincente possiamo usare lo shader graph:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Usiamo due mappe Voronoi elevate a potenza e con offset temporale per simulare delle caustiche.<\/li>\n\n\n\n<li>Utilizziamo un semplice gradiente per dare colore all&#8217;acqua in base alla profondit\u00e0<\/li>\n\n\n\n<li>Usando l&#8217;UV, definiamo un offset dalla superficie entro il quale l&#8217;acqua si colora di bianco per avere un effetto &#8220;contorno&#8221;<\/li>\n\n\n\n<li>Sfruttando la derivata verticale sull&#8217;UV, implementiamo l&#8217;oscuramento dell&#8217;acqua in corrispondenza delle zone a pi\u00f9 alta variazione d&#8217;altezza.<\/li>\n<\/ul>\n\n\n\n<p>Lo shader graph risultante \u00e8 il seguente:<\/p>\n\n\n\n<figure class=\"wp-block-image alignwide size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2113\" height=\"1637\" src=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36.png\" alt=\"Shader graph contenente lo shader usato\" class=\"wp-image-186\" srcset=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36.png 2113w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36-300x232.png 300w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36-1024x793.png 1024w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36-768x595.png 768w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36-1536x1190.png 1536w, https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/image-36-2048x1587.png 2048w\" sizes=\"auto, (max-width: 2113px) 100vw, 2113px\" \/><\/figure>\n\n\n\n<p>Il risultato finale che si ottiene \u00e8 il seguente:<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls muted src=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Movie_002.mp4\"><\/video><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Codice finale<\/h2>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Profiling;\nusing UnityEngine.SocialPlatforms;\n\npublic class InteractiveWater : MonoBehaviour\n{\n    private Vector3[] vertices;\n    private Mesh mesh;\n    public int resolution = 12;\n    public int springsCount = 20;\n    public float defaultDisplacementForce = 0.5f;\n    public float maxDisplacementForce = 5f;\n    public float maxImpactVelocity = 100f;\n    public int wavePropagationPasses = 8;\n    public static float elasticFactor = 0.02f;\n    public static float dampingFactor = 0.99f;\n    private float[] leftDeltas;\n    private float[] rightDeltas;\n    public float spreadFactor = 0.02f;\n    private bool isAwake = false;\n    private List&lt;Spring> springs = new List&lt;Spring>();\n    private class Spring {\n        public float position = 1, startPosition = 1, velocity = 0;\n\n        public void ApplyForce(float force) {\n            velocity += force;\n        }\n\n        public void Update() {\n            float positionDelta = startPosition - position;\n            float force = positionDelta * elasticFactor;\n            ApplyForce(force);\n            position += velocity;\n            velocity *= dampingFactor;\n        }\n    }\n    private void Start() {\n        generateMesh();\n        mesh = GetComponent&lt;MeshFilter>().mesh;\n        vertices = mesh.vertices;\n        generateSprings();\n        leftDeltas = new float&#091;springs.Count&#093;;\n        rightDeltas = new float&#091;springs.Count&#093;;\n        StartCoroutine(checkDisplacementEnd());\n    }\n\n    private void FixedUpdate() {\n        if(vertices == null || springs == null || isAwake == false) return;\n\n        for(int i = 0; i &lt; springs.Count; i++) {\n            springs&#091;i&#093;.Update();\n        }\n\n        updateMeshFromSprings();\n\n        for(int j = 0; j &lt; wavePropagationPasses; j++) {\n            for(int i = 0; i &lt; springs.Count; i++) {\n                if(i > 0) {\n                    leftDeltas&#091;i&#093; = spreadFactor * (springs&#091;i&#093;.position - springs&#091;i - 1&#093;.position);\n                    springs&#091;i - 1&#093;.velocity += leftDeltas&#091;i&#093;;\n                }\n\n                if(i &lt; springs.Count - 1) {\n                    rightDeltas&#091;i&#093; = spreadFactor * (springs&#091;i&#093;.position - springs&#091;i + 1&#093;.position);\n                    springs&#091;i + 1&#093;.velocity += rightDeltas&#091;i&#093;;\n                }\n            }\n\n            for(int i = 0; i &lt; springs.Count; i++) {\n                if(i > 0) {\n                    springs&#091;i - 1&#093;.position += leftDeltas&#091;i&#093;;\n                }\n\n                if(i &lt; springs.Count - 1) {\n                    springs&#091;i + 1&#093;.position += rightDeltas&#091;i&#093;;\n                }\n            }\n        }\n    }\n\n    private void generateMesh() {\n        Mesh mesh = new Mesh();\n        Vector3[] vertices = new Vector3&#091;(resolution + 1) * 2&#093;;\n        int[] triangles = new int&#091;resolution * 6&#093;;\n        Vector2[] uv = new Vector2&#091;vertices.Length&#093;;\n\n        for(int x = 0; x &lt;= resolution; x++) {\n            int index = x * 2;\n            float normalizedX = (float)x \/ resolution;\n            vertices&#091;index&#093; = new Vector3(normalizedX, 0, 0);\n            vertices&#091;index + 1&#093; = new Vector3(normalizedX, 1, 0);\n\n            uv&#091;index&#093; = new Vector2(normalizedX, 0);\n            uv&#091;index + 1&#093; = new Vector2(normalizedX, 1);\n        }\n\n        int triangleIndex = 0;\n        for(int x = 0; x &lt; resolution; x++) {\n            int bottomLeft = x * 2;\n            int topLeft = bottomLeft + 1;\n            int bottomRight = bottomLeft + 2;\n            int topRight = bottomLeft + 3;\n\n            triangles&#091;triangleIndex++&#093; = bottomLeft; \n            triangles&#091;triangleIndex++&#093; = topLeft; \n            triangles&#091;triangleIndex++&#093; = topRight;\n            triangles&#091;triangleIndex++&#093; = bottomLeft; \n            triangles&#091;triangleIndex++&#093; = topRight; \n            triangles&#091;triangleIndex++&#093; = bottomRight;\n        }\n\n        mesh.vertices = vertices;\n        mesh.uv = uv;\n        mesh.triangles = triangles;\n        mesh.RecalculateNormals();\n        mesh.RecalculateBounds();\n\n        GetComponent&lt;MeshFilter>().mesh = mesh;\n    }\n\n    private void updateMeshFromSprings() {\n        float deltaX = 1 \/ (float)resolution;\n        float localX = 0;\n        for(int i = 0; i &lt; resolution; i++) {\n            int topIndex = i * 2 + 1;\n            vertices&#091;topIndex&#093;.y = SampleSplineAt(localX);\n            localX += deltaX;\n        }\n        mesh.vertices = vertices;\n        mesh.RecalculateBounds();\n        mesh.RecalculateNormals();\n    }\n\n    private void generateSprings() {\n        for(int i = 0; i &lt; springsCount; i++) {\n            springs.Add(new Spring());\n        }\n    }\n\n    private void resetSprings() {\n        for(int i = 0; i &lt; springs.Count; i++) {\n            springs&#091;i&#093;.velocity = 0f;\n            springs&#091;i&#093;.position = springs&#091;i&#093;.startPosition;\n        }\n        updateMeshFromSprings();\n    }\n\n    public void displace(float x, float force = 0.15f) {\n        if(springs.Count == 0) return;\n        isAwake = true;\n\n        Vector3 localPos = transform.InverseTransformPoint(new Vector3(x, 0, 0));\n        float scaledX = Mathf.Clamp01(localPos.x) * (springs.Count - 1);\n        float rightWeight = scaledX % 1;\n        float leftWeight = 1 - rightWeight;\n        int leftIndex = Mathf.FloorToInt(scaledX);\n        int rightIndex = leftIndex + 1;\n\n        if(leftIndex >= 0) {\n            springs&#091;leftIndex&#093;.ApplyForce(force * leftWeight);\n        }\n        if(rightIndex &lt;= springs.Count - 1) {\n            springs&#091;rightIndex&#093;.ApplyForce(force * rightWeight);\n        }\n    }\n\n    private void OnTriggerEnter2D(Collider2D collision) {\n        float force = defaultDisplacementForce;\n        Rigidbody2D rigidbody = collision.GetComponent&lt;Rigidbody2D>();\n        if(rigidbody != null) {\n            float t = Mathf.Clamp01(rigidbody.linearVelocity.magnitude \/ maxImpactVelocity);\n            force = -Mathf.Lerp(defaultDisplacementForce, maxDisplacementForce, t);\n        }\n        displace(collision.transform.position.x , force);\n    }\n\n    IEnumerator checkDisplacementEnd() {\n        const float CHECK_INTERVAL = 2.5f;\n        const float MIN_VELOCITY_THRESHOLD = 0.00025f;\n        yield return new WaitForSeconds(CHECK_INTERVAL);\n\n        float maxAbsoluteVelocity = 0;\n        for(int i = 0; i &lt; springs.Count; i++) {\n            if(Mathf.Abs(springs&#091;i&#093;.velocity) > maxAbsoluteVelocity) {\n                maxAbsoluteVelocity = Mathf.Abs(springs&#091;i&#093;.velocity);\n            }\n        }\n\n        if(maxAbsoluteVelocity &lt; MIN_VELOCITY_THRESHOLD) {\n            isAwake = false;\n            resetSprings();\n        }\n        StartCoroutine(checkDisplacementEnd());\n    }\n\n    private float SampleSplineAt(float localX) {\n        int segmentCount = springsCount - 1;\n        int i = Mathf.FloorToInt(localX * segmentCount);\n        i = Mathf.Clamp(i, 1, springsCount - 3);\n\n        float u = localX * segmentCount - i;\n\n        float p0 = springs&#091;i - 1&#093;.position;\n        float p1 = springs&#091;  i  &#093;.position;\n        float p2 = springs&#091;i + 1&#093;.position;\n        float p3 = springs&#091;i + 2&#093;.position;\n\n        return 0.5f * (u * (u * (u * (-p0 + 3f * p1 - 3f * p2 + p3) +\n                                (2f * p0 - 5f * p1 + 4f * p2 - p3)) +\n                           (-p0 + p2)) +\n                      (2f * p1));\n    }\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Collections<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Collections<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Generic<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">UnityEngine<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">UnityEngine<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Profiling<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">UnityEngine<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">SocialPlatforms<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">InteractiveWater<\/span><span style=\"color: #D4D4D4\"> : <\/span><span style=\"color: #4EC9B0\">MonoBehaviour<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Mesh<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">12<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">20<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">defaultDisplacementForce<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.5f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">maxDisplacementForce<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">5f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">maxImpactVelocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">100f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">wavePropagationPasses<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">static<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">elasticFactor<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.02f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">static<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">dampingFactor<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.99f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.02f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">List<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">Spring<\/span><span style=\"color: #D4D4D4\">&gt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">List<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">Spring<\/span><span style=\"color: #D4D4D4\">&gt;();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Spring<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">startPosition<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Update<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">positionDelta<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">startPosition<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">positionDelta<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">elasticFactor<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> *= <\/span><span style=\"color: #9CDCFE\">dampingFactor<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Start<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">generateMesh<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">GetComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">MeshFilter<\/span><span style=\"color: #D4D4D4\">&gt;().<\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">generateSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">StartCoroutine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">checkDisplacementEnd<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">FixedUpdate<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> || <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> || <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">Update<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">wavePropagationPasses<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #9CDCFE\">spreadFactor<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">leftDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">rightDeltas<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">generateMesh<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Mesh<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Mesh<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">&#091;(<\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Length<\/span><span style=\"color: #D4D4D4\">&#093;;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">index<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093; = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">normalizedX<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topLeft<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">bottomRight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topRight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">topLeft<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">topRight<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">bottomLeft<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">topRight<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">triangleIndex<\/span><span style=\"color: #D4D4D4\">++&#093; = <\/span><span style=\"color: #9CDCFE\">bottomRight<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">uv<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">triangles<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateNormals<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateBounds<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">GetComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">MeshFilter<\/span><span style=\"color: #D4D4D4\">&gt;().<\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">deltaX<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> \/ (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">resolution<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">topIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">topIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">y<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">SampleSplineAt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">deltaX<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">vertices<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateBounds<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">mesh<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">RecalculateNormals<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">generateSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Add<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Spring<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">resetSprings<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">startPosition<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">updateMeshFromSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">displace<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.15f<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> == <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">true<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">localPos<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">transform<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">InverseTransformPoint<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Vector3<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">scaledX<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Clamp01<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">localPos<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\">) * (<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rightWeight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">scaledX<\/span><span style=\"color: #D4D4D4\"> % <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">leftWeight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">rightWeight<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">FloorToInt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">scaledX<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rightIndex<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\"> &gt;= <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">leftIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">leftWeight<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rightIndex<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">rightIndex<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #DCDCAA\">ApplyForce<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">rightWeight<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">OnTriggerEnter2D<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">Collider2D<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">collision<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">defaultDisplacementForce<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #4EC9B0\">Rigidbody2D<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rigidbody<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">collision<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetComponent<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #4EC9B0\">Rigidbody2D<\/span><span style=\"color: #D4D4D4\">&gt;();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rigidbody<\/span><span style=\"color: #D4D4D4\"> != <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Clamp01<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rigidbody<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">linearVelocity<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">magnitude<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">maxImpactVelocity<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\"> = -<\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Lerp<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">defaultDisplacementForce<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">maxDisplacementForce<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">displace<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">collision<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">transform<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">x<\/span><span style=\"color: #D4D4D4\"> , <\/span><span style=\"color: #9CDCFE\">force<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4EC9B0\">IEnumerator<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">checkDisplacementEnd<\/span><span style=\"color: #D4D4D4\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">CHECK_INTERVAL<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2.5f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">MIN_VELOCITY_THRESHOLD<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.00025f<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">yield<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">WaitForSeconds<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">CHECK_INTERVAL<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Count<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Abs<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\">) &gt; <\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Abs<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">velocity<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">maxAbsoluteVelocity<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">MIN_VELOCITY_THRESHOLD<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">isAwake<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">resetSprings<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">StartCoroutine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">checkDisplacementEnd<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">SampleSplineAt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">segmentCount<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">FloorToInt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">segmentCount<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Mathf<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Clamp<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">springsCount<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">localX<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">segmentCount<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;  <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">  &#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p3<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">springs<\/span><span style=\"color: #D4D4D4\">&#091;<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">&#093;.<\/span><span style=\"color: #9CDCFE\">position<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">0.5f<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\"> * (-<\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">3f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">3f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">p3<\/span><span style=\"color: #D4D4D4\">) +<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                                (<\/span><span style=\"color: #B5CEA8\">2f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">5f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">4f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">p3<\/span><span style=\"color: #D4D4D4\">)) +<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                           (-<\/span><span style=\"color: #9CDCFE\">p0<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">p2<\/span><span style=\"color: #D4D4D4\">)) +<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                      (<\/span><span style=\"color: #B5CEA8\">2f<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">p1<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un effetto particolarmente interessante presente in molti videogiochi \u00e8 la deformazione degli specchi d&#8217;acqua in reazione al movimento del giocatore o alla caduta di oggetti. In questo articolo vedremo come realizzare un effetto di questo tipo in Unity, analizzando alcune soluzioni possibili. Le basi &#8211; un sistema a molle Nella vita reale il movimento dei [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":191,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[17,14,16],"class_list":["post-145","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-game-developement","tag-2d","tag-game-developement","tag-unity"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Come creare un effetto acqua dinamico in Unity 2D - Blog di Gabriele Scaggiante<\/title>\n<meta name=\"description\" content=\"In questo tutorial vedremo come creare un effetto di deformazione per simulare l&#039;interazione tra acqua e oggetti 2D\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Come creare un effetto acqua dinamico in Unity 2D - Blog di Gabriele Scaggiante\" \/>\n<meta property=\"og:description\" content=\"In questo tutorial vedremo come creare un effetto di deformazione per simulare l&#039;interazione tra acqua e oggetti 2D\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog di Gabriele Scaggiante\" \/>\n<meta property=\"article:published_time\" content=\"2025-08-18T09:20:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-08-18T09:20:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png\" \/>\n\t<meta property=\"og:image:width\" content=\"618\" \/>\n\t<meta property=\"og:image:height\" content=\"667\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"gabri.scaggiante\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"gabri.scaggiante\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/\",\"url\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/\",\"name\":\"Come creare un effetto acqua dinamico in Unity 2D - Blog di Gabriele Scaggiante\",\"isPartOf\":{\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png\",\"datePublished\":\"2025-08-18T09:20:21+00:00\",\"dateModified\":\"2025-08-18T09:20:23+00:00\",\"author\":{\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/#\/schema\/person\/5c76cf1169086f4afc9415344cff07a4\"},\"description\":\"In questo tutorial vedremo come creare un effetto di deformazione per simulare l'interazione tra acqua e oggetti 2D\",\"breadcrumb\":{\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#primaryimage\",\"url\":\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png\",\"contentUrl\":\"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png\",\"width\":618,\"height\":667},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/gabrielescaggiante.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Come creare un effetto acqua dinamico in Unity 2D\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/#website\",\"url\":\"https:\/\/gabrielescaggiante.com\/blog\/\",\"name\":\"Blog di Gabriele Scaggiante\",\"description\":\"Un blog su videogiochi, advergames e tecnologia\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/gabrielescaggiante.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/#\/schema\/person\/5c76cf1169086f4afc9415344cff07a4\",\"name\":\"gabri.scaggiante\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/gabrielescaggiante.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/929197b1cb90db5697fb0ed885973691732a43b5a31de2fc2436c37f1b9b7fa4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/929197b1cb90db5697fb0ed885973691732a43b5a31de2fc2436c37f1b9b7fa4?s=96&d=mm&r=g\",\"caption\":\"gabri.scaggiante\"},\"sameAs\":[\"https:\/\/gabrielescaggiante.com\/blog\"],\"url\":\"https:\/\/gabrielescaggiante.com\/blog\/author\/gabri-scaggiante\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Come creare un effetto acqua dinamico in Unity 2D - Blog di Gabriele Scaggiante","description":"In questo tutorial vedremo come creare un effetto di deformazione per simulare l'interazione tra acqua e oggetti 2D","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/","og_locale":"it_IT","og_type":"article","og_title":"Come creare un effetto acqua dinamico in Unity 2D - Blog di Gabriele Scaggiante","og_description":"In questo tutorial vedremo come creare un effetto di deformazione per simulare l'interazione tra acqua e oggetti 2D","og_url":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/","og_site_name":"Blog di Gabriele Scaggiante","article_published_time":"2025-08-18T09:20:21+00:00","article_modified_time":"2025-08-18T09:20:23+00:00","og_image":[{"width":618,"height":667,"url":"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png","type":"image\/png"}],"author":"gabri.scaggiante","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"gabri.scaggiante","Tempo di lettura stimato":"14 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/","url":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/","name":"Come creare un effetto acqua dinamico in Unity 2D - Blog di Gabriele Scaggiante","isPartOf":{"@id":"https:\/\/gabrielescaggiante.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#primaryimage"},"image":{"@id":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#primaryimage"},"thumbnailUrl":"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png","datePublished":"2025-08-18T09:20:21+00:00","dateModified":"2025-08-18T09:20:23+00:00","author":{"@id":"https:\/\/gabrielescaggiante.com\/blog\/#\/schema\/person\/5c76cf1169086f4afc9415344cff07a4"},"description":"In questo tutorial vedremo come creare un effetto di deformazione per simulare l'interazione tra acqua e oggetti 2D","breadcrumb":{"@id":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#primaryimage","url":"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png","contentUrl":"https:\/\/gabrielescaggiante.com\/blog\/wp-content\/uploads\/2025\/08\/Water.png","width":618,"height":667},{"@type":"BreadcrumbList","@id":"https:\/\/gabrielescaggiante.com\/blog\/come-creare-un-effetto-acqua-dinamico-in-unity-2d\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gabrielescaggiante.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Come creare un effetto acqua dinamico in Unity 2D"}]},{"@type":"WebSite","@id":"https:\/\/gabrielescaggiante.com\/blog\/#website","url":"https:\/\/gabrielescaggiante.com\/blog\/","name":"Blog di Gabriele Scaggiante","description":"Un blog su videogiochi, advergames e tecnologia","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gabrielescaggiante.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/gabrielescaggiante.com\/blog\/#\/schema\/person\/5c76cf1169086f4afc9415344cff07a4","name":"gabri.scaggiante","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/gabrielescaggiante.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/929197b1cb90db5697fb0ed885973691732a43b5a31de2fc2436c37f1b9b7fa4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/929197b1cb90db5697fb0ed885973691732a43b5a31de2fc2436c37f1b9b7fa4?s=96&d=mm&r=g","caption":"gabri.scaggiante"},"sameAs":["https:\/\/gabrielescaggiante.com\/blog"],"url":"https:\/\/gabrielescaggiante.com\/blog\/author\/gabri-scaggiante\/"}]}},"_links":{"self":[{"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/posts\/145","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/comments?post=145"}],"version-history":[{"count":38,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/posts\/145\/revisions"}],"predecessor-version":[{"id":193,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/posts\/145\/revisions\/193"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/media\/191"}],"wp:attachment":[{"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/media?parent=145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/categories?post=145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gabrielescaggiante.com\/blog\/wp-json\/wp\/v2\/tags?post=145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}