I use the following code to generate a Cube as a single mesh. My purpose is to generate a sphere from it by normalizing as I have shown in the commented line (I just have to do that to all those statements in the following lines). The problem here is that the mesh changes from a cube to a flat plane as I keep increasing the resolution (parameter given as public int resolution).
(This code was inspired by this video https://youtu.be/QN39W020LqU . But I am using the technique in my own way as given by the following code, so that I can generate a single mesh instead of a combination of 6 meshes, this is required for my work)
[code=CSharp]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sc_Planet : MonoBehaviour
{
[Range(2, 512)]
public int resolution = 2;
[Range(2, 256)]
public int radius = 10;
MeshFilter meshFilter;
void OnValidate()
{
Initialize();
}
void Initialize()
{
if (meshFilter == null)
{
GameObject meshObj = new GameObject("mesh_Planet");
meshObj.transform.parent = transform;
meshObj.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));
meshFilter = meshObj.AddComponent<MeshFilter>();
meshFilter.sharedMesh = new Mesh();
}
int xmax = resolution + 1;
int ymax = resolution + 1;
float dx = 1.0f / resolution;
float dy = 1.0f / resolution;
Vector3[] vertsTop = new Vector3[xmax * ymax];
Vector3[] vertsRight = new Vector3[xmax * ymax];
Vector3[] vertsFront = new Vector3[xmax * ymax];
Vector3[] vertsBottom = new Vector3[xmax * ymax];
Vector3[] vertsLeft = new Vector3[xmax * ymax];
Vector3[] vertsBack = new Vector3[xmax * ymax];
for (int y = 0; y < ymax; y++)
{
for (int x = 0; x < xmax; x++)
{
float px = dx * x - 0.5f;
float py = dy * y - 0.5f;
int t = x + y * xmax;
//vertsTop[t] = new Vector3(py, 0.5f, px).normalized * radius;
vertsTop[t] = new Vector3(py, 0.5f, px);
vertsRight[t] = new Vector3(px, py, 0.5f);
vertsFront[t] = new Vector3(0.5f, px, py);
vertsBottom[t] = new Vector3(px, -0.5f, py);
vertsLeft[t] = new Vector3(py, px, -0.5f);
vertsBack[t] = new Vector3(-0.5f, py, px);
}
}
List<int> trianglesList = new List<int>();
for (int y = 0; y < ymax - 1; ++y)
{
for (int x = 0; x < xmax; ++x)
{
if (x % xmax != xmax - 1)
{
int f = x + y * xmax;
trianglesList.Add(f);
trianglesList.Add(f + 1);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f + xmax);
}
}
}
List<Vector3> verts = new List<Vector3>();
Dictionary<Vector3, int> vdict = new Dictionary<Vector3, int>();
List<int> triangles = new List<int>();
int nextIndex = 0;
void addFace(Vector3 [] in_verts, List<int> in_triangles)
{
for(int i = 0; i < in_verts.Length; ++i)
{
if (!vdict.ContainsKey(in_verts[i]))
{
vdict.Add(in_verts[i], nextIndex);
verts.Add(in_verts[i]);
++nextIndex;
}
}
for(int i = 0; i < in_triangles.Count; ++i)
{
triangles.Add(vdict[in_verts[in_triangles[i]]]);
}
}
addFace(vertsTop, trianglesList);
addFace(vertsRight, trianglesList);
addFace(vertsFront, trianglesList);
addFace(vertsBottom, trianglesList);
addFace(vertsLeft, trianglesList);
addFace(vertsBack, trianglesList);
var mesh = meshFilter.sharedMesh;
mesh.Clear();
mesh.vertices = verts.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
}
}
[/code]
This code works in Blender (I used python to script it on Blender and it works very well for any resolution).
The only problem is that when I use this in Unity, the meshes become weird as I have shown in the images I have attached below.
At Resolution = 96 :
At Resolution = 122 :
At Resolution = 182 :
At Resolution = 344:
Why is this happening?
How should I correct it?
(I have also posted this in unity forums: Why cube mesh becomes a plane when in high resolution?)
Ok I found the answer. This is exceeding the limit of vertices on unity api for 16-bit based meshes. I had to change it to a 32-bit indexed mesh to correct it.
Details are in this docuemntaiton page : https://docs.unity3d.com/ScriptReference/Rendering.IndexFormat.html?_ga=2.9556401.501737799.1635227368-67181881.1629608252
I just had to add the code :
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
That was it.
Related
i'm a newbie and i am following a tutorial on procedural landmass generation. However, my plane does not look right. It has a lot of seams/cracks. Is there someone who can point me in the right direction?
Below is my MeshGenerator scripts:
public static class MeshGenerator
{
public static MeshData GenerateTerrainMesh(float[,] heightMap, float heightMultiplier, AnimationCurve heightCurve)
{
int width = heightMap.GetLength(0);
int height = heightMap.GetLength(1);
float topLeftX = (width - 1) / -2f;
float topLeftZ = (height - 1) / 2f;
MeshData meshData = new MeshData(width, height);
int vertexIndex = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
meshData.vertices[vertexIndex] = new Vector3(topLeftX + x, heightCurve.Evaluate(heightMap[x,y]) * heightMultiplier, topLeftZ - y);
meshData.uvs[vertexIndex] = new Vector2(x / (float)width, y / (float)height);
if (x < width - 1 && y < height - 1)
{
meshData.AddTriangle(vertexIndex, vertexIndex + width + 1, vertexIndex + width);
meshData.AddTriangle(vertexIndex, + width + 1, vertexIndex + 1);
}
vertexIndex++;
}
}
return meshData;
}
}
public class MeshData
{
public Vector3[] vertices;
public int[] triangles;
public Vector2[] uvs;
int triangleIndex;
public MeshData(int meshWidth, int meshHeight)
{
vertices = new Vector3[meshWidth * meshHeight];
uvs = new Vector2[meshWidth * meshHeight];
triangles = new int[(meshWidth-1) * (meshHeight-1)*6];
}
public void AddTriangle(int a, int b, int c)
{
triangles[triangleIndex] = a;
triangles[triangleIndex+1] = b;
triangles[triangleIndex+2] = c;
triangleIndex += 3;
}
public Mesh CreateMesh()
{
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
return mesh;
}
}
You triangle indices are wrong, this is rather obvious since you have a bunch of triangle-shaped holes. Notably
meshData.AddTriangle(vertexIndex, + width + 1, vertexIndex + 1);
the second vertex of the second triangle is a constant value, and that is most likely incorrect
You should not need to keep a running total of vertexIndex, you should be perfectly able to compute the triangle indices from the grid indices:
var v1 = y * (width+1) + x; // You should have one more column of vertices than you have grid cells
var v2 = v2 + 1; // the vertex one column to the right
var v3 = v1 + width+1; // the vertex one row down
var v4 = v3 + 1;
meshData.AddTriangle(v1, v2, v4);
meshData.AddTriangle(v1, v4, v3);
You may need to invert the vertex order to ensure the normals are oriented correctly.
I am relatively new to Terrain Generation in Unity, and am currently stuck in one place. I have followed Brackey's tutorial on terrain generation, and in that tutorial, he uses something like this:
float y = Mathf.PerlinNoise(x, z) * 2f;
To manipulate the height of the terrain. I also followed Sebastian Lague's tutorial on this. This is where I am stuck.
I want to use Sebastian Lague's Noise.cs file that he created (can be found on his GitHub) to manipulate the terrain height.
The reason is because this noise generator, rather than Mathf.PerlinNoise(), gives you a much better control over the texture it outputs. The problem is, Noise.cs will return a 2D float array, while Mathf.PerlinNoise() returns a 1D float value. Is there a way for Noise.cs to return a float value, just like Mathf's function?
Noise.cs:
using UnityEngine;
using System.Collections;
public static class Noise {
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset) {
float[,] noiseMap = new float[mapWidth,mapHeight];
System.Random prng = new System.Random (seed);
Vector2[] octaveOffsets = new Vector2[octaves];
for (int i = 0; i < octaves; i++) {
float offsetX = prng.Next (-100000, 100000) + offset.x;
float offsetY = prng.Next (-100000, 100000) + offset.y;
octaveOffsets [i] = new Vector2 (offsetX, offsetY);
}
if (scale <= 0) {
scale = 0.0001f;
}
float maxNoiseHeight = float.MinValue;
float minNoiseHeight = float.MaxValue;
float halfWidth = mapWidth / 2f;
float halfHeight = mapHeight / 2f;
for (int y = 0; y < mapHeight; y++) {
for (int x = 0; x < mapWidth; x++) {
float amplitude = 1;
float frequency = 1;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++) {
float sampleX = (x-halfWidth) / scale * frequency + octaveOffsets[i].x;
float sampleY = (y-halfHeight) / scale * frequency + octaveOffsets[i].y;
float perlinValue = Mathf.PerlinNoise (sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistance;
frequency *= lacunarity;
}
if (noiseHeight > maxNoiseHeight) {
maxNoiseHeight = noiseHeight;
} else if (noiseHeight < minNoiseHeight) {
minNoiseHeight = noiseHeight;
}
noiseMap [x, y] = noiseHeight;
}
}
for (int y = 0; y < mapHeight; y++) {
for (int x = 0; x < mapWidth; x++) {
noiseMap [x, y] = Mathf.InverseLerp (minNoiseHeight, maxNoiseHeight, noiseMap [x, y]);
}
}
return noiseMap;
}
}
MeshGenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class MeshGenerator : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
public int xSize = 20;
public int zSize = 20;
int mapWidth;
int mapHeight;
int seed;
float scale;
int octaves;
float persistance;
float lacunarity;
Vector2 offset;
// Start is called before the first frame update
void Start()
{
// Initialize everything
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
void CreateShape()
{
// Creating the grid of vertices
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
// Setting vertex positions
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
//float y = Mathf.PerlinNoise(x * .3f, z * .3f) * 2f;
float y = Noise.GenerateNoiseMap(mapWidth, mapHeight, seed, scale, octaves, persistance, lacunarity, offset);
vertices[i] = new Vector3(x, y, z);
i++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
}
void UpdateMesh()
{
// Clear mesh data, reset with above vars and recalculate normals
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
private void OnDrawGizmos()
{
if (vertices == null) return;
Gizmos.color = Color.red;
// Draw Vertex Gizmos
for (int i = 0; i < vertices.Length; i++)
{
Gizmos.DrawSphere(vertices[i], .1f);
}
}
}
I've figured it out, I would've had to put vertices[i] = new Vector3(x, y[x, z], z); Now I've already tried this, but I suppose visual studio bugged and did not save it properly. Anyways, yes, I just needed to use x/y to pick out my float.
Now I have an octahedron sphere and I woud like to add noise to it, but I can' t do it because I dont know to much of this,
I think I need to modify the vertex pos but i don't know how.
Here is the script that generate the vertices, If you need More, only Ask (;
Vector3[] vertices = new Vector3[(resolution + 1) * (resolution + 1) * 4 - (resolution * 2 - 1) * 3];
int v = 0, vBottom = 0, t = 0;
for (int i = 0; i < 4; i++)
{
vertices[v++] = Vector3.down;
}
for (int i = 1; i <= resolution; i++)
{
float progress = (float)i / resolution;
Vector3 from, to;
vertices[v++] = to = Vector3.Lerp(Vector3.down, Vector3.up, progress);
for (int d = 0; d < 4; d++)
{
from = to;
to = Vector3.Lerp(Vector3.down, directions[d], progress);
t = CreateLowerStrip(i, v, vBottom, t, triangles);
v = CreateVertexLine(from, to, i, v, vertices);
vBottom += i > 1 ? (i - 1) : 1;
}
vBottom = v - 1 - i * 4;
}
Depending on how exactly your noise should look like the simplest I can imagine would be to simply iterate through the vertices and slightly shift them around by random direction vectors with a random magnitude up to a certain maximum like e.g.
void Randomize(Vector3[] vertices, float maxDistance)
{
for(var i = 0; i< vertices.Length; i++)
{
// Generates a random vactor pointing in any possible direction
var randomDirection = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
// Generate a random magnitude between 0 and given maxDistance
var randomMagnitude = Random.Range(0, maxDistance);
// Move the current vert the randomMagnitude along the randomDirection
vertices[i] += randomDirection * randomMagnitude;
}
}
Or alternatively you could only move on Vectors between the current vert position and the center (assuming Vector3.zero for now)
void RandomizeFromCenter(Vector3[] vertices, float maxDistance)
{
var center = Vector3.zero;
for(var i = 0; i< vertices.Length; i++)
{
var direction = (vertices[i] - center).normalized;
// Generate a random magnitude between -maxDistance and maxDistance
var randomMagnitude = Random.Range(-maxDistance, maxDistance);
// Move the current vert the randomMagnitude along the randomDirection
vertices[i] += direction * randomMagnitude;
}
}
I currently have a "CreateMesh" script that can be put as a component of an object with a Mesh Renderer, and a Mesh Filter, and a 2D mesh is created with a polygon collider in the dimensions of the mesh given a "MeshType" variable is set to either "tri" or "box" (for a triangle and rectangle mesh respectively.) I want to also add the ability to create a circular mesh however from some research I've realised this isn't as simple as I first thought. However I'm yet to find anything that's helping.
This is the code I have for the box and triangle meshes:
public float width = 5f;
public float height = 5f;
public string meshType;
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
// Update is called once per frame
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
}
void TriangleMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[3]
{
new Vector3(0,0,0), new Vector3(width, 0, 0), new Vector3(0, height, 0)
};
//Triangles
int[] tri = new int[3];
tri[0] = 0;
tri[1] = 2;
tri[2] = 1;
//normals
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[3];
uv[0] = new Vector2(0, 0);
uv[0] = new Vector2(1, 0);
uv[0] = new Vector2(0, 1);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[3]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
void BoxMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[4]
{
new Vector3(0,0,0), new Vector3(0, height, 0), new Vector3(width, height, 0), new Vector3(width, 0, 0)
};
//Triangles
int[] tri = new int[6];
tri[0] = 0;
tri[1] = 1;
tri[2] = 3;
tri[3] = 1;
tri[4] = 2;
tri[5] = 3;
//normals
Vector3[] normals = new Vector3[4];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
normals[3] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(0, 1);
uv[2] = new Vector2(1, 1);
uv[3] = new Vector2(1, 0);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[4]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
So essentially I want a function that I could call in the update method that would simply create a circular mesh. E.g:
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
if (meshType == "circle")
{
CircleMesh(radius);
}
}
The solution I've managed to find involves creating a regular polygon of n sides with a large value of n. I have a function called PolyMesh which creates a regular polygon mesh with n sides and a given radius.
Generating the vertices
For each vertex of a regular polygon with n sides the coordinates relative to the centre of the polygon are given by x = r*i*sin(θ) and y = r*i*cos(θ) so therefore x = r*i*sin(2π/2) and y = r*i*cos(2π/2). Where i iterates from 0 to n-1. We can therefore have a list which has vertices assigned to it and then is converted to an array afterwards:
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
Generating the triangles
A given regular polygon of n sides can be split into n-2 triangles from the same point. So we can generate each triangle as follows:
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
Generating the Normals
Since this is a 2d object we can have every normal as -Vector3.forward like so:
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
Generating the collider
We could just use a circle collider with the same radius but in order to make this function work for a polygon of a smaller value of n we must use a PolygonCollider2D. Since the vertices are already in order in the vertices array we can simply use them as the paths for our PolygonCollider2D.
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
The complete code should look like this:
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
void PolyMesh(float radius, int n)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
//initialise
mesh.vertices = verticies;
mesh.triangles = triangles;
mesh.normals = normals;
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
}
An introduction to meshes
I have less than 50 reputation and so I can't just comment on #Tom Ryan's answer.
With that said, beware that his solution doesn't include the UVs for the mesh. Here is that addition:
//uvs
Vector2[] uvs = new Vector2[vertices.Length];
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x / (radius*2) + 0.5f, vertices[i].y / (radius*2) + 0.5f);
}
// Later...
mesh.uv = uvs;
I'm following this tutorial set: https://www.youtube.com/watch?v=owBt9SNKXCI&index=6&list=PLbghT7MmckI4qGA0Wm_TZS8LVrqS47I9R to dynamically build a tile map layout. It works to a point, but it generates a very strange layout with 128 x 128 sized tiles.
Clearly that strange partitioning shouldn't be happening, but I cannot seem to track down what's going on to cause it. Here is my version of the code, which is mostly identical to quill18creates's version sans a few small differences:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class TileMap : MonoBehaviour {
public int size_x = 100;
public int size_z = 50;
public float tileSize = 1.0f;
public Texture2D terrainTiles;
int tileResolution = 128;
// Use this for initialization
void Start () {
BuildMesh();
}
Color[][] ChopUpTiles() {
int numTilesPerRow = terrainTiles.width / tileResolution;
int numRows = terrainTiles.height / tileResolution;
Color[][] tiles = new Color[numTilesPerRow*numRows][];
for(int y=0; y < numRows; y++) {
for(int x=0; x < numTilesPerRow; x++) {
tiles[y * numTilesPerRow + x] = terrainTiles.GetPixels( x*tileResolution , y*tileResolution, tileResolution, tileResolution );
}
}
return tiles;
}
void BuildTexture() {
//DTileMap map = new DTileMap(size_x, size_z);
int texWidth = size_x * tileResolution;
int texHeight = size_z * tileResolution;
Texture2D texture = new Texture2D(texWidth, texHeight);
Color[][] tiles = ChopUpTiles();
for(int y=0; y < size_z; y++) {
for(int x=0; x < size_x; x++) {
Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];
texture.SetPixels(x * tileResolution, y * tileResolution, tileResolution, tileResolution, p);
}
}
//texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
texture.Apply();
MeshRenderer mesh_renderer = GetComponent<MeshRenderer>();
mesh_renderer.sharedMaterials[0].mainTexture = texture;
}
public void BuildMesh() {
int numTiles = size_x * size_z;
int numTris = numTiles * 2;
int vsize_x = size_x + 1;
int vsize_z = size_z + 1;
int numVerts = vsize_x * vsize_z;
// Generate the mesh data
Vector3[] vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
int[] triangles = new int[ numTris * 3 ];
int x, z;
for(z=0; z < vsize_z; z++) {
for(x=0; x < vsize_x; x++) {
vertices[ z * vsize_x + x ] = new Vector3( x*tileSize, 0, -z*tileSize );
normals[ z * vsize_x + x ] = Vector3.up;
uv[ (z * vsize_x) + x ] = new Vector2( (float)x / size_x, (float)z / size_z );
}
}
Debug.Log ("Done Verts!");
for(z=0; z < size_z; z++) {
for(x=0; x < size_x; x++) {
int squareIndex = z * size_x + x;
int triOffset = squareIndex * 6;
triangles[triOffset + 0] = z * vsize_x + x + 0;
triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 3] = z * vsize_x + x + 0;
triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 4] = z * vsize_x + x + 1;
}
}
// Create a new Mesh and populate with the data
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
// Assign our mesh to our filter/renderer/collider
MeshFilter mesh_filter = GetComponent<MeshFilter>();
MeshCollider mesh_collider = GetComponent<MeshCollider>();
mesh_filter.mesh = mesh;
mesh_collider.sharedMesh = mesh;
BuildTexture();
}
}
I don't get exactly what part is wrong in the image but I think it is that the same tiles are lumping together.
I tried your code and it works well for me. But I guess the following part could be causing the lumping together problem for you:
Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];
Instead you should do:
Color[] p = tiles[Random.Range(0, 5)];
Because, the other way, Random is generating float numbers and maybe they are near the each other that rounding them to the integer gives same tile. Give it a try.
Also just reminding, make sure the width and the height of your texture is divisible by 128.
Well, it was definitely a size issue, but there was also an issue with positioning. Tiles have to start at the bottom-left corner for the coordinate system to find them.