I`m helping my friend to make his study project, and for it we need a 3d frustum, with and ability to set the diameter of the upper round surface and the bottom one in runtime, could you please advice how can it be done? I am thinking of getting the array of edgex/vertices, that are connected with the center one on the top and on the bottom, and change their coords, maybe there is an easier way to do so?
For creating a cone frustum with dynamic sizes you can use the script from http://wiki.unity3d.com/index.php/ProceduralPrimitives#C.23_-_Cone
Since you create the mesh once at beginning later you know exactly which vertices are the ones for the top and bottom plane so you can easily change them dynamically afterwards.
Somewhat like e.g.
public class DynamicConicalFrustum : MonoBehaviour
{
[SerializeField] private MeshFilter meshFilter;
[SerializeField] private MeshCollider meshCollider;
[Header("Settings")]
[SerializeField] private float _height = 1f;
[SerializeField] private float _bottomRadius = .25f;
[SerializeField] private float _topRadius = .05f;
[SerializeField] private int nbSides = 18;
private Mesh mesh;
const float _2pi = Mathf.PI * 2f;
private Vector3[] vertices;
private void Awake()
{
if (!meshFilter && !TryGetComponent<MeshFilter>(out meshFilter))
{
meshFilter = gameObject.AddComponent<MeshFilter>();
}
if(!GetComponent<MeshRenderer>())
{
var mr = gameObject.AddComponent<MeshRenderer>();
mr.material = new Material(Shader.Find("Standard"));
}
if (!meshCollider)
meshCollider = GetComponent<MeshCollider>();
mesh = meshFilter.mesh;
if (!mesh)
{
mesh = new Mesh();
}
meshFilter.mesh = mesh;
if (meshCollider)
meshCollider.sharedMesh = mesh;
RecreateFrustum(_height,_bottomRadius,_topRadius);
}
#if UNITY_EDITOR
private void OnValidate()
{
if (Application.isPlaying)
{
Awake();
}
}
#endif
public void RecreateFrustum(float height, float bottomRadius, float topRadius)
{
mesh.Clear();
int nbVerticesCap = nbSides + 1;
#region Vertices
// bottom + top + sides
vertices = new Vector3[nbVerticesCap + nbVerticesCap + nbSides * 2 + 2];
// Bottom cap
vertices[0] = new Vector3(0f, 0f, 0f);
for(var idx = 1; idx <= nbSides; idx++)
{
float rad = (float)(idx ) / nbSides * _2pi;
vertices[idx ] = new Vector3(Mathf.Cos(rad) * bottomRadius, 0f, Mathf.Sin(rad) * bottomRadius);
}
// Top cap
vertices[nbSides + 1] = new Vector3(0f, height, 0f);
for(var idx = nbSides + 2; idx <= nbSides * 2 + 1; idx++)
{
float rad = (float)(idx - nbSides - 1) / nbSides * _2pi;
vertices[idx] = new Vector3(Mathf.Cos(rad) * topRadius, height, Mathf.Sin(rad) * topRadius);
}
// Sides
int v = 0;
for(var idx = nbSides * 2 + 2; idx <= vertices.Length - 4; idx+=2)
{
float rad = (float)v / nbSides * _2pi;
vertices[idx] = new Vector3(Mathf.Cos(rad) * topRadius, height, Mathf.Sin(rad) * topRadius);
vertices[idx + 1] = new Vector3(Mathf.Cos(rad) * bottomRadius, 0, Mathf.Sin(rad) * bottomRadius);
v++;
}
vertices[vertices.Length - 2] = vertices[nbSides * 2 + 2];
vertices[vertices.Length - 1] = vertices[nbSides * 2 + 3];
#endregion
#region Triangles
int nbTriangles = nbSides + nbSides + nbSides * 2;
int[] triangles = new int[nbTriangles * 3 + 3];
// Bottom cap
int tri = 0;
int i = 0;
while (tri < nbSides - 1)
{
triangles[i] = 0;
triangles[i + 1] = tri + 1;
triangles[i + 2] = tri + 2;
tri++;
i += 3;
}
triangles[i] = 0;
triangles[i + 1] = tri + 1;
triangles[i + 2] = 1;
tri++;
i += 3;
// Top cap
//tri++;
while (tri < nbSides * 2)
{
triangles[i] = tri + 2;
triangles[i + 1] = tri + 1;
triangles[i + 2] = nbVerticesCap;
tri++;
i += 3;
}
triangles[i] = nbVerticesCap + 1;
triangles[i + 1] = tri + 1;
triangles[i + 2] = nbVerticesCap;
tri++;
i += 3;
tri++;
// Sides
while (tri <= nbTriangles)
{
triangles[i] = tri + 2;
triangles[i + 1] = tri + 1;
triangles[i + 2] = tri + 0;
tri++;
i += 3;
triangles[i] = tri + 1;
triangles[i + 1] = tri + 2;
triangles[i + 2] = tri + 0;
tri++;
i += 3;
}
#endregion
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
mesh.RecalculateTangents();
mesh.Optimize();
}
}
It's of course not really optimized currently but I hope you can keep going from there ;)
E.g. that method creates extra vertices for the sides .. one could re-use the ones from the top and bottom cap since they match positions anyway.
Further you could of course also just update the according vertices when the height and radius change, you wouldn't need to recreate the entire mesh every time since the triangles stay the same, only the vertices change positions.
Related
This question already has answers here:
List of object is null even after calling constructor [duplicate]
(4 answers)
Field 'xxx' is never assigned to, and will always have its default value null
(2 answers)
Closed 1 year ago.
(edited for more context)
When I pass my Amplifiers and Frequencies float arrays into my functions corresponding arguments it is passed as null in the function.
Here is a code sample:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshCollider))]
public class MeshGenerator: MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
float[] Amplifiers;
float[] Frequencies;
public int xSize = 20;
public int zSize = 20;
public int Layers = 1;
public float Seed = .3f;
float rNum = 1f;
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
float[] Frequencies = new float[Layers];
float[] Amplifiers = new float[Layers];
for (int i = 0; i < Layers; i++)
{
Amplifiers[i] = Random.Range(1.5f, 2.5f);
Frequencies[i] = Random.Range(.25f, .4f);
}
}
private void Update()
{
rNum = Random.Range(1f, 2.5f);
}
float TerrainPerlin(int layers, float[] ampArray, float[] freqArray, int x, int y, float seed)
{
if (ampArray == null || freqArray == null)
{
Debug.Log("Amplifier Array or Frequency Array is null");
return Mathf.PerlinNoise(x * .3f, y * .3f) * 2f;
}
if (ampArray.Length != layers || freqArray.Length != layers)
{
Debug.Log("Amplifier Array or Frequency Array and the amount of Layers aren't equal");
return Mathf.PerlinNoise(x * .3f, y * .3f) * 2f;
}
float result = 0;
for (int i = 0; i < layers; i++)
{
result += Mathf.PerlinNoise(x * (freqArray[i] + seed), (y * freqArray[i]) + seed) * ampArray[i];
}
return result;
}
void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
//float y = Mathf.PerlinNoise(x * seed, z * (seed * 1.5f)) * (amplifier * rNum);
float y = 0f;
y = TerrainPerlin(Layers, Amplifiers, Frequencies, x, z, Seed);
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()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
MeshCollider meshCollider = gameObject.GetComponent<MeshCollider>();
meshCollider.sharedMesh = mesh;
mesh.Optimize();
}
void OnDrawGizmos()
{
if (vertices == null)
return;
for (int i = 0; i < vertices.Length; i++)
{
Gizmos.DrawSphere(vertices[i], .1f);
}
}
}
Before i added the null handling and console messages this was the error i was getting
NullReferenceException: Object reference not set to an instance of an object
MeshGenerator.TerrainPerlin (System.Int32 layers, System.Single[] ampArray, System.Single[] freqArray, System.Int32 x, System.Int32 y, System.Single seed) [at Assets/Scripts/MeshGenerator.cs:51]
Context on what I am trying to do:
I'm trying to make procedural terrain in unity I have been able to use a single layer of Perlin Noise to do that however I want to use multiple octaves of Perlin Noise to generate a terrain mesh so I can have better looking terrain that has mountains and hills, and more detail. However when I try to use my function with randomly generated arrays it just returns null values to the arguments.
this is the part of the code that generate a mesh, if you want more information ask.
So in the scene I cannot see it, I tried to enter play mode but nothing, if I go in the inspector I can see: 4 verts, 2 tris, the right amount of tris and verts.
public void ConstructMesh()
{
Vector3[] vertices = new Vector3[(resolution + 2) * (resolution + 2)];
int[] triangles = new int[(resolution + 1) * (resolution + 1) * 6];
int triIndex = 0;
for (int y = 0; y < resolution; y++)
{
for (int x = 0; x < resolution; x++)
{
int i = x + y * resolution;
Vector2 percent = new Vector2(x, y) / (resolution - 1);
Vector3 pointOnUnitCode = localUp + (percent.x - .5f) * 2 * axisA + (percent.y - .5f) * 2 * axisB;
vertices[i] = pointOnUnitCode;
triangles[triIndex] = i;
triangles[triIndex + 1] = i + resolution + 1;
triangles[triIndex + 2] = i + resolution;
triangles[triIndex + 3] = i;
triangles[triIndex + 4] = i + 1;
triangles[triIndex + 5] = i + resolution + 1;
triIndex += 6;
}
}
planet.Clear();
planet.vertices = vertices;
planet.triangles = triangles;
planet.RecalculateNormals();
}
You need a MeshRenderer and MeshFilter in the GameObject to be able to render your mesh.
Supposing your method ConstructMesh is a MonoBehaviour and it's attached to the same object you want to display the mesh, you can do the following:
GetComponent<MeshFilter>().mesh = planet;
This question already has an answer here:
How to use meshes with more than 64k vertices in Unity 2018.1
(1 answer)
Closed 2 years ago.
I'm trying to upload point cloud in unity C#.
Because there is no element that draws point directly, I create a cube for each point of point cloud.
So, For n points in point cloud, 8n vertices (because it is cube), 12 meshes exist for my code.
A mesh = 3 index --> a cube : 12 meshes --> 3*12 index (var name : triangles)
point XYZ are saved in PointList : List < Vector3 >
each points has color in ColorList : List< Vector3 >
I checked all vertices and meshes have correct values, and drawing points (cubes) works well.
However there is a problem. The original point cloud has 1412765 points(image1). And the number of vertices is same to it. But! If I try to draw all of them, maybe some of them are not drawn. (image2. I guess around 10000 cubes is the maximum.)
What's the problem?
float resolution = 2.5f;
int pointSize = PointList.Count;
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
Vector3[] vertices;
vertices = new Vector3[pointSize * 8];
for (int i = 0; i < pointSize; i++)
{
float x = PointList[i].x;
float y = PointList[i].y;
float z = PointList[i].z;
vertices[i * 8 + 0] = new Vector3(x - resolution, y - resolution, z - resolution);
vertices[i * 8 + 1] = new Vector3(x + resolution, y - resolution, z - resolution);
vertices[i * 8 + 2] = new Vector3(x + resolution, y + resolution, z - resolution);
vertices[i * 8 + 3] = new Vector3(x - resolution, y + resolution, z - resolution);
vertices[i * 8 + 4] = new Vector3(x - resolution, y + resolution, z + resolution);
vertices[i * 8 + 5] = new Vector3(x + resolution, y + resolution, z + resolution);
vertices[i * 8 + 6] = new Vector3(x + resolution, y - resolution, z + resolution);
vertices[i * 8 + 7] = new Vector3(x - resolution, y - resolution, z + resolution);
}
mesh.vertices = vertices;
int[] triangles;
triangles = new int[pointSize * 12 * 3];
triangles[0] = 0;
triangles[1] = 2;
triangles[2] = 1;
triangles[3] = 0;
triangles[4] = 3;
triangles[5] = 2;
triangles[6] = 2;
triangles[7] = 3;
triangles[8] = 4;
triangles[9] = 2;
triangles[10] = 4;
triangles[11] = 5;
triangles[12] = 1;
triangles[13] = 2;
triangles[14] = 5;
triangles[15] = 1;
triangles[16] = 5;
triangles[17] = 6;
triangles[18] = 0;
triangles[19] = 7;
triangles[20] = 4;
triangles[21] = 0;
triangles[22] = 4;
triangles[23] = 3;
triangles[24] = 5;
triangles[25] = 4;
triangles[26] = 7;
triangles[27] = 5;
triangles[28] = 7;
triangles[29] = 6;
triangles[30] = 0;
triangles[31] = 6;
triangles[32] = 7;
triangles[33] = 0;
triangles[34] = 1;
triangles[35] = 6;
for (int i = 1; i < pointSize; i++)
{
for (int j = 0; j < 36; j++)
{
int val = triangles[j] + 8 * i;
triangles[i * 36 + j] = triangles[j] + 8 * i;
}
}
mesh.triangles = triangles;
Color32[] colors = new Color32[mesh.vertices.Length];
for (int i = 0; i < pointSize; i++)
{
for (int j = 0; j < 8; j++)
{
Color32 newColor = new Color32(
(byte)ColorList[i].x,
(byte)ColorList[i].y,
(byte)ColorList[i].z,
255);
colors[i * 8 + j] = newColor;
}
}
mesh.colors32 = colors;
Debug.Log("points : " + PointList.Count);
Debug.Log("vertices (point*8): " + mesh.vertices.Length);
Debug.Log("triangles (point*36): " + mesh.triangles.Length);
Debug.Log("colors (points*8): " + mesh.colors32.Length);
}
I found an anser!!!!
the maximum number of vertices is 65535 when using mesh!!!
Adding just one line can solve this problem
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
How to use meshes with more than 64k vertices in Unity 2018.1
I am trying to generate spheres within my gameworld.
I have this script: RandomEnvironment
using UnityEngine;
using System.Collections;
public class RandomEnvironment : MonoBehaviour
{
public Material[] meshMaterials;
int numberOfMeshes = 50;
// Use this for initialization
void Start()
{
for (int i = 1; i <= numberOfMeshes; i++)
{
GameObject planetObject = new GameObject("Planet" + i);
Randomize randomPlanet = planetObject.AddComponent<Randomize>();
planetObject.transform.position = new Vector3(Random.Range(-1000, 1000), Random.Range(-1000, 1000), Random.Range(-1000, 1000));
}
}
}
And then I have the script Randomize:
//http://wiki.unity3d.com/index.php/ProceduralPrimitives
using UnityEngine;
using System.Collections;
public class Randomize : MonoBehaviour {
// Use this for initialization
void Start () {
MeshFilter filter = gameObject.AddComponent<MeshFilter>();
Mesh mesh = filter.mesh;
mesh.Clear();
float radius = 1f;
// Longitude |||
int nbLong = 24;
// Latitude ---
int nbLat = 16;
#region Vertices
Vector3[] vertices = new Vector3[(nbLong + 1) * nbLat + 2];
float _pi = Mathf.PI;
float _2pi = _pi * 2f;
vertices[0] = Vector3.up * radius;
for (int lat = 0; lat < nbLat; lat++)
{
float a1 = _pi * (float)(lat + 1) / (nbLat + 1);
float sin1 = Mathf.Sin(a1);
float cos1 = Mathf.Cos(a1);
for (int lon = 0; lon <= nbLong; lon++)
{
float a2 = _2pi * (float)(lon == nbLong ? 0 : lon) / nbLong;
float sin2 = Mathf.Sin(a2);
float cos2 = Mathf.Cos(a2);
vertices[lon + lat * (nbLong + 1) + 1] = new Vector3(sin1 * cos2, cos1, sin1 * sin2) * radius;
}
}
vertices[vertices.Length - 1] = Vector3.up * -radius;
#endregion
#region Normales
Vector3[] normales = new Vector3[vertices.Length];
for (int n = 0; n < vertices.Length; n++)
normales[n] = vertices[n].normalized;
#endregion
#region UVs
Vector2[] uvs = new Vector2[vertices.Length];
uvs[0] = Vector2.up;
uvs[uvs.Length - 1] = Vector2.zero;
for (int lat = 0; lat < nbLat; lat++)
for (int lon = 0; lon <= nbLong; lon++)
uvs[lon + lat * (nbLong + 1) + 1] = new Vector2((float)lon / nbLong, 1f - (float)(lat + 1) / (nbLat + 1));
#endregion
#region Triangles
int nbFaces = vertices.Length;
int nbTriangles = nbFaces * 2;
int nbIndexes = nbTriangles * 3;
int[] triangles = new int[nbIndexes];
//Top Cap
int i = 0;
for (int lon = 0; lon < nbLong; lon++)
{
triangles[i++] = lon + 2;
triangles[i++] = lon + 1;
triangles[i++] = 0;
}
//Middle
for (int lat = 0; lat < nbLat - 1; lat++)
{
for (int lon = 0; lon < nbLong; lon++)
{
int current = lon + lat * (nbLong + 1) + 1;
int next = current + nbLong + 1;
triangles[i++] = current;
triangles[i++] = current + 1;
triangles[i++] = next + 1;
triangles[i++] = current;
triangles[i++] = next + 1;
triangles[i++] = next;
}
}
//Bottom Cap
for (int lon = 0; lon < nbLong; lon++)
{
triangles[i++] = vertices.Length - 1;
triangles[i++] = vertices.Length - (lon + 2) - 1;
triangles[i++] = vertices.Length - (lon + 1) - 1;
}
#endregion
mesh.vertices = vertices;
mesh.normals = normales;
mesh.uv = uvs;
mesh.triangles = triangles;
mesh.RecalculateBounds();
mesh.Optimize();
}
// Update is called once per frame
void Update () {
}
}
I found the script to generate a sphere on the internet. The Randomize script is supposed to draw me a sphere, and the RandomEnvironment is supposed to make use of that. When I launch the game, I do not get any errors, but there aren't any spheres either. I placed the RandomEnvironment script on an empty gameobject.
I am a beginner with Unity, any help is welcome!
So I'm trying to port a tilemap solution from XNA and Ive based this start of a youtube tutorial but I'm having a hard time with Mesh's (which as far as I can see are the only way to draw a surface).
I have an overarching object TileMap and a Tilemap can have many Map Layers. The problem is inside my code when I assign a mesh to a MapLayer it tries to assign it Up to the TileMap.
MissingComponentException: There is no 'MeshFilter' attached to the
"TileMap" game object, but a script is trying to access it. You
probably need to add a MeshFilter to the game object "TileMap". Or
your script needs to check if the component is attached before using
it.
MapLayer.BuildMesh (UnityEngine.MeshFilter meshFiler, UnityEngine.MeshRenderer meshRenderer, UnityEngine.MeshCollider meshCollider) (at Assets/MapLayer.cs:79)
Unfortunatly pastebin is down atm but Ill move all this crap off the most as soon as It's back up
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;
// Use this for initialization
void Start ()
{
GetLayer ();
}
void GetLayer ()
{
MapLayer m = new MapLayer (GetComponent<MeshFilter> (),
GetComponent<MeshRenderer> (),
GetComponent<MeshCollider> (),
size_x, size_z, tileSize);
}
}
using System;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshCollider))]
public class MapLayer
{
public int size_x;
public int size_z;
public float tileSize;
// Use this for initialization
public MapLayer (MeshFilter meshFiler, MeshRenderer meshRenderer, MeshCollider meshCollider,
int size_x, int size_z, float tileSize)
{
this.size_x = size_x;
this.size_z = size_z;
this.tileSize = tileSize;
BuildMesh (meshFiler, meshRenderer, meshCollider);
}
void BuildMesh (MeshFilter meshFiler, MeshRenderer meshRenderer, MeshCollider meshCollider)
{
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 / vsize_x, (float)z / vsize_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 + 1] = z * vsize_x + x + vsize_x + 0;
triangles [triOffset + 2] = z * vsize_x + x + vsize_x + 1;
triangles [triOffset + 3] = z * vsize_x + x + 0;
triangles [triOffset + 4] = z * vsize_x + x + vsize_x + 1;
triangles [triOffset + 5] = z * vsize_x + x + 1;
}
}
Debug.Log ("Done Triangles!");
// 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 = meshFiler;
MeshRenderer mesh_renderer = meshRenderer;
MeshCollider mesh_collider = meshCollider;
mesh_filter.mesh = mesh;
mesh_collider.sharedMesh = mesh;
Debug.Log ("Done Mesh!");
}
}
You are only using 1 GameObject here. You are assigning your script TileMap as a component to a GameObject, then creating an instance of the class MapLayer within the TileMap Component, which is on the single GameObject you're using.
I think you should try to utilize the component nature of Unity3D a little more.
To fix this you will need to refactor your code a little:
Have MapLayer extend from MonoBehaviour so it can be attached as a component to a GameObject.
Refactor TileMap to support multiple MapLayers and spawn the MapLayer as its own GameObject.
I have refactored your classes for you as an example. In Unity Editor you would make the MapLayer gameobjects manually and ensure you attach them as children of the TileMap.
TileMap:
using System.Collections.Generic;
using UnityEngine;
public class TileMap : MonoBehaviour {
public int size_x = 100;
public int size_z = 50;
public float tileSize = 1.0f;
// Use this for initialization
void Start() {
}
void CreateMapLayer() {
GameObject mapLayerGO = new GameObject();
mapLayerGO.transform.parent = gameObject.transform;
MapLayer mapLayer = mapLayerGO.AddComponent<MapLayer>();
mapLayer.Initialize();
}
}
MapLayer:
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshCollider))]
public class MapLayer : MonoBehaviour {
private TileMap parentTileMap;
void Start() {
parentTileMap = transform.parent.GetComponent<TileMap>();
}
// Use this for initialization
public void Initialize() {
BuildMesh();
}
void BuildMesh() {
int numTiles = parentTileMap.size_x * parentTileMap.size_z;
int numTris = numTiles * 2;
int vsize_x = parentTileMap.size_x + 1;
int vsize_z = parentTileMap.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 * parentTileMap.tileSize, 0, z * parentTileMap.tileSize);
normals[z * vsize_x + x] = Vector3.up;
uv[z * vsize_x + x] = new Vector2((float)x / vsize_x, (float)z / vsize_z);
}
}
Debug.Log("Done Verts!");
for (z = 0; z < parentTileMap.size_z; z++) {
for (x = 0; x < parentTileMap.size_x; x++) {
int squareIndex = z * parentTileMap.size_x + x;
int triOffset = squareIndex * 6;
triangles[triOffset + 0] = z * vsize_x + x + 0;
triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 0;
triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 3] = z * vsize_x + x + 0;
triangles[triOffset + 4] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 5] = z * vsize_x + x + 1;
}
}
Debug.Log("Done Triangles!");
// 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 = gameObject.GetComponent<MeshFilter>();
MeshRenderer mesh_renderer = gameObject.GetComponent<MeshRenderer>(); ;
MeshCollider mesh_collider = gameObject.GetComponent<MeshCollider>(); ;
mesh_filter.mesh = mesh;
mesh_collider.sharedMesh = mesh;
Debug.Log("Done Mesh!");
}
}