- Home /
Perlin Resources system
Hello! Im trying to make a perlin based resource map, and for the resources to be harvested, I'm would like to make this map into different models.
I have all the differents values grouped.
the groups you see in the picture, are just a texture, for visualizing while I'm trying to get this whole thing to work,also, the cyan color shows the edge.
The model will be used to check, if a building are on top, if so, begin harvest. however, I'm having some deficulties generating the mesh.
I'm using triangulator for the mesh generation, but it gives me some strange meshes
So, my qustion are:
Are there a better way to harvest these resources? Are there a better way to do this whole system? Are there a better way to generate these models?
UPDATE:: Look at the answer below.
also, I've created a repo for the project, at bitbucket. https://bitbucket.org/bukz/unity-perlin-resource-system/
Interesting idea! Just so that I understand it correctly, you want to create a planar mesh using the Perlin based resouce map?
If the above is correct, my questions are:
- is the resource map 2D?
- what do the values in the resource map mean? That is, are they floats, ints, enum values...?
- how should the mesh represent the different resource values? Should there be a hole in the mesh there?
If you want holes where there are resources, the simplest approach I can imagine is to just generate a texture that has alpha = 0 where there should be holes, and apply that to a simple plane. You can also get from the texture (or even better, from the resource map) if a building can harvest from there.
yes, the resource map should be flat.
the resource map it self are just a texture2D, which have been filled with a random resource, based on a random.range.
the value inside the map, are pixels/color, however, with that, I have a multidimensional array, which hold what kind of resource that pixel are.
from the resource map, a mesh for each of the resource-groups should be generated, so I can convert it into a gameobject.
what I'm essentially trying to do, are make a resource system like SimCIty/City Skylines.
Sorry, I'm still not sure what you would like to do, what the meshes for resource groups should look like. Do you want to have independent shapes where resources are? Or all of them in the same mesh?
Anyway, as to your original question, I think your approach in general is good. The only thing I would recommend is to keep the data model (types of resources for each grid cell) and the visual model (colored texture & generated mesh) separate. This will simplify some logic, the data model telling you all the info, and the visual model only being updated when the data changes. For example, you avoid converting back from pixel colors to resource types, or from pixel coordinates to grid cell coordinates, because that data is always directly available in the data model.
Answer by julio-hb · May 10, 2018 at 07:59 PM
So, I managed to create a somewhat mesh.
to generate the mesh from the points, I made a new texture for the resource with the following code:
public Texture2D GenerateTexture(Vector2[] points)
{
float lowestX = Mathf.Infinity, lowestY = Mathf.Infinity, highestX = 0, highestY = 0;
foreach (Vector2 point in points)
{
if (point.x < lowestX)
lowestX = point.x;
if (point.y < lowestY)
lowestY = point.y;
if (point.x > highestX)
highestX = point.x;
if (point.y < highestY)
highestY = point.y;
}
float length = (highestX + lowestX+ highestY + lowestY) * 10;
Texture2D tex = new Texture2D((int)length, (int)length);
for (int x = 0; x < length; x++)
{
for (int y = 0; y < length; y++)
{
tex.SetPixel(x, y, Color.clear);
}
}
foreach (Vector2 point in points)
{
Vector2 p = point - new Vector2(lowestX,lowestY);
tex.SetPixel((int)p.x,(int)p.y, Color.cyan);
}
tex.Apply();
return tex;
}
After that, I made a sprite from the texture, and used those vertices. (https://answers.unity.com/questions/671208/how-to-convert-sprite-to-mesh-or-to-a-polygon-.html)
public GameObject GenerateResource(GridGroups group)
{
Texture2D resource_texture = GenerateTexture(group.points.ToArray());
Sprite sprite = Sprite.Create(resource_texture, new Rect(0, 0, size.x, size.y), Vector2.zero);
Mesh mesh = new Mesh();
mesh.vertices = Array.ConvertAll(sprite.vertices, i => (Vector3)i);
mesh.uv = sprite.uv;
mesh.triangles = Array.ConvertAll(sprite.triangles, i => (int)i);
GameObject g = new GameObject(group.type.ToString());
g.transform.localScale = new Vector3(100, 100, 100);
g.transform.rotation = Quaternion.Euler(new Vector3(90, 0, 180));
g.AddComponent<MeshFilter>().mesh = mesh;
g.AddComponent<MeshRenderer>();
return g;
}
It would be wrong to say that the result are good, however, atleast the work somewhat now. if anyone else finds a better solution, post a reply.
Heres the updated asset files: https://bitbucket.org/bukz/unity-perlin-resource-system
Now I see what you mean. Not a bad solution, but you are right that probably there is something better. Basically you are creating a texture from a 2D array, and then turning the texture into polygons. I think it is possible to skip the texture and create the polygons directly, but you would have to write the polygon shape detection algorithm (detect the areas enclosed by resource points), at the moment done by the texture-to-sprite function, and that can be hard.
A different approach would be to use a shader with vertex colors, and paint the vertices of a grid mesh (the same size as your terrain) with the color of each resource. It would be a lot easier, but there are some points to consider: - have to use a specific shader (maybe not an issue)
- needs a mesh with a lot more vertices (not really an issue nowadays)
- aliasing on the edges of the resources (because now the lines are rasterized to the grid)
- colors on the edges might or might not look nice - need to check
Btw, the way you calculate length
you will run into trouble if values in points
can be negative. Ins$$anonymous$$d, I would pass the corners of the whole terrain, and create a texture the size of the whole terrain (in fact, I would do this even if I know they are always positive). This would also avoid variable resolution for the resource polygons, as you will get finer polygons if the resources are closer together, and less detailed ones if they are spread out, due to the size of your texture depending on this.
Finally, I would recommend first calculating the color for each pixel, and then using Texture2D.SetPixels32()
just once. This avoids costly resource accesses, and it is a lot more efficient function. This can be useful even if you decide to go for the vertex coloring approach (and there is a $$anonymous$$esh.colors32
function as well ;) ).
I'll diffently look into that! I'm a bit busy at the moment though.
however, a new method of generting the resources are needed. the process takes about 10 seconds for my medend laptop, which are way to much, in my opinion.
Are you using Perlin noise for generating the resources? If yes, is it your own implementation, or the one included in Unity? Either way, decreasing the number of octaves generated and/or the resolution of the noise usually helps speed up the generation process. Or you could check out this tutorial which has a fairly efficient Perlin noise algorithm implemented in it.
You could also ask a new question on how to improve your resource generation, sharing the code for it. If you do, tag me, and I'll try to help.
Your answer
Follow this Question
Related Questions
Uneven lighting with shared vertices when building mesh 1 Answer
Can and should a procedural mesh be shared between multiple GameObjects 1 Answer
Shared Meshes, do they auto-update? 0 Answers
Creating a convex MESH (not collider) 2 Answers
How can I remove redundant vertices in custom mesh? 0 Answers