# Check out this question if you're bored

So I’ve been working on a project that creates a sea of cubes by layering different perlin noises. The cubes find their position on the perlin noise “texture” and their height is set to a value between -1 and +1. That value is determined by the color of the perlin noise. How would I apply this to a planes mesh; where the vertices of the mesh act like the cubes do? Here is my code ( which you’re welcome to try out ) Hopefully it’s not too long.

``````var cubeAmountX : int = 50;
var cubeAmountZ : int = 50;
var seed : int = 0.0;
var seed2 : int = 0.0;
var cube : GameObject;
var colorSetsScale : boolean;
var heightSetsScale : boolean;
var sizeDivider : float = 2.0;
var animateColor : boolean;
var roundHeightToInt : boolean;
var noiseScale : float = 6.5;
var noiseScale2 : float = 6.5;
var cubeHeight : float = 3;
var cubeHeight2 : float = 3;
var animateSpeed : float = 0.5;
var animateSpeed2 : float = 1.0;
private var finalHeight : float;

function Start ()
{
for (var spawnPositionX = 0; spawnPositionX < cubeAmountX; spawnPositionX++)
{
for (var spawnPositionZ = 0; spawnPositionZ < cubeAmountZ; spawnPositionZ++)
{
var makeCube = Instantiate(cube, Vector3(spawnPositionX,0,spawnPositionZ), Quaternion.identity);
makeCube.transform.parent = this.transform;
}
}
for (var child : Transform in this.transform)
{
if (noiseScale <= 0.001)
{
noiseScale = 0.0011;
}
var height = Mathf.PerlinNoise(child.transform.position.x/noiseScale + (seed * 10), child.transform.position.z/noiseScale + (seed *  10));
var height2 = Mathf.PerlinNoise(child.transform.position.x/noiseScale2 + (seed2 * -10), child.transform.position.z/noiseScale2 + (seed2 *  -10));
height *= cubeHeight;
height2 *= cubeHeight2;
finalHeight = height + height2;
if (animateColor)
{
child.renderer.material.color = Color(finalHeight,finalHeight,finalHeight,finalHeight);
}
if (colorSetsScale)
{
if (sizeDivider <= 0.0)
{
sizeDivider = 0.001;
}
child.transform.localScale = Vector3 (finalHeight,finalHeight,finalHeight);
}
}
}

function Update ()
{
for (var child : Transform in this.transform)
{
var height = Mathf.PerlinNoise(child.transform.position.x/noiseScale, child.transform.position.z/noiseScale);
var height2 = Mathf.PerlinNoise(child.transform.position.x/noiseScale2 + (seed2 * -10), child.transform.position.z/noiseScale2 + (seed2 *  -10));
height *= cubeHeight;
height2 *= cubeHeight2;
var finalHeight = height + height2;
if (animateColor)
{
child.renderer.material.color = Color(finalHeight,finalHeight,finalHeight,finalHeight);
}
}
for (var child : Transform in this.transform)
{
height = Mathf.PerlinNoise(Time.time * animateSpeed + (child.transform.position.x/noiseScale) + (seed * 10), Time.time * animateSpeed + (child.transform.position.z/noiseScale) + (seed * 10));
height2 = Mathf.PerlinNoise(Time.time * animateSpeed2 + child.transform.position.x/noiseScale2 + (seed2 * -10),Time.time * animateSpeed2 + child.transform.position.z/noiseScale2 + (seed2 *  -10));
height *= cubeHeight;
height2 *= cubeHeight2;
finalHeight = height + height2;
if (!roundHeightToInt)
{
child.transform.position.y = finalHeight + transform.position.y;
}
else if (roundHeightToInt)
{
child.transform.position.y = Mathf.RoundToInt(finalHeight * cubeHeight + transform.position.y);
}
if (animateColor)
{
child.renderer.material.color = Color(finalHeight,finalHeight,finalHeight,finalHeight);
}
if (colorSetsScale)
{
if (sizeDivider <= 0.0)
{
sizeDivider = 1;
}
child.transform.localScale = Vector3 (finalHeight,finalHeight,finalHeight);
heightSetsScale = false;
}
if (heightSetsScale)
{
if (sizeDivider <= 0.0)
{
sizeDivider = 1;
}
var cubeHeight : float = child.transform.localPosition.y;
child.transform.localScale = Vector3 (cubeHeight/sizeDivider, cubeHeight/sizeDivider, cubeHeight/sizeDivider);
colorSetsScale = false;
}
if (!heightSetsScale && !colorSetsScale)
{
child.transform.localScale = Vector3 (1,1,1);
}
}
}
``````

example 2… rather than updating the cube locations can’t you update the vertex positions?

Thats what I’d like to do, but I can’t figure it out. Here’s my progress on the vertex based displacement

``````var seed : int = 0.0;
var roundHeightToInt : boolean;
var noiseScale : float = 6.5;
var waveHeight : int = 3;
var animateSpeed : float = 1.0;

private var mesh : Mesh;
private var vertices : Vector3[];
private var perlinHeight : float;

function Start ()
{
mesh = this.gameObject.GetComponent(MeshFilter).mesh;
}

function Update ()
{
mesh = this.gameObject.GetComponent(MeshFilter).mesh;
vertices = mesh.vertices;
for (var vert = 0; vert < vertices.Length; vert++)
{
var worldVert : Vector3 = vertices[vert];
perlinHeight = Mathf.PerlinNoise (worldVert.x / noiseScale, worldVert.z / noiseScale);
worldVert.y = perlinHeight * waveHeight;
}
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
``````

Are you just talking about a HeightMap?

Unity doesn’t appear to use a texture for its terrain heightmaps (I never played with their terrain system… just never made a game needing it). Which is weird, because most engines I’ve played with just used textures directly.

Anyways, there are scripts out there that exist to map a texture to the existing terrain heightmap container.

I’

m trying to update in realtime my own mesh. Not a terrain object. Is that what you’re suggesting? to use a terrain object?

You can modify the terrain data at runtime.

I’d like to do it to a my own mesh though. Could I do your heightmap idea on something that isn’t a unity terrain object? I’f not, I need to figure out how to move the vertices in the way I move cubes in the video at the top of the thread

Is there a reason why?

Is this for purely academic reasons because you want to learn?

Or is there something wrong with the Terrain class in Unity that it doesn’t support something you need?

If you want to use your own mesh, well it’s not that hard.

You have a mesh (imported one, or procedurally generated).
The number of verts on the mesh should be to the detail level you desire (procedurally generated meshes make this easier to change at runtime).
You loop over the verts of the mesh, and set their position based on your heightmap texture. Just like the cubes.

Honestly that’s what the Terrain class in Unity does as well. It has a mesh, and it adjusts the height of the vertices based on the ‘TerrainData’ object associated with it. It’s just the TerrainData isn’t a texture, and instead is its own data structure.

That’s basically what I’ve been trying. Here’s my script. You can see where I’m stuck…As in it doesnt work

``````var seed : int = 0.0;
var roundHeightToInt : boolean;
var noiseScale : float = 6.5;
var waveHeight : int = 3;
var animateSpeed : float = 1.0;

private var mesh : Mesh;
private var vertices : Vector3[];
private var perlinHeight : float;

function Start ()
{
mesh = this.gameObject.GetComponent(MeshFilter).mesh;
}

function Update ()
{
mesh = this.gameObject.GetComponent(MeshFilter).mesh;
vertices = mesh.vertices;
for (var vert = 0; vert < vertices.Length; vert++)
{
var worldVert : Vector3 = vertices[vert];
perlinHeight = Mathf.PerlinNoise (worldVert.x / noiseScale, worldVert.z / noiseScale);
worldVert.y = perlinHeight * waveHeight;
}
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
``````

Vector3’s are structs. That means they are passed by value, not by reference.

You edit the vector3, which is the value of the vert, but you don’t set it back to the vert array.

After line 25 in that code put:
vertices[vert] = worldVert;

This is the same thing as position on the transform.

You can’t say:

``````var v = transform.position;
v.x += 1.0f;
``````

The change doesn’t take. You have to say:

``````var v = transform.position;
v.x += 1.0f;
transform.position = v;
``````

I’d also like to point out that the Terrain class also supports smoothing and other extra features.

Ok, done. But it still doesn’t move the vertices

``````var seed : int = 0.0;
var roundHeightToInt : boolean;
var noiseScale : float = 6.5;
var waveHeight : int = 3;
var animateSpeed : float = 1.0;

private var mesh : Mesh;
private var vertices : Vector3[];
private var perlinHeight : float;

function Start ()
{
mesh = this.gameObject.GetComponent(MeshFilter).mesh;
}

function Update ()
{
mesh = this.gameObject.GetComponent(MeshFilter).mesh;
vertices = mesh.vertices;
for (var vert = 0; vert < vertices.Length; vert++)
{
var worldVert : Vector3 = vertices[vert];
perlinHeight = Mathf.PerlinNoise (worldVert.x / noiseScale, worldVert.z / noiseScale);
worldVert.y = perlinHeight * waveHeight;
vertices[vert] = worldVert;
}
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
``````

So I can manipulate my object’s mesh through the terrain class without making it a terrain object?

What?

No. That is not what I said in any way shape or form.

oh, sorry. I know I’m overcomplicating this. Could you explain what I need to fix in my code? Btw, if you haven’t noticed, I’m a pretty amateur programmer.

Also as to your code still not working, Mesh.vertices is also a copy of the vertices.

That means you have to set the vertices back to the mesh as well.

Before you say mesh.RecalculateBounds();

You should put:
mesh.vertices = vertices;

There’s other things wrong with your code.

1. You have your mesh declared as a class level variable. That’s fine. And you get the component upon ‘Start’. That’s good. But then you continue to re-get the component on every update. Why? You already got it. Why waste the time getting it again?

2. You have your vertices and perlinHeight variables as a class level variable as well. But they’re only used temporarily in the scope of the ‘Update’ method. Why? Define those variables INSIDE ‘Update’ where they’re needed. A class level variable should be for variables that persist for the life of the object. Not the life of a method call.

3. your naming conventions can be confusing. It’s common for a for loop to use the variable ‘i’ (short for index). You use ‘vert’, but that value isn’t the vert, it’s the index of the vert. This causes you to have to call the actual vert ‘worldVert’… note also that ‘worldVert’ is defined to the method, and not to the class (see 2).

ok cool, now the mesh moves, although its weird…also the collider doesn’t update. What should I call to update it?