- Home /
How to optimize 2d generated map
I was making a mapgame, and i stumbled upon an issue I has suspected would come. My very primitive method of generating every pixel makes the game super slow.
My current system loads a map from a txt file in this form :
0 1 1 0
0 1 0 1
0 0 1 0
basicaly every pixel is saved as a value, those values are the nlater used to generate countries. The problem here is that Im generating every pixel as a new image that is also a child of the parent country object.
A serious problem arose when I noticed that changing colors of all the child pixels in my script makes the game lag for 5 seconds. So I decided to post this problem here.
I basicaly need to know if there is a way to generate an image from scratch, I know it is possible to generate meshes but dont know anything about Images. Or perhaps you could suggest some options in the editor to me that could help with faster rendering.
Edit : Removing all white pixels tripled the framerate to 45, but it still takes 1+ seconds to change color for the countries (no matter their size)
A quick google search ("generate image using code c#") gave me these two results: https://stackoverflow.com/questions/47458100/create-image-in-c-sharp and https://blog.aspose.com/2020/06/27/create-images-and-graphics-using-csharp-or-vb.net/ Isn't this exactly what you are looking for? Hope this helps.
Answer by CycloneWhale · Aug 24, 2021 at 12:34 AM
Hi, what exactly do you mean when you say you're generating each pixel as a new image? If each pixel is it's own gameObject, then the game will certainly not be able to handle it. I would suggest maybe using the tilemap system, but it can get pretty finnicky.
You could also look into generating a mesh for the entire world, as you said.
Either way you will most likely have to create some kind of chunk system, and there are plenty of good tutorials on youtube, but they will most likely not be tailored to your current situation, so you will have to do a lot on your own. But researching chunk systems would be a pretty good start.
Will look more into tilemaps as you say. The reason why I initialy decided that i need each country to be an individual image (or a collection of them, like right now) is beacouse the countries are UI buttons, they are meant to be clickable. Thanks for answearing. I still need to know more about the color changing problem. Lowering the number of pixels seemed to work a lot in this matter suggesting that my current code scans all gameobjects for some reason.
void ColorChange(Material material)
{
foreach (Transform child in transform)
{
child.gameObject.GetComponent<Image>().color = material.color;
}
}
Do you perhaps know if This color changing function can be improved in preformance ?
Edit : Im investigating this issue specificaly so i might not actually need any help
I think if you're looking for performance, than realistically the only way that I could think of, would be generating a mesh for each country. You can use the OnMouseDown() function to detect when you click on it.
Answer by Llama_w_2Ls · Aug 24, 2021 at 03:54 PM
What about creating the texture manually? If you know the dimensions of your image, you can create a texture of that size, and set the individual pixel colors of the texture quite quickly. (Even faster if you use SetPixels or SetPixels32).
var texture = new Texture2D(width, height);
var color = Color.white;
// Set all pixels to white (could change to use an array of colors to determine each individual pixel color)
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
texture.SetPixel(x, y, color);
}
}
// Applies all changes to the texture
texture.Apply();
Then, create a sprite from the texture and set it as the sprite of a sprite renderer. For example:
var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height, Vector2.zero);
// This object will now display the map texture
mySpriteRenderer.sprite = sprite;
I've been using this technique for my terraria clone. It works pretty well for small chunks of data, but texture.Apply is the expensive method here. Use it sparingly. Hope that helps @CrusadingBanana
Answer by roman_sedition · Aug 26, 2021 at 08:19 AM
Create texture via setting pixel colours like @Llama_w_2Ls said. After the initial map is created, you only need to use SetPixel for any deltas. If the base map is just the grey and white, you should write that file instead of recreating it procedurally all the time, then the deltas are only just iterating through the black and the red pixels. Then apply the texture after those red and black pixels have been set.
Use GetPixel(x,y) based on your mouse position when you click on the image instead of having to create buttons.
Call appropriate method if the colour returned by GetPixel() matches whatever your criteria is.
Your answer
Follow this Question
Related Questions
Not getting shadows for dynamic objects 0 Answers
What's a good draw call count? 2 Answers
How can I speed up assigning a mesh to a MeshCollider? 2 Answers
Android Best performance 1 Answer
Need optimizing tips for mobile third person shooting game. 2 Answers