Hi, I'm trying to remake MS-DOS game tunneler You can play it here. In the game, you control a tank that digs tunnels as it goes. I decided to make the dirt from individual particles(Objects). Each one has its own collider and the tank destroys them as it moves along. It works but it's really intensive for my pc. The FPS drops even when the game is built. I'm a complete newbie and I realized this is not the way to go. I thought maybe creating a mesh instead but I'd like to know what's the best way to go around doing this? If anyone experienced can suggest a better solution it'd be much appreciated.
Advice on best design
No, no. You don't need to have objects you collide with. You just have one array of pixels. On a modern computer you can be wasteful and use a full byte per pixel. Then you move your tanks and your projectiles and do collision detection by looking up values in the array.
Hello Gyro1! I think that would be a really good approach if you only had a few game objects, but adding that many colliders to that many game objects will make the game run slower. My suggestion is to get rid of the colliders attached to your pixel objects and simply destroy (or disable) the pixel game objects when the main character gets close to them. What you will have to do is detect the main characters position relative to the pixel. When the main character is within a certain distance of the pixel, the pixel object is disabled. I've included a script that I think will work. Good luck!
Wow. Thanks. Looks like you both agreed on the same solution. I really appreciate the code as well. Thanks again.
Hey Gyro1,
I think that have so many colliders it always make your game run slow, specially running on browsers.
What you can use instead is to work directly with the dirt image, getting the pixels using GetPixel32 (https://docs.unity3d.com/ScriptReference/Texture2D.GetPixels32.html ) and then modify them as you go along with the tank. Instead of colliders you have to check for the pixels next to the tank and change their color to something neutral using SetPixel (https://docs.unity3d.com/ScriptReference/Texture2D.SetPixel.html )
We did something similar in one of our games that was about earthquakes and the performace is awesome!
Good luck!
Our games about to be launched:
https://www.facebook.com/warintheskies
https://www.facebook.com/mathordice
Thanks for your help. I've tested your suggestions and here are some of my findings:
Removing colliders from individual dirt particles didn't have much impact on the performance. The problem is rendering so many objects. Even with sprite 1x1px and filtermode set to point and collider removed the majority of resources goes to Render TransparentGeometry. If I want to use individual objects I must make them bigger so there is less of them(Proven to work).
I've also tried simply checking the position of the tank and the projectiles and then changing a texture of a quad respectively. The quad has its own collider and whenever something enters it removes the necessary pixels. This works quite well, however, I can only use colliders for entry then I have to define collision with code. So If I have collider with a complicated shape it's quite useless. I've tried using Collider2D.OverlapPoint but it didn't work out very well.
void RemovePixels(Collider2D coll){
for (float y = 0f; y < 10f; y+=0.10f) {
for (float x = 0f; x < 10f; x+=0.10f) {
if (coll.OverlapPoint (new Vector2 (x + 0.05f, y + 0.05f))) {
SetPixel (Mathf.RoundToInt(x*10),Mathf.RoundToInt(y*10),blankcolor); //sets pixel on a defined position to transparent color
if(coll.tag == "Projectile")Destroy (coll.gameObject);
}
}
}
}
Maybe it's just bad implementation but this code was very intense for the CPU. Probably because it was under void OnTriggerStay2D
I ended up using this method:
void RemovePixels(Collider2D coll){
SetPixel (Mathf.RoundToInt(coll.transform.position.x*10),Mathf.RoundToInt(coll.transform.position.y*10),blankcolor);
}
It works and the performance is great but as I mentioned the shape of the collider is lost and has to be defined manually. If somebody has any Idea how It'd possible to determine a whether a pixel is overlapping a collider I'd love to hear it. Thanks for the help so far.
There are a lot of functions in unity under Physics2D that you can try , i rarely used these myself but it might do the trick for you:
https://docs.unity3d.com/ScriptReference/Physics2D.html
The Overlap functions(there are quite a lot of these based on different shapes) would probably answer your question , also seems there are a lot of Cast functions you can look into and see if they are good for your implementation.
P.S.: I would personally look into generating the map as a single image and do what Aleid Cross suggested(this way you render 1 object at all times instead of 1 million), having a collider on each pixel is bound to be a performance nightmare.