I didn’t know I was going to join prior to the event, so I had to rewrite my 2D water code.
Feels fair to still share it with everyone though.
It could use some improvements, I’m moving the verts on the cpu since I can’t do shaders haha.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using AssemblyCSharp;
//[ExecuteInEditMode()]
using AssemblyCSharpEditor;
/* Written by Martino Wullems, aka omgnoseat*/
public class MWater2D : MonoBehaviour {
public int width = 10;
public int height = 1;
public Mesh mesh = null;
private float textureScale;
private List<Vector3> vertices;
private List<int> triangles;
private List<Vector2> newUV;
private List<WaveVert> waveVerts;
public float segmentWidth = 1;
int segmentCount;
private MeshRenderer renderer;
float dx = 0;
public float waveRepeat = 10f;
public float scrollSpeed = 0.2f;
public float amplitude = 0.02f;
float theta = 0;
public float springToBase = 0.02f;
public float forceMultiplier = 1f;
public float spring = 0.05f;
public float floatValue = 1f;
// Use this for initialization
LiteTimer timer = new LiteTimer(0.1f );
public void Start()
{
timer.looping = true;
timer.onElapsed += HandleonElapsed;
timer.start( );
Build();
}
public void Build () {
mesh = GetComponent<MeshFilter> ().mesh;
vertices = new List<Vector3>();
triangles = new List<int>();
newUV = new List<Vector2>( );
waveVerts = new List<WaveVert>() ;
mesh = GetComponent<MeshFilter>().mesh;
renderer = GetComponent<MeshRenderer>();
//textureScale = renderer.sharedMaterial.GetTexture(0).width / width;
//textureScale = 1f / textureScale;
//print (“textureScale : ” + textureScale );
float tx = 0;
segmentCount = Mathf.FloorToInt( width / segmentWidth);
Debug.Log (“segmentCount: ” + segmentCount );
for(tx = 0; tx < segmentCount; tx++)
{
Vector3 tl = new Vector3 ( tx * segmentWidth , 0 , 0 );
Vector3 tr = new Vector3 ( (tx * segmentWidth ) + segmentWidth , 0 , 0 );
Vector3 br = new Vector3 ( (tx * segmentWidth ) + segmentWidth , -height, 0 );
Vector3 bl = new Vector3 ( (tx * segmentWidth ) , -height , 0 );
vertices.Add( tl );
vertices.Add( tr );
vertices.Add( br );
vertices.Add( bl );
waveVerts.Add( new WaveVert( tl, tl, springToBase ) );
waveVerts.Add( new WaveVert( tr, tr, springToBase ) );
waveVerts.Add( new WaveVert( br, br, springToBase ) );
waveVerts.Add( new WaveVert( bl, bl, springToBase ) );
newUV.Add(new Vector2 (0, 1));
newUV.Add(new Vector2 (1, 1));
newUV.Add(new Vector2 (1, 0));
newUV.Add(new Vector2 (0, 0));
}
int squarecount = 0;
for(tx = 0; tx < segmentCount; tx++)
{
//if( tiles[ty][tx] < 0 ) continue;
triangles.Add( (squarecount * 4 ) + 0 );
triangles.Add( (squarecount * 4 ) + 1 );
triangles.Add( (squarecount * 4 ) + 3 );
triangles.Add( (squarecount * 4 ) + 1 );
triangles.Add( (squarecount * 4 ) + 2 );
triangles.Add( (squarecount * 4 ) + 3 );
squarecount++;
}
refreshMesh();
if( GetComponent<BoxCollider2D>() == null ) gameObject.AddComponent<BoxCollider2D>();
dx = ( ( Mathf.PI * 2 ) / waveRepeat) * segmentWidth;
}
void HandleonElapsed ()
{
updateForce();
generateWave();
refreshMesh();
//set vertices to waveverts
for(int i = 0; i < vertices.Count; i += 4)
{
//update verts
waveVerts[i].Update();
if(i >= 4) waveVerts[i-3].Update();
vertices[i] = waveVerts[i].pos;
if(i >= 4 )vertices[i-3] = waveVerts[i].pos;
//print (“i ” + i);
}
//last one
waveVerts[ vertices.Count – 3 ].Update();
vertices[vertices.Count -3] = waveVerts[ vertices.Count – 3 ].pos;
//print (“vertices.count: ” + vertices.Count);
//print (“———–“);
}
void updateForce()
{
for(int i = 0; i < vertices.Count; i += 4)
{
int vID = i / 4;
WaveVert p = waveVerts[i];
if( vID > 2 )
{
WaveVert prevP = waveVerts[i – 4];
float dy = prevP.pos.y – p.pos.y;
//dy*= 0.3f;
p.velocity.y += spring * dy * Time.deltaTime;
}
if( vID < segmentCount – 2)
{
WaveVert nextP = waveVerts[i + 4];
float dy = nextP.pos.y – p.pos.y;
//dy *= 0.3f;
p.velocity.y += spring * dy * Time.deltaTime;
}
}
}
void generateWave()
{
theta += scrollSpeed * Time.deltaTime;
float x = theta;
float y = transform.position.y – ( Mathf.Sin( x ) * amplitude ); //sin x is y positions upon % normalized circle pretty much;
for(int i = 0; i < vertices.Count; i += 4)
{
//check wave Y
y = 0 – ( Mathf.Sin( x ) * amplitude );
//if( i > 0 ) vertices[i – 3] = new Vector3( vertices[i-3].x, y, 0 ); //not -=
//vertices[i] = new Vector3(vertices[i].x, y, 0 );
waveVerts[i].anchor = new Vector3( vertices[i].x, y, 0 );
if( i >= 4 )waveVerts[i-3].anchor = new Vector3( vertices[i].x, y, 0 );
x += dx ;
}
//last one
y = 0 – ( Mathf.Sin( x ) * amplitude );
waveVerts[ vertices.Count – 3 ].anchor = new Vector3( vertices[ vertices.Count -3].x, y, 0 );
}
void applyForce( int pointID, float forceY)
{
int realID = pointID * 4;;
forceY *= forceMultiplier;
int xForce = Mathf.FloorToInt( forceY ) / 2;
if(xForce < 0 ) xForce = 0;
if(xForce > segmentCount) xForce = segmentCount;
waveVerts[ realID ].velocity += new Vector3(0, forceY, 0 );
if( realID > 0 ) waveVerts[ realID – 3 ].velocity += new Vector3(0, forceY, 0 );
}
public void refreshMesh()
{
mesh.Clear ();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.uv = newUV.ToArray();
mesh.Optimize ();
mesh.RecalculateNormals ();
//GetComponent<MeshCollider>().sharedMesh = mesh;
}
// Update is called once per frame
public void Update () {
HandleonElapsed();
//timer.Update();
if( Input.GetKey( KeyCode.P ) )
{
applyForce( 15, 0.3f );
}
}
public void OnTriggerEnter2D( Collider2D collider )
{
if(collider.rigidbody2D == null ) return;
waterInteraction( collider, collider.rigidbody2D.velocity.y / 50 );
}
public void OnTriggerExit2D( Collider2D collider )
{
if(collider.rigidbody2D == null ) return;
waterInteraction( collider, collider.rigidbody2D.velocity.y / 30 );
}
public void OnTriggerStay2D( Collider2D collider )
{
if(collider.rigidbody2D == null ) return;
waterInteraction( collider, collider.rigidbody2D.velocity.x / 500 );
collider.rigidbody2D.velocity += new Vector2(0, (floatValue ) * Time.fixedDeltaTime );
}
private void waterInteraction( Collider2D collider, float power )
{
float enterPos = Mathf.Abs( transform.position.x – collider.transform.position.x );
float size = (width * segmentWidth);
int point = Mathf.FloorToInt( ( enterPos / size ) * width);
if( point == 0 || point == segmentCount ) return;
applyForce( point , power );
}
}