
Ultra-Optimized Mesh Generation in Unity Using Jobs and Burst
July 1, 2026
Creating Dynamic Water with Vertex Shaders in Unity
July 1, 2026Static water is boring. In modern games, players expect water to react to their presence, ripple when touched, and flow naturally.
One of the most effective ways to create interactive water is through Mesh Deformation. By programmatically moving the vertices of a water plane, we can simulate waves and ripples in real-time.
The Core Concept: Math Behind the Waves
To create a wave effect, we use trigonometric functions, specifically the Sine wave. The basic formula for a wave height at a given point is:
$y = A \cdot \sin(k \cdot x + \omega \cdot t)$
Where:
- A is the Amplitude (Height of the wave)
- k is the Wave Number (Frequency/Width)
- t is Time
Setting Up the Water Mesh
To deform water, you need a mesh with a high density of vertices. A simple quad won’t work because it only has 4 vertices. You need a Plane or a custom grid mesh with many subdivisions.
C# Implementation: Simple Sine Waves
This script modifies the vertices of a mesh to create a simple waving surface.
using UnityEngine;
public class SimpleWater : MonoBehaviour
{
public float power = 0.1f;
public float scale = 1.0f;
public float timeScale = 1.0f;
private Mesh mesh;
private Vector3[] baseVertices;
void Start()
{
mesh = GetComponent<MeshFilter>().mesh;
baseVertices = mesh.vertices;
}
void Update()
{
Vector3[] vertices = new Vector3[baseVertices.Length];
for (int i = 0; i < vertices.Length; i++)
{
Vector3 vertex = baseVertices[i];
// Calculate a wave based on X and Z position
vertex.y += Mathf.Sin(Time.time * timeScale + (baseVertices[i].x * scale) + (baseVertices[i].z * scale)) * power;
vertices[i] = vertex;
}
mesh.vertices = vertices;
mesh.RecalculateNormals(); // Important for correct lighting!
}
}
Adding Interactivity: Ripple Effects
To make the water react to objects (like a player jumping in), we need to track “Impact Points” and calculate a ripple that spreads from that center.
public void CreateRipple(Vector3 impactPoint, float intensity)
{
// In a professional system, you would pass this point to a shader
// or a Job System to deform the mesh vertices locally.
}
Optimization: Moving to Jobs + Burst
Updating thousands of vertices every frame on the Main Thread is a recipe for a laggy game. For “Ultra-Optimized” water, you should use the Unity Job System.
- Parallel Jobs: Calculate vertex offsets for each vertex on separate CPU cores.
- Burst Compiler: Speed up the math calculations (Sin, Cos) significantly.
- NativeArray: Use memory-efficient arrays to store vertex data.
Performance Comparison
| Method | CPU Usage | Best For |
|---|---|---|
| Simple Update Loop | High | Small Ponds / Stylized water |
| Vertex Shader | Low (GPU) | Visual waves without physics |
| Jobs + Burst | Medium (CPU Parallel) | Interactive water with physics/buoyancy |
Conclusion
Dynamic mesh-based water adds a layer of polish that makes your game feel high-quality. While it requires a bit of math, the result of seeing your player create ripples in a procedural lake is worth the effort.









