Im trying to make a 'n' sided mesh with a custom color for each triangle, I can select how many sides it has, the radius, and i'm struggling with the color. I want to put a random color on each drawn triangle, now that works, but I don't want it to blend with the other colors, I want it to be a flat color.
Shoud I make a material for each triangle via code and assign it to a triangle?, maybe a shader?. I dont know too much about materials or shaders, but willing to learn, just need to know what would be the best solution and maybe how to apply it.this is an Example of what i want
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[RequireComponent(typeof(MeshFilter))]
public class CreateSectionMesh : MonoBehaviour {
//Sides of the Plane
[Range(3, 100, order = 1)]
[SerializeField]
int NumberOfSides = 3;
//Radius of the plane
[Range(10, 100, order = 1)]
[SerializeField]
int ShapeRadius = 10;
// Just setup everything from the start to test...
void Start() {
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = new Vector3[NumberOfSides + 1];
//With this I can know the angle for each triangle
float angle = 2 * Mathf.PI / NumberOfSides;
vertices[0] = new Vector3(0, 0);
Color[] colors = new Color[vertices.Length];
//Set the vertices
for (int i = 1; i <= NumberOfSides; i++) {
vertices[i] = new Vector3(Mathf.Sin(i * angle), Mathf.Cos(i * angle)) * ShapeRadius;
}
for (int i = 0; i <= NumberOfSides; i++) {
Debug.LogFormat("Vertices: {0}", vertices[i]);
}
//Setup the triangles to draw them properly
int[] triangles = new int[3 * NumberOfSides];
for (int i = 0; i < NumberOfSides; i++) {
triangles[3 * i] = 0;
triangles[3 * i + 1] = i + 1;
triangles[3 * i + 2] = i + 2 > NumberOfSides ? i + 2 - NumberOfSides : i + 2;
}
for (int i = 0; i < triangles.Length; i++) {
Debug.Log(triangles[i]);
}
//Finally the color for each triangle, but is blending with each near driangle color...
for (int i = 0; i < vertices.Length; i++) {
colors[i] = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.colors = colors;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.Optimize();
}
}
Thanks for the help
Related
When I hit Play Unity makes me wait infinite time before start the scene. The message in Hold On window is "Application.EnterPlayMode Waiting for Unity's code to finish executing". There is only one scene in URP with global volume, directional light and a plane with this script:
using UnityEngine;
public class PerlinNoise : MonoBehaviour
{
[Header("Resolution")]
[Space]
public int width = 256;
public int heigth = 256;
[Space]
[Header("Adjustments")]
[Space]
public float scale = 20;
public float xOffset = 10;
public float yOffset = 10;
void Update()
{
Renderer renderer = GetComponent<Renderer>();
renderer.material.mainTexture = GenerateTexture();
}
Texture2D GenerateTexture()
{
Texture2D texture = new Texture2D(width, heigth);
for (int x = 0; x < width; x++)
{
for (int y = 0; x < heigth; y++)
{
Color color = GenerateColor(x, y);
texture.SetPixel(width, heigth, color);
}
}
texture.Apply();
return texture;
}
Color GenerateColor(int x, int y)
{
float xCoord = (float)x / width * scale + xOffset;
float yCoord = (float)y / width * scale + yOffset;
float perlinNoise = Mathf.PerlinNoise(xCoord, yCoord);
return new Color(perlinNoise, perlinNoise, perlinNoise);
}
}
I tried to kill unity editor task in task manager and restart unity but the same issue repeats. Please help me
You have an infinite loop inside your GenerateTexture method. Specifically, the condition in the nested loop (for y) is accidentally checking for x:
for (int x = 0; x < width; x++)
{
for (int y = 0; x < heigth; y++) // x < height SHOULD BE y < height
{
Color color = GenerateColor(x, y);
texture.SetPixel(width, heigth, color); // this should probably be (x, y, color)
}
}
There is a code for a drawing circle with LineRenderer.
but I want to draw multiple circles with different radius, I used "for loop" but there is one circle instead of multiple
public float ThetaScale = 0.01f;
public float radius = 3f;
private int Size;
private LineRenderer LineDrawer;
private float Theta = 0f;
void Start ()
{
LineDrawer = GetComponent<LineRenderer>();
}
void Update ()
{
Theta = 0f;
Size = (int)((1f / ThetaScale) + 1f);
LineDrawer.SetVertexCount(Size);
for (int l = 0; l < 5; l++)
{
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
LineDrawer.SetPosition(i, new Vector3(x, 0, y));
}
}
}
In every loop you always overwrite the same positions indices in the same line renderer. So you will always only have the last circle.
Note that it is also quite expensive to use SetPoisition repeatedly. As it says in the API you should rather work on an array and then use SetPoisitions to assign all positions at once.
One thing is a bit unclear though: If you use one single LineRenderer you won't get independent circles but they will always be connected at some point. Otherwise you would need 5 separated LineRenderer instances.
Option A: 5 circles but connected to each other since part of a single LineRenderer
void Start ()
{
LineDrawer = GetComponent<LineRenderer>();
LineDrawer.loop = false;
Theta = 0f;
// Use one position more to close the circle
Size = (int)((1f / ThetaScale) + 1f) + 1;
LineDrawer.positionCount = 5 * Size;
var positions = new Vector3[5 * Size];
for (int l = 0; l < 5; l++)
{
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
positions[5 * l + i] = new Vector3(x, 0, y);
}
}
LineDrawer.SetPositions(positions);
}
Option B: 5 separated circles in 5 separated LineRenderers
// Drag 5 individual LineRenderer here via the Inspector
public LineRenderer[] lines = new LineRenderer[5];
void Start ()
{
foreach(var line in lines)
{
line.loop = true;
Theta = 0f;
Size = (int)((1f / ThetaScale) + 1f);
line.positionCount = Size;
var positions = new Vector3[Size];
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
positions[5 * l + i] = new Vector3(x, 0, y);
}
line.SetPositions(positions);
}
}
You missed few details here and there. Here, this will work:
using UnityEngine;
[ExecuteAlways]
[RequireComponent( typeof(LineRenderer) )]
public class CircularBehaviour : MonoBehaviour
{
[SerializeField][Min(3)] int _numSegments = 16;
[SerializeField][Min(1)] int _numCircles = 5;
[SerializeField] float _radius = 3f;
LineRenderer _lineRenderer;
void Awake ()
{
_lineRenderer = GetComponent<LineRenderer>();
_lineRenderer.loop = false;
_lineRenderer.useWorldSpace = false;
}
void Update ()
{
const float TAU = 2f * Mathf.PI;
float theta = TAU / (float)_numSegments;
int numVertices = _numSegments + 1;
_lineRenderer.positionCount = numVertices * _numCircles;
int vert = 0;
for( int l=1 ; l<=_numCircles ; l++ )
{
float r = _radius * (float)l;
for( int i=0 ; i<numVertices ; i++ )
{
float f = theta * (float)i;
Vector3 v = new Vector3{ x=Mathf.Cos(f) , y=Mathf.Sin(f) } * r;
_lineRenderer.SetPosition( vert++ , v );
}
}
}
}
But
as #derHugo explained, this is not what you're looking for exactly as all circles will be drawn connected.
I am trying to make a 3D-voxel game that uses the marching cubes algorithm to procedurally generate a game world. This is working fine so far, except that, on exactly perpendicular sides on the positive and negative x sides of a given perpendicular piece of the world/chunk mesh, it looks like the uv coordinates aren't quite right as it just displays a solid color instead of the texture. [![view of debug-chunks and the buggy sides][1]][1]
At <2.> you can see the chunk wall how it is supposed to look like and at <1.> you can see the weird bug. This ONLY occurs on exactly perpendicular x-side triangles! Those meshes in the image are debug-chunks to show the problem.
All the noise-to-terrain translation works fine and I don't get any bugs there. It's only the uvs that cause problems.
I am using the following code to populate the Mesh.vertices, Mesh.triangles and Mesh.uv:
void MakeChunkMeshData()
{
for (int x = 0; x < Variables.chunkSize.x - 1; x++)
{
for (int y = 0; y < Variables.chunkSize.y - 1; y++)
{
for (int z = 0; z < Variables.chunkSize.z - 1; z++)
{
byte[] cubeCornerSolidityValues = new byte[8]{
chunkMapSolidity[x, y, z],
chunkMapSolidity[x + 1, y, z],
chunkMapSolidity[x + 1, y + 1, z],
chunkMapSolidity[x, y + 1, z],
chunkMapSolidity[x, y, z + 1],
chunkMapSolidity[x + 1, y, z + 1],
chunkMapSolidity[x + 1, y + 1, z + 1],
chunkMapSolidity[x, y + 1, z + 1]
};
MarchOne(new Vector3Int(x, y, z), cubeCornerSolidityValues);
}
}
}
}
void DrawChunk()
{
chunkMesh.vertices = vertices.ToArray();
chunkMesh.triangles = triangles.ToArray();
chunkMesh.SetUVs(0, uvs.ToArray());
chunkMesh.RecalculateNormals();
}
void ClearMesh()
{
chunkMesh.Clear();
}
void ClearChunkMeshAndData()
{
chunkMesh.Clear();
uvs = new List<Vector2>();
vertices = new List<Vector3>();
triangles = new List<int>();
}
/// <summary>
/// cube contains bytes for each corner of the cube
/// </summary>
/// <param name="cube"></param>
/// <returns></returns>
int GetCubeConfiguration(byte[] cube)
{
int u = 0;
int result = 0;
for(int corner = 0; corner < 8; corner++)
{
if (cube[corner] < Variables.solidityThreshold)
{
u++;
result |= 1 << corner;
}
}
return result;
}
Vector2[] getUvsPerTriangle(byte[] voxelTypes)
{
int resId = voxelTypes[0];
if (voxelTypes[1] == voxelTypes[2])
resId = voxelTypes[1];
resId = 1;
Vector2 normalized = getUvCoordFromTextureIndex(resId) / Constants.TextureAtlasSizeTextures;
float textureLength = 1f/Constants.TextureAtlasSizeTextures;
Vector2[] result = new Vector2[3] {
normalized + new Vector2(1,0) * textureLength,
normalized + new Vector2(0,1) * textureLength,
normalized + new Vector2(1,1) * textureLength
};
//Debug.Log(result);
return result;
}
/// <summary>
/// returns the absolute x and y coordinates of the given texture in the atlas (example: [4, 1])
/// </summary>
/// <param name="textureIndex"></param>
/// <returns></returns>
Vector2 getUvCoordFromTextureIndex(int textureIndex)
{
int x = textureIndex % Constants.TextureAtlasSizeTextures;
int y = (textureIndex - x) / Constants.TextureAtlasSizeTextures;
return new Vector2(x, y);
}
/// <summary>
/// takes the chunk-wide mesh data and adds its results after marching one cube to it.
/// </summary>
/// <returns></returns>
void MarchOne(Vector3Int offset, byte[] cube)
{
int configuration = GetCubeConfiguration(cube);
byte[] voxelTypes = new byte[3];
int edge = 0;
for (int i = 0; i < 5; i++) //loop at max 5 times (max number of triangles in one cube config)
{
for(int v = 0; v < 3; v++) // loop 3 times through shit(count of vertices in a TRIangle, who would have thought...)
{
int cornerIndex = VoxelData.TriangleTable[configuration, edge];
if (cornerIndex == -1) // indicates the end of the list of vertices/triangles
return;
Vector3 vertex1 = lwTo.Vec3(VoxelData.EdgeTable[cornerIndex, 0]) + offset;
Vector3 vertex2 = lwTo.Vec3(VoxelData.EdgeTable[cornerIndex, 1]) + offset;
Vector3Int vertexIndex1 = lwTo.Vec3Int(VoxelData.EdgeTable[cornerIndex, 0]) + offset;
Vector3Int vertexIndex2 = lwTo.Vec3Int(VoxelData.EdgeTable[cornerIndex, 1]) + offset;
Vector3 vertexPosition;
if (Variables.badGraphics)
{
vertexPosition = (vertex1 + vertex2) / 2f;
}
else
{
// currently using this "profile"
// this code determines the position of the vertices per triangle based on the value in chunkSolidityMap[,,]
float vert1Solidity = chunkMapSolidity[vertexIndex1.x, vertexIndex1.y, vertexIndex1.z];
float vert2Solidity = chunkMapSolidity[vertexIndex2.x, vertexIndex2.y, vertexIndex2.z];
float difference = vert2Solidity - vert1Solidity;
difference = (Variables.solidityThreshold - vert1Solidity) / difference;
vertexPosition = vertex1 + ((vertex2 - vertex1) * difference);
}
vertices.Add(vertexPosition);
triangles.Add(vertices.Count - 1);
voxelTypes[v] = chunkMapVoxelTypes[vertexIndex1.x, vertexIndex1.y, vertexIndex1.z];
edge++;
}
uvs.AddRange(getUvsPerTriangle(voxelTypes));
}
}
EDIT:
when only slightly rotating the chunks, the weird problem immediately disappears. I don't know why, but at least i now have some clue what's going on here.
[1]: https://i.stack.imgur.com/kYnkl.jpg
Well, it turns out that this probably is some weird behavior from unity. When explicitly setting the mesh after the mesh population process as the meshFilters' mesh, it works just fine. Also, I had to call mesh.RecalculateTangents() to make it work.
i want to create a view like grid with prefabs inside camera view but i'm unable to do so. prefabs are going out of the camera view. can any one help me to resolve this? i want to place prefab as a grid and 9 * 6 grid.
public GameObject tilePrefab;
Vector2 mapSize;
void Start()
{
createGrid();
Debug.Log("Screen Width : " + Screen.width);
Debug.Log("Screen Height : " + Screen.height);
mapSize = new Vector2(Screen.width/9,Screen.height/12);
Debug.Log("mapSize : " + mapSize);
}
void createGrid()
{
for (int x = 0; x < 9; x++)
{
for (int y = 0; y < 6; y++)
{
Vector3 tilePosition = new Vector3(-mapSize.x+0.5f + x,-mapSize.y + 0.5f+y ,0 );
GameObject ballclone = (GameObject)Instantiate(tilePrefab,tilePosition,Quaternion.identity);
ballclone.transform.parent = transform;
}
}
}
You can use ViewportToWorldPoint
for (int x = 0; x < 9; x++)
for (int y = 0; y < 6; y++)
xx.position = camera.ViewportToWorldPoint(new Vector3(1f/9*x, 1f/6*y, distance));
distance is the distance between the camera and the object.
When creating the mesh, I had a problem: both in the game, and in the scene appears a large triangular polygon. The problem is that with a system size of 250 by 250 points there aren't this polygon. At a size of 400 by 400 points, it already appears.
What I did:
void Start () {
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = mf.mesh;
int size = 400;
Vector3[] vertices = new Vector3[size * size];
Vector3[] normals = new Vector3[size * size];
Vector2[] uvc = new Vector2[size * size];
int c = 0;
for (int i =0; i < size; i++)
{
for(int j =0; j < size; j++)
{
vertices[c] = new Vector3(i, j, Mathf.Sin(j+i+Mathf.PI));
normals[c] = -Vector3.forward;
float mult = 1.0f / ((float)(size));
uvc[c] = new Vector2(((float)(i))*mult, ((float)(j)) * mult);
c++;
}
};
int[] triangles = new int[(size-1)*(size-1)*6];
int counter = 0;
{
for (int i = 0; i < size - 1; i++)
{
for (int j = 0; j < size - 1; j++)
{
setTriangle(ref triangles, ref counter, i * size + j);
setTriangle(ref triangles, ref counter, (i + 1) * size + j);
setTriangle(ref triangles, ref counter, i * size + j + 1);
setTriangle(ref triangles, ref counter, (i + 1) * size + j);
setTriangle(ref triangles, ref counter, (i + 1) * size + j + 1);
setTriangle(ref triangles, ref counter, i * size + j + 1);
};
}
};
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uvc;
mesh.RecalculateNormals();
gameObject.transform.position = new Vector3(-55, -60, 90);
void setTriangle(ref int[] triangle, ref int index, int num)
{
triangle[index++] = num;
}
And what I have in results. The first picture is with 250 by 250 points. The second is with 400 by 400. The third is just bigger picture
I think you are over the max. number of vertices for the mesh when the size is 400x400.
The default max. number of vertices for a mesh is 65535. If you want to have more, then you have to set:
mesh.indexFormat = Rendering.IndexFormat.UInt32;
but this is not guaranteed to be supported in all platforms.