{"author_name":"omgnoseat","cat":"LD #29","comments":[{"author_name":"","time":"April 26, 2014 11:25 am","epoch":1398529500,"text":"Aha!  I needed exactly this.  Thanks!","spam":"N"}],"epoch":1398514860,"likes":1,"metadata":{"p_key":"31946","p_author":"omgnoseat","p_authorkey":"14763","p_urlkey":"67445","p_title":"unity3d 2D water","p_cat":"LD #29","p_event":"LD29","p_time":"1398514860","p_likes":"1","p_comments":"1","p_status":"UPD5","us_key":"14763","us_name":"omgnoseat","us_username":"omgnoseat","event_start":"1398384000","event_key":"22","event_name":"LD29"},"text":"<blockquote><p>I didn&#8217;t know I was going to join prior to the event, so I had to rewrite my 2D water code.<br \/>\n Feels fair to still share it with everyone though.<br \/>\n It could use some improvements, I&#8217;m moving the verts on the cpu since I can&#8217;t do shaders haha.<\/p>\n <p>using UnityEngine;<br \/>\n using System.Collections;<br \/>\n using System.Collections.Generic;<br \/>\n using AssemblyCSharp;<br \/>\n \/\/[ExecuteInEditMode()]<br \/>\n using AssemblyCSharpEditor;<\/p>\n <p>\/* Written by Martino Wullems, aka omgnoseat*\/<br \/>\n public class MWater2D : MonoBehaviour {<\/p>\n <p>public int width = 10;<br \/>\n public int height = 1;<\/p>\n <p>public Mesh mesh = null;<br \/>\n private float textureScale;<\/p>\n <p>private List&lt;Vector3&gt; vertices;<br \/>\n private List&lt;int&gt; triangles;<br \/>\n private List&lt;Vector2&gt; newUV;<\/p>\n <p>private List&lt;WaveVert&gt; waveVerts;<\/p>\n <p>public float segmentWidth = 1;<br \/>\n int segmentCount;<\/p>\n <p>private MeshRenderer renderer;<\/p>\n <p>float dx = 0;<br \/>\n public float waveRepeat = 10f;<br \/>\n public float scrollSpeed = 0.2f;<br \/>\n public float amplitude = 0.02f;<br \/>\n float theta = 0;<\/p>\n <p>public float springToBase = 0.02f;<\/p>\n <p>public float forceMultiplier = 1f;<\/p>\n <p>public float spring = 0.05f;<br \/>\n public float floatValue = 1f;<br \/>\n \/\/ Use this for initialization<br \/>\n LiteTimer timer = new LiteTimer(0.1f );<\/p>\n <p>public void Start()<br \/>\n {<br \/>\n timer.looping = true;<br \/>\n timer.onElapsed += HandleonElapsed;<br \/>\n timer.start( );<\/p>\n <p>Build();<br \/>\n }<\/p>\n <p>public void Build () {<\/p>\n <p>mesh = GetComponent&lt;MeshFilter&gt; ().mesh;<\/p>\n <p>vertices = new List&lt;Vector3&gt;();<br \/>\n triangles = new List&lt;int&gt;();<br \/>\n newUV = new List&lt;Vector2&gt;( );<br \/>\n waveVerts = new List&lt;WaveVert&gt;() ;<\/p>\n <p>mesh = GetComponent&lt;MeshFilter&gt;().mesh;<\/p>\n <p>renderer = GetComponent&lt;MeshRenderer&gt;();<br \/>\n \/\/textureScale = renderer.sharedMaterial.GetTexture(0).width \/ width;<br \/>\n \/\/textureScale = 1f \/ textureScale;<br \/>\n \/\/print (&#8220;textureScale : &#8221; + textureScale );<br \/>\n float tx = 0;<br \/>\n segmentCount = Mathf.FloorToInt( width \/ segmentWidth);<\/p>\n <p>Debug.Log (&#8220;segmentCount: &#8221; + segmentCount );<\/p>\n <p>for(tx = 0; tx &lt; segmentCount; tx++)<br \/>\n {<br \/>\n Vector3 tl = new Vector3 ( tx * segmentWidth , 0 , 0 );<br \/>\n Vector3 tr = new Vector3 ( (tx * segmentWidth ) + segmentWidth , 0 , 0 );<br \/>\n Vector3 br = new Vector3 ( (tx * segmentWidth ) + segmentWidth , -height, 0 );<br \/>\n Vector3 bl = new Vector3 ( (tx * segmentWidth ) , -height , 0 );<\/p>\n <p>vertices.Add( tl );<br \/>\n vertices.Add( tr );<br \/>\n vertices.Add( br );<br \/>\n vertices.Add( bl );<\/p>\n <p>waveVerts.Add( new WaveVert( tl, tl, springToBase ) );<br \/>\n waveVerts.Add( new WaveVert( tr, tr, springToBase ) );<br \/>\n waveVerts.Add( new WaveVert( br, br, springToBase ) );<br \/>\n waveVerts.Add( new WaveVert( bl, bl, springToBase ) );<\/p>\n <p>newUV.Add(new Vector2 (0, 1));<br \/>\n newUV.Add(new Vector2 (1, 1));<br \/>\n newUV.Add(new Vector2 (1, 0));<br \/>\n newUV.Add(new Vector2 (0, 0));<\/p>\n <p>}<\/p>\n <p>int squarecount = 0;<br \/>\n for(tx = 0; tx &lt; segmentCount; tx++)<br \/>\n {<br \/>\n \/\/if( tiles[ty][tx] &lt; 0 ) continue;<\/p>\n <p>triangles.Add( (squarecount * 4 ) + 0 );<br \/>\n triangles.Add( (squarecount * 4 ) + 1 );<br \/>\n triangles.Add( (squarecount * 4 ) + 3 );<\/p>\n <p>triangles.Add( (squarecount * 4 ) + 1 );<br \/>\n triangles.Add( (squarecount * 4 ) + 2 );<br \/>\n triangles.Add( (squarecount * 4 ) + 3 );<\/p>\n <p>squarecount++;<br \/>\n }<\/p>\n <p>refreshMesh();<\/p>\n <p>if( GetComponent&lt;BoxCollider2D&gt;() == null ) gameObject.AddComponent&lt;BoxCollider2D&gt;();<br \/>\n dx = ( ( Mathf.PI * 2 ) \/ waveRepeat) * segmentWidth;<br \/>\n }<\/p>\n <p>void HandleonElapsed ()<br \/>\n {<br \/>\n updateForce();<br \/>\n generateWave();<br \/>\n refreshMesh();<\/p>\n <p>\/\/set vertices to waveverts<br \/>\n for(int i = 0; i &lt; vertices.Count; i += 4)<br \/>\n {<br \/>\n \/\/update verts<br \/>\n waveVerts[i].Update();<br \/>\n if(i &gt;= 4) waveVerts[i-3].Update();<\/p>\n <p>vertices[i] = waveVerts[i].pos;<br \/>\n if(i &gt;= 4 )vertices[i-3] = waveVerts[i].pos;<\/p>\n <p>\/\/print (&#8220;i &#8221; + i);<br \/>\n }<\/p>\n <p>\/\/last one<br \/>\n waveVerts[ vertices.Count &#8211; 3 ].Update();<br \/>\n vertices[vertices.Count -3] = waveVerts[ vertices.Count &#8211; 3 ].pos;<br \/>\n \/\/print (&#8220;vertices.count: &#8221; + vertices.Count);<br \/>\n \/\/print (&#8220;&#8212;&#8212;&#8212;&#8211;&#8220;);<br \/>\n }<\/p>\n <p>void updateForce()<br \/>\n {<br \/>\n for(int i = 0; i &lt; vertices.Count; i += 4)<br \/>\n {<br \/>\n int vID = i \/ 4;<br \/>\n WaveVert p = waveVerts[i];<\/p>\n <p>if( vID &gt; 2 )<br \/>\n {<br \/>\n WaveVert prevP = waveVerts[i &#8211; 4];<br \/>\n float dy = prevP.pos.y &#8211; p.pos.y;<br \/>\n \/\/dy*= 0.3f;<\/p>\n <p>p.velocity.y += spring * dy * Time.deltaTime;<br \/>\n }<\/p>\n <p>if( vID &lt; segmentCount &#8211; 2)<br \/>\n {<br \/>\n WaveVert nextP = waveVerts[i + 4];<br \/>\n float dy = nextP.pos.y &#8211; p.pos.y;<br \/>\n \/\/dy *= 0.3f;<\/p>\n <p>p.velocity.y += spring * dy * Time.deltaTime;<br \/>\n }<\/p>\n <p>}<br \/>\n }<br \/>\n void generateWave()<br \/>\n {<br \/>\n theta += scrollSpeed * Time.deltaTime;<br \/>\n float x = theta;<br \/>\n float y = transform.position.y &#8211; ( Mathf.Sin( x ) * amplitude ); \/\/sin x is y positions upon % normalized circle pretty much;<\/p>\n <p>for(int i = 0; i &lt; vertices.Count; i += 4)<br \/>\n {<br \/>\n \/\/check wave Y<br \/>\n y = 0 &#8211; ( Mathf.Sin( x ) * amplitude );<\/p>\n <p>\/\/if( i &gt; 0 ) vertices[i &#8211; 3] = new Vector3( vertices[i-3].x, y, 0 ); \/\/not -=<br \/>\n \/\/vertices[i] = new Vector3(vertices[i].x, y, 0 );<\/p>\n <p>waveVerts[i].anchor = new Vector3( vertices[i].x, y, 0 );<br \/>\n if( i &gt;= 4 )waveVerts[i-3].anchor = new Vector3( vertices[i].x, y, 0 );<\/p>\n <p>x += dx ;<br \/>\n }<\/p>\n <p>\/\/last one<br \/>\n y = 0 &#8211; ( Mathf.Sin( x ) * amplitude );<br \/>\n waveVerts[ vertices.Count &#8211; 3 ].anchor = new Vector3( vertices[ vertices.Count -3].x, y, 0 );<br \/>\n }<\/p>\n <p>void applyForce( int pointID, float forceY)<br \/>\n {<br \/>\n int realID = pointID * 4;;<\/p>\n <p>forceY *= forceMultiplier;<\/p>\n <p>int xForce = Mathf.FloorToInt( forceY ) \/ 2;<br \/>\n if(xForce &lt; 0 ) xForce = 0;<br \/>\n if(xForce &gt; segmentCount) xForce = segmentCount;<\/p>\n <p>waveVerts[ realID ].velocity += new Vector3(0, forceY, 0 );<br \/>\n if( realID &gt; 0 ) waveVerts[ realID &#8211; 3 ].velocity += new Vector3(0, forceY, 0 );<\/p>\n <p>}<\/p>\n <p>public void refreshMesh()<br \/>\n {<br \/>\n mesh.Clear ();<br \/>\n mesh.vertices = vertices.ToArray();<br \/>\n mesh.triangles = triangles.ToArray();<br \/>\n mesh.uv = newUV.ToArray();<br \/>\n mesh.Optimize ();<br \/>\n mesh.RecalculateNormals ();<\/p>\n <p>\/\/GetComponent&lt;MeshCollider&gt;().sharedMesh = mesh;<br \/>\n }<\/p>\n <p>\/\/ Update is called once per frame<br \/>\n public void Update () {<\/p>\n <p>HandleonElapsed();<br \/>\n \/\/timer.Update();<\/p>\n <p>if( Input.GetKey( KeyCode.P ) )<br \/>\n {<br \/>\n applyForce( 15, 0.3f );<br \/>\n }<br \/>\n }<\/p>\n <p>public void OnTriggerEnter2D( Collider2D collider )<br \/>\n {<br \/>\n if(collider.rigidbody2D == null ) return;<br \/>\n waterInteraction( collider, collider.rigidbody2D.velocity.y \/ 50 );<br \/>\n }<\/p>\n <p>public void OnTriggerExit2D( Collider2D collider )<br \/>\n {<br \/>\n if(collider.rigidbody2D == null ) return;<br \/>\n waterInteraction( collider, collider.rigidbody2D.velocity.y \/ 30 );<br \/>\n }<\/p>\n <p>public void OnTriggerStay2D( Collider2D collider )<br \/>\n {<br \/>\n if(collider.rigidbody2D == null ) return;<br \/>\n waterInteraction( collider, collider.rigidbody2D.velocity.x \/ 500 );<\/p>\n <p>collider.rigidbody2D.velocity += new Vector2(0, (floatValue ) * Time.fixedDeltaTime );<br \/>\n }<\/p>\n <p>private void waterInteraction( Collider2D collider, float power )<br \/>\n {<br \/>\n float enterPos = Mathf.Abs( transform.position.x &#8211; collider.transform.position.x );<br \/>\n float size = (width * segmentWidth);<\/p>\n <p>int point = Mathf.FloorToInt( ( enterPos \/ size ) * width);<br \/>\n if( point == 0 || point == segmentCount ) return;<\/p>\n <p>applyForce( point , power );<br \/>\n }<\/p>\n <p>}<\/p><\/blockquote>","time":"April 26th, 2014 7:21 am","title":"unity3d 2D water"}