I have a normal class with no errors, but visual studio thinks the class ends before it should. It thinks the c* bracket of the whole class itself. Can you help me? I will show you a photo of what I mean:
You can see what I mean with the picture: the class ends where it shouldn't. I have already tried erasing a adding new brackets, copy and paste, and almost anything you can think of.
EDIT:
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using LukeWaffel.BUI;
using UnityEngine.UI;
public class Pattern : MonoBehaviour
{
public Text levelTxt;
public GameObject[] displayRow;
//a messageBox instance that can be used many times
private UIBox box;
public GameObject displayPrefab;
public GameObject displayBlockParent;
public GameObject userPrefab;
public GameObject userBlockParent;
public GameObject[] userRow;
//an array that is used for a function to check if all boolians in the array are true
private bool[] alltrue;
public int zNum;
public int xNum;
public int yNum;
private Color[] colors;
private bool isHardGenerate = false;
//the space between blocks needed to create a table
private float offset;
//how many colors are currently at play for exapmle: colorNum = 2 (the colors allowed in a pattern are red and yellow)
private int colorNum = 2;
// a variable that indicates the amount of colored blocks in a pattern
private int numToColor = 0;
public static int level = 0;
// a class that indicates which blocks are active: user or display;
private BlockController b;
// Start is called before the first frame update
private void Start()
{
levelTxt.text = "Level: " + (level + 1);
//initialize the colors available in the current game.
List<Color> colorsTemp = new List<Color>();
colorsTemp.Add(Color.red);
colorsTemp.Add(Color.yellow);
colorsTemp.Add(Color.green);
//convert the colors to array. the list was there just to add the colors hence thte name colorsTemp
colors = colorsTemp.ToArray<Color>();
//the blockController class controls how much time the user has to see the pattern before it is drawn
b = gameObject.GetComponent<BlockController>();
offset = 1f;
//start to generate the pattern
GenerateEasy();
}
private void GenerateEasy()
{
//set the number of colored blocks(randomized) GetRandomFloat is a custom function created to decide the skip of the randomized number. By defult that value is 0.5f
private float rnd = GetRandomFloat(1, 4);
if(rnd == 1)//that means that all blocks would be colored and thats an easy pattern. because of that we need to change the number
{
rnd++;
}
//the formula to decide how many blocks will be colored
numToColor = Mathf.CeilToInt((Num* xNum * yNum)/rnd);
// Create empty grid
displayRow = new GameObject[zNum * xNum * yNum];
userRow = new GameObject[zNum * xNum * yNum];
alltrue = new bool[yNum * xNum * zNum];
// Create blocks
for (int i = 0; i<yNum; i++)
{
for (int j = 0; j<xNum; j++)
{
for (int k = 0; k<zNum; k++)
{
//creating display table we are not selecting the pattern yet.
GameObject g = Instantiate(displayPrefab, new Vector3(j * offset, i * offset, k * offset), Quaternion.Euler(180, 0, 0), displayBlockParent.transform);
displayRow[i * (xNum * zNum) + j * zNum + k] = g;
//creating the coloring table (in all variables named build/user)
GameObject o = Instantiate(userPrefab, new Vector3(j * offset, i * offset, k * offset), Quaternion.Euler(180, 0, 0), userBlockParent.transform);
userRow[i * (xNum * zNum) + j * zNum + k] = o;
userRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color = colors[0];
}
}
}
//reverse the array because by defult the blocks are upside down, so we need to correct that and flip all the blocks again
Array.Reverse(displayRow);
Array.Reverse(userRow);
//create pattern for the display table. notice in the for loop the outer for loop runs numToColor times, the amount of blocks that should be colored
for (int s = 0; s<numToColor; s++)
{
//the for loop runs once too much, so in the first loop we need to not make any actions, unless num to color is 1, and then it only runs one time.
if (numToColor != 1 && s == 0)
{
continue;
}
//initialize the colored and notcolored lists. this only exists in generateEasy because this makes the pattern easier to remember. colored are the blocks that are not good for coloring and not colored are the blocks viable to color.
List<GameObject> colored = new List<GameObject>();
List<GameObject> notColored = new List<GameObject>();
//if non of the blocks are colored yet, color a block randomly
if (displayRow.ToList<GameObject>().All(p => p.GetComponent<Renderer>().material.color == colors[0]))
{
int randomIndex = UnityEngine.Random.Range(0, yNum * xNum * zNum);
displayRow[randomIndex].GetComponent<Renderer>().material.color = colors[UnityEngine.Random.Range(1, colorNum)];
}
//this for checks if any of the blocks that exist contain a color that isn't red(the defult color)
for (int i = 0; i<yNum; i++)
{
for (int j = 0; j<xNum; j++)
{
for (int k = 0; k<zNum; k++)
{
//the colors array are all the available colors in the game. because red is the defult color and the first one in the array, it does not count as a colored block and therefor need to be skipped for the if statment.
if (colors.Skip(1).Any(p => p == displayRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color))
{
//adding the colored blocks to the colored array, which helps later for the formula for the easy pattern, and at the same time making them unable to be recolored accidently by the pattern.
colored.Add(displayRow[i * (xNum * zNum) + j * zNum + k]);
}
}
}
}
//thia doe loop checks if the block that's not already colored is viable for being colored for the easy level. if it is, it adds the block to the notColored array
for (int i = 0; i<yNum; i++)
{
for (int j = 0; j<xNum; j++)
{
for (int k = 0; k<zNum; k++)
{
if (displayRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color == colors[0] && (colored.Any(p => (j != xNum - 1 && GameObject.ReferenceEquals(p, displayRow[i * (xNum * zNum) + (j + 1) * zNum + k]))
|| (j != 0 && GameObject.ReferenceEquals(p, displayRow[i * (xNum * zNum) + (j - 1) * zNum + k]))
|| (i != 0 && GameObject.ReferenceEquals(p, displayRow[(i - 1) * (xNum * zNum) + j * zNum + k]))
|| (i != yNum - 1 && GameObject.ReferenceEquals(p, displayRow[(i + 1) * (xNum * zNum) + j * zNum + k]))
|| (k != 0 && GameObject.ReferenceEquals(p, displayRow[i * (xNum * zNum) + j * zNum + k - 1]))
|| (k != zNum - 1 && GameObject.ReferenceEquals(p, displayRow[i * (xNum * zNum) + j * zNum + k + 1])))))
{
notColored.Add(displayRow[i * (xNum * zNum) + j * zNum + k]);
}
}
}
}
//finally, one of the not colored blocks in the not colored array is randomly colored with a random color according to level.
notColored.ToArray()[UnityEngine.Random.Range(0, notColored.ToArray().Length)].GetComponent<Renderer>().material.color = colors[UnityEngine.Random.Range(1, colorNum)];
}
}
private void GenerateHard()
{
//up until the very end, Generate hard is extremley similar to easyGenerate. if you want detailed comment on most of the function, please refer to easy generate.
//set the number of colored blocks
float rnd = GetRandomFloat(1, 4);
if (rnd == 1)
{
rnd++;
}
numToColor = Mathf.CeilToInt((zNum * xNum * yNum) / rnd);
displayRow = new GameObject[zNum * xNum * yNum];
userRow = new GameObject[zNum * xNum * yNum];
alltrue = new bool[yNum * xNum * zNum];
for (int i = 0; i < yNum; i++)
{
for (int j = 0; j < xNum; j++)
{
for (int k = 0; k < zNum; k++)
{
GameObject g = Instantiate(displayPrefab, new Vector3(j * offset, i * offset, k * offset), Quaternion.Euler(180, 0, 0), displayBlockParent.transform);
displayRow[i * (xNum * zNum) + j * zNum + k] = g;
GameObject o = Instantiate(userPrefab, new Vector3(j * offset, i * offset, k * offset), Quaternion.Euler(180, 0, 0), userBlockParent.transform);
userRow[i * (xNum * zNum) + j * zNum + k] = o;
userRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color = colors[0];
}
}
}
Array.Reverse(displayRow);
Array.Reverse(userRow);
//create a pattern. for now it is the same as easy generate but it's going to get different soon.
for (int s = 1; s < numToColor; s++)
{
List<GameObject> colored = new List<GameObject>();
List<GameObject> notColored = new List<GameObject>();
if (displayRow.ToList<GameObject>().All(p => p.GetComponent<Renderer>().material.color == colors[0]))
{
int randomIndex = UnityEngine.Random.Range(0, yNum * xNum * zNum);
displayRow[randomIndex].GetComponent<Renderer>().material.color = colors[UnityEngine.Random.Range(1, colorNum)];
}
for (int i = 0; i < yNum; i++)
{
for (int j = 0; j < xNum; j++)
{
for (int k = 0; k < zNum; k++)
{
if (colors.Skip(1).Any(p => p == displayRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color))
{
colored.Add(displayRow[i * (xNum * zNum) + j * zNum + k]);
}
}
}
}
//now is the different part, the for loop does not check if the block will be viable for an easy pattern, it just adds every blocks that's not colored, even if that block makes the pattern much harder
for (int i = 0; i < yNum; i++)
{
for (int j = 0; j < xNum; j++)
{
for (int k = 0; k < zNum; k++)
{
if (displayRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color == colors[0])
{
notColored.Add(displayRow[i * (xNum * zNum) + j * zNum + k]);
}
}
}
}
//like before, the progranm chooses to color a block in the not coloed array randomly.
notColored.ToArray()[UnityEngine.Random.Range(0, notColored.ToArray().Length)].GetComponent<Renderer>().material.color = colors[UnityEngine.Random.Range(1, colorNum)];
}
}
// Update is called once per frame
private void Update()
{
//this huge outer if is resposible for cheking the pattern
if (Input.GetKeyDown(KeyCode.Return) && !CrossHair.ok)
{
for (int i = 0; i < yNum; i++)
{
for (int j = 0; j < xNum; j++)
{
for (int k = 0; k < zNum; k++)
{
//checks if the pattern is exactly equal to what the user has colored
if (displayRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color.Equals(userRow[i * (xNum * zNum) + j * zNum + k].GetComponent<Renderer>().material.color))
{
alltrue[i * (xNum * zNum) + j * zNum + k] = true;
}
else
{
alltrue[i * (xNum * zNum) + j * zNum + k] = false;
}
}
}
}
//if the user got the pattern right then...
if (alltrue.ToList<bool>().All(b => b))
{
if ((level + 1) % 10 != 0 && level + 1 != 0)
{
//make the mouse appear and make the user unable to move the player or color any blocks so that the user can focus on the messegebox
CrossHair.ok = true;
Cursor.lockState = CursorLockMode.None;
Cursor.lockState = CursorLockMode.Confined;
Cursor.visible = true;
//display the message bix
box = new UIBox("bID", BUI.UIType.Message);
box.header = "You have passed the level!";
box.body = "You have passed this current level. Have you got what it takes to take on the next Puzzle?";
box.buttons.Add(new UIButton("Yes, next level!", FuncButton));
BUI.Instance.AddToQueue(box);
//reset everything for the next level. also increases the level.
b.Reset();
level++;
levelTxt.text = "Level: " + (level + 1);
DestroyArray(userRow);
DestroyArray(displayRow);
//generate hard and generate easy switch turns.
if (!isHardGenerate)
{
yNum++;
isHardGenerate = true;
GenerateHard();
}
else
{
isHardGenerate = false;
xNum++;
GenerateEasy();
}
}
//every 10 levels a color is added to the table.
else
{
Debug.Log("passed level 10");
CrossHair.ok = true;
Cursor.lockState = CursorLockMode.None;
Cursor.lockState = CursorLockMode.Confined;
Cursor.visible = true;
box = new UIBox("bID", BUI.UIType.Message);
box.header = "You have passed the level!";
box.body = "You have passed this current level. Have you got what it takes to take on the next Puzzle?";
box.buttons.Add(new UIButton("Yes, next level!", FuncButton));
BUI.Instance.AddToQueue(box);
xNum = 2;
yNum = 2;
colorNum++;
b.Reset();
level++;
levelTxt.text = "Level: " + (level + 1);
DestroyArray(userRow);
DestroyArray(displayRow);
isHardGenerate = false;
GenerateEasy();
}
}
//if the user lost then...
else
{
//for this refer to the beginning of the if statment
CrossHair.ok = true;
Cursor.lockState = CursorLockMode.None;
Cursor.lockState = CursorLockMode.Confined;
Cursor.visible = true;
box = new UIBox("bID", BUI.UIType.Message);
box.header = "You have failed";
box.body = "You have failed this current level. Have you got what it takes to try again?";
box.buttons.Add(new UIButton("Yes, try this level again!", FuncButton));
BUI.Instance.AddToQueue(box);
//if level doesnt equal to 0, go down a levle, you cant go down from the first level.
if (level != 0)
level--;
b.Reset();
levelTxt.text = "Level: " + (level + 1);
DestroyArray(userRow);
DestroyArray(displayRow);
if (isHardGenerate)
{
yNum--;
isHardGenerate = false;
GenerateEasy();
}
else
{
if (level != 0)
{
isHardGenerate = true;
xNum--;
GenerateHard();
}
else
{
GenerateEasy();
}
}
}
//destroys every onject in an array
void DestroyArray(GameObject[] b)
{
foreach (GameObject k in b)
Destroy(k.gameObject);
}
//lets the player move again and cloles the message box
void FuncButton(UIBox boxInfo, UIButton buttonInfo)
{
CrossHair.ok = false;
BUI.Instance.CloseBox(box.id);
}
}
}
//go to refrence to find the meaning of the function. (in easyGenerate.)
public float GetRandomFloat(int min, int max, float value = 0.5f)
{
int multipliedMin = (int)(min / value);
int multipliedMax = (int)(max / value);
return ((float)UnityEngine.Random.Range(multipliedMin, multipliedMax)) * value;
}
}
Remove private in private float rnd = GetRandomFloat(1, 4);
Take a look at the official documentation here in order to understand the access modifiers.
You're declaring a property inside a method. These should go within the initial class braces.
Related
I'm trying to make mesh with Vector3 data from database at runtime.
Here is my code
private IEnumerator CreateShape()
{
int count = 0;
triangles = new int[x_size * y_size * 6];
//index buffer
for (int i = 0; i < x_size - 1; i++)
{
for (int j = 0; j < y_size - 1; j++)
{
triangles[((i * y_size + j) * 6) + 0] = i * y_size + j;
triangles[((i * y_size + j) * 6) + 1] = (i + 1) * y_size + j;
triangles[((i * y_size + j) * 6) + 2] = i * y_size + j + 1;
triangles[((i * y_size + j) * 6) + 3] = i * y_size + j + 1;
triangles[((i * y_size + j) * 6) + 4] = (i + 1) * y_size + j;
triangles[((i * y_size + j) * 6) + 5] = (i + 1) * y_size + j + 1;
}
yield return new WaitForSeconds(0.01f);
}
}
And check updates for updating Mesh data..
private void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
Vertices data has no problem, cuz i checked it with different way.
private void OnDrawGizmos()
{
if (vertices[x_size * y_size - 1] != Vector3.zero)
{
for (int i = 0; i < x_size - 1; i++)
{
for (int j = 0; j < y_size - 1; j++)
{
Gizmos.DrawSphere(vertices[i * y_size + j], .1f);
}
}
}
}
Checked whether vertices data is wrong or not with gizmos but the data has no probs:
It should form a simple plane mesh shape, but it goes back to the start point and continue making in the middle of mesh-create-process..
What i expected:
But it goes wrong:
It seemed somehow internal index buffer calculation goes wrong..
Vertices data is about 160,000ea Vector3, and tris is also about 160,000*6 = 1,000,000ea integer.
Maybe the data is too much for making mesh while runtime at all..?
or.. the axis is changed when x value become larger than y value..?
Why this happens? How can i fix this?
As said per default meshes in unity have an index buffer of 16-bit (= UInt16) meaning the maximum index is 65535.
If you want to go higher (like with your mesh) you will need to change the Mesh.indexFormat to 32-bit (= UInt32), allowing a maximum index of 4294967295.
Note though that not all GPU support this!
Well, my question is pretty simple to understand, I'm trying to create a grid of chunks but on each step, I want to double the distance of a chunk.
Then, this is the code I have:
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class DrawLoDTest : MonoBehaviour
{
private List<Vector3> initialChunks;
public int chunkSize = 16;
public int lodLevels = 2;
public int width = 16;
public int height = 16;
private Color[] colorList;
// Start is called before the first frame update
private void Start()
{
}
// Update is called once per frame
private void Update()
{
}
private void Init()
{
if (initialChunks != null && initialChunks.Count > 0)
return;
colorList = new[] { Color.blue, Color.green, Color.yellow, Color.cyan, Color.magenta, Color.grey };
Debug.Log("Init test!");
initialChunks = new List<Vector3>(16 * 16);
for (var i = 0; i < width * height; i++)
{
var x = i % width;
var y = i / width;
initialChunks.Add(new Vector3(x * chunkSize - width * chunkSize / 2, 0, y * chunkSize - height * chunkSize / 2));
}
//Debug.Log(string.Join(Environment.NewLine, initialChunks.Select(v => v.ToString())));
}
private void OnDrawGizmos()
{
Init();
Gizmos.color = Color.red;
foreach (var chunk in initialChunks)
{
Gizmos.DrawWireCube(chunk, Vector3.one * chunkSize);
}
var ww = 0;
var ww2 = 0;
var sum = 0;
var halfChunkSize = chunkSize / 2;
var halfWidth = width * halfChunkSize;
var halfHeight = height * halfChunkSize;
for (var i = 1; i <= lodLevels; i++)
{
if (ww > 0)
++ww2;
var pow = (int)Mathf.Pow(2, i);
var w = width / pow;
var h = height / pow;
Gizmos.color = colorList[i - 1];
var oddSum = ww * chunkSize * pow;
for (var x = -1 - ww2; x <= w + ww2; x++)
{
for (var n = 0; n <= 1; n++)
{
var sign = n == 0 ? -1 : 1;
var chunk = new Vector3(
halfWidth - x * chunkSize * pow - halfChunkSize,
0,
halfHeight * sign - halfChunkSize - chunkSize * 2 * sign + oddSum * sign + sum * sign);
chunk.x -= pow * halfChunkSize;
for (var j = i + 1; j >= i; j--)
{
chunk.z += chunkSize * (int)Mathf.Pow(2, j) / 2 * sign;
}
Gizmos.DrawWireCube(chunk, Vector3.one * chunkSize * pow);
}
}
// TODO
if ((w + ww2 * 2 + 2) / 2 % 2 != 0)
{
Debug.Log($"[{i}, {ww}, {ww2}] W: {w} + {ww2} * 2 = {w + ww2 * 2} + 2 = {w + ww2 * 2 + 2} / 2 = {(w + ww2 * 2 + 2) / 2}");
if (ww == 0)
{
--i;
++ww;
}
else
{
ww = 0;
sum += oddSum;
}
}
else
{
if (ww2 > 0)
ww2 = 0;
}
}
}
}
A little bit of explanation:
First, I load a 16x16 chunk grid (initialChunks).
Then, I start a loop foreach lod level (I'm testing it for 6 levels).
Then, foreach axis I iterate its position.
Then, in a nested loop foreach axis I give a sign (a loop for 0 to 1, that converts into -1 and 1 for the sign).
Then, and this is the more complex thing, if the following row/column has an odd number of elements then I try to match the current row/column by doubling it, in that way non of the following corner will be half of the previous one, like the image below:
I have two main problems:
For some reason, sum and oddSum variables has the wrong input.
At certain levels, (for i >= 5) the logic is broken.
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.
I'm using unity, c#, and I cannot figure out how I can generate a landscape with all different kinds of height colors. For instance, I want sand near the water and snow on mountain peaks. But I cannot manage to make this happen in code where the mesh is being generated.
Just to make clear, The mesh generates perfectly fine, but I cannot manage to change the colors of each separate triangle.
void CreateMesh()
{
planeMesh = new Mesh();
List<Vector3> vertices = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<int> indices = new List<int>();
List<Color> colors = new List<Color>();
for (int x = 0; x < gridSize + 1; x++)
{
for (int y = 0; y < gridSize + 1; y++)
{
float height = Mathf.PerlinNoise(y / (float)gridSize, x / (float)gridSize) * 15.0f;
vertices.Add(new Vector3(y, height, x));
if(height > 12)//mountain tops
{
uvs.Add(new Vector2(0, 1/3));//down to up, x first
colors.Add(Color.white);
}
else if(height > 3 && height < 13)//grassy fields
{
uvs.Add(new Vector2(1/3,2/3));
colors.Add(Color.green);
}
else if(height > 0 && height < 4)//sand
{
uvs.Add(new Vector2(2/3, 2/3));
colors.Add(Color.yellow);
}
}
}
//making the indices
for (int b = 0; b < gridSize; b++)
{
for (int c = 0; c < gridSize; c++)
{
indices.Add(b + ((gridSize + 1) * c));
indices.Add(b + gridSize + 1 + ((gridSize + 1) * c));
indices.Add(b + 1 + ((gridSize + 1) * c));
indices.Add(b + gridSize + 1 + ((gridSize + 1) * c));
indices.Add(b + gridSize + 2 + ((gridSize + 1) * c));
indices.Add(b + 1 + ((gridSize + 1) * c));
}
}
planeMesh.SetVertices(vertices);
planeMesh.SetIndices(indices.ToArray(), MeshTopology.Triangles, 0);
planeMesh.SetUVs(0, uvs);
planeMesh.RecalculateNormals();
planeMesh.colors = colors.ToArray();
GetComponent<MeshFilter>().mesh = planeMesh;
GetComponent<MeshFilter>().mesh.name = "Environment";
}
Could you guys help me with that?
Solved it! It seems the numbers I was using for the uvs were being rounded down to 0! I had to make them floats to use them properly.
I know so many questions have been already asked based on this topic and still i am unable to generate tiles in isometric view.
please check the below code and its out put
private void picIsometricBox_Paint(object sender, PaintEventArgs e)
{
try
{
int paddingTop = sdpaddingTop.Value * -80;
int paddingleft = sdpaddingLeft.Value * 40;
int rotateangle = sbRotate.Value * 5;
int noofCells = 9;
int cellsize = 60;
int x = 0;
for (int j = 1; j <= noofCells; j++)
{
for (int i = 1; i <= noofCells; i++)
{
var ep = (x % 2) == 0 ? Brushes.White : Brushes.Black;
int xv = (j * cellsize + paddingleft);
int yv = (i * cellsize) + paddingTop;
int xxv = (i * cellsize) + paddingleft;
int yyv = cellsize + paddingTop;
e.Graphics.RotateTransform(rotateangle);
e.Graphics.FillRectangle(ep, xv, yv, cellsize, cellsize);
e.Graphics.FillRectangle(ep, xxv, yyv, cellsize, cellsize);
e.Graphics.ResetTransform();
x++;
}
}
}
catch (Exception ex)
{
}
}
output is rendered in picture box:
I am not sure how to generate tiles like below