Update mesh for waves (solved)

I am trying to make a nice ocean for a little project yet I cannot for the life of me figure out how to update the mesh. I have tried some suggestions on other threads but nothing worked so I figured I would ask directly. The script is in C# and goes like so.


     using UnityEngine;
     using System.Collections;
     public class Wavegen : MonoBehaviour
     {
         float scale = 1f;
         float speed = 1.0f;
         float noiseStrength = 1f;
         float noiseWalk = 1f;
     
         private Vector3[] baseHeight;
      
         void Update () {
         Mesh mesh = GetComponent<MeshFilter>().mesh;
         MeshCollider collider = GetComponent<MeshCollider>();
         if (baseHeight == null)
             baseHeight = mesh.vertices;
   
         Vector3[] vertices = new Vector3[baseHeight.Length];
         for (int i=0;i<vertices.Length;i++)
         {
             Vector3 vertex = baseHeight*;*
 <em>vertex.y += Mathf.Sin(Time.time * speed+ baseHeight<em>.x + baseHeight<em>.y + baseHeight_.z) * scale;_</em></em></em>
 <em><em><em><em>vertex.y += Mathf.PerlinNoise(baseHeight<em>.x + noiseWalk, baseHeight_.y + Mathf.Sin(Time.time * 0.1f)    ) * noiseStrength;_</em></em></em></em></em>
 <em><em><em><em><em>_vertices *= vertex;*_</em></em></em></em></em>
 <em><em><em><em><em>_*}*_</em></em></em></em></em>
 <em><em><em><em><em>_*mesh.vertices = vertices;*_</em></em></em></em></em>
 <em><em><em><em><em>_*mesh.RecalculateNormals();		*_</em></em></em></em></em>
 <em><em><em><em><em>_*collider.sharedMesh = null;*_</em></em></em></em></em>
 <em><em><em><em><em>_*collider.sharedMesh = mesh;*_</em></em></em></em></em>
 <em><em><em><em><em>_*}*_</em></em></em></em></em>
 <em><em><em><em><em>_*}*_</em></em></em></em></em>
<em><em><em><em><em>_*```*_</em></em></em></em></em>
<em><em><em><em><em>_*Is there a way to add the mesh to this and also do I have to delete the mesh that appears when you create the object? (PS sorry bout the formatting errors I don't know what is making it do that) Edit: updated the script with a few lines but they seem to do nothing.*_</em></em></em></em></em>

So what happens when you run the code (it seems to be alright)? Does your gameObject has a mesh attached to it?

It has a mesh but it is just just the default mesh aka all objects fall through and land on a flat surface in the center of it. It is just the default Plane mesh.

I cannot comment on your code without more study, but to get a plane with vertices to apply this to do, use the [CreatePlane editor script in the Unity Wiki.][1] [1]: http://wiki.unity3d.com/index.php?title=CreatePlane

Okay lemme do some test with that.

Um for some reason I am getting the fallowing error with that script "mesh does not contain definition of vertices". Error CS1061

2 Answers

2

For me your script works without problems. I created a Plane object throught GameObject/Create Other/Plane, attached your script to that object and pressed Play. I can see the wave motion.

Edit: if you want not just a visual change, but also change in the collider, you need to add those lines to the end of your Update method.

MeshCollider collider = GetComponent<MeshCollider>();
// this =null is necessary, because it forces collision mesh to be recalculated,
// if you don't do thing then Unity thinks that it's the same mesh and doesn't recalculate it
collider.sharedMesh = null;
collider.sharedMesh = mesh;

Note that you need to attach Rigidbody component to other objects if you want them to be affected by physics and change in this collider.

Note that updating Mesh data in runtime is considered a slow operation. Updating collider in runtime is very slow. It might be ok for PC if your mesh is not too complex.

The motion is fine yet the thing I want is for the mesh to update so it effects objects.

I added the code and the ridged body object but it still seems to act like the mesh is flat. Can you show me where exactly I plug these into?

I tried your code - it works here. There must be something wrong with your setup. Can you try setting it up again? P.S.: you can format code in comments (and you should because it's not readable).

Oh do I feel like a dummy. I just realized that I made a copy of the script and that I wasn't using the right one now it works fine. Thanks for your help. Also I tried to format the code in the comments but it just wouldn't work for me. Next step is to figure out how to have some kinda buoyancy but that is for another thread.

You're welcome. You should mark the answer as correct if it solves your problem. Welcome to Unity answers!

First, if you have a non-flat plane mesh, you need to find the surface vertices, like this:

List<Vector3> waveVertices = new List<Vector3>();
     for(int i = 0; i < GetComponent<MeshFilter>().sharedMesh.vertices.Length - 1; i++) {
          Vector3 vertex = GetComponent<MeshFilter>().sharedMesh.vertices*;*
  • Vector3 nextVertex = GetComponent().sharedMesh.vertices[i + 1];*
  • if(vertex.y > nextVertex.y) {*
  •     waveVertices.Add(vertex);*
    
  • }*
    }
    Then, you basically just take the vertex postions and move them upwards or downwards, and assign them back to the mesh’s vertices array. Add some fancy Math.PI or whatever computing for bell-shaped wave motions if you want, as you did in your example.

float min = 0f;
float max = 1f;
float waveSpeed = 5f;
int waveDir = 0;

void Update() {
if(waveVertices.Count > 0) {

Mesh mesh = GetComponent().mesh;
Vector3[] vertices = mesh.vertices;

lvl = vertices[waveVertices[0]].y;

if(waveDir == 1 && vertices[waveVertices[0]].y >= max) {
waveDir = 0;
}
if(waveDir == 0 && vertices[waveVertices[0]].y <= min) {
waveDir = 1;
}

foreach(int i in waveVertices) {
if(waveDir == 0) {
vertices -= Vector3.up * Time.deltaTime * waveSpeed;
* }*
* else {*
vertices += Vector3.up * Time.deltaTime * waveSpeed;
* }*
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
* }*
}

This is gonna sound very noobish but where do I put the top part in the script? I am still very new to Unity.

There are so many things wrong with this answer: - It doesn't compile. - When you fix all compile errors it doesn't work. - Doing GetComponent().sharedMesh.vertices* is a slow operation and you do it 3 times in a loop. It's slow because it searches for component, then it makes a copy of all vertices (from C++ to C# space), before accessing one of them. And you do it 3 times every loop.*

You are right, thanks for your feedback.