6
\$\begingroup\$

I'm a veteran programmer, but I'm new to Unity and game programming (although I've made games in the past, but not with an engine). The first game I'm making is an exact Space Invaders clone, but I've run into a situation that Unity doesn't seem to support out-of-the-box (although I have no doubt that it can do this).

To summarize, in case anyone is not familiar with the subtleties of Space Invaders, there are 4 fortresses between the player's laser base and the aliens. If any shot of the player or the aliens hits one of the fortresses, it gets damaged. Technically, an explosion sprite is drawn wherever the hit was detected and then erased, leaving the fortress pixels missing, which actually becomes an unprotected area of the fortress. So the collision detection in the original reads the video memory, looking for fortress pixels, and detonates the shot if it encounters even a single pixel during the shot's travel.

In my version, I'm using a 2D project with the Pixel Perfect Camera, and I'm using sprites to draw everything. I've made a sprite to use for the fortresses, but I don't think that's going to work. I think I need to use a texture so I can use GetPixel() and SetPixel() on it? Sprites have a texture property, but it's read-only. I would rather not have to call SetPixel() for every pixel of the explosion, but it would be better to XOR the pixels out of the instance of the sprite, if that's possible.

How can I go about this? Can I stick with using sprites for this?

\$\endgroup\$

2 Answers 2

11
\$\begingroup\$

I would recommend separating the drawing portion of your program from the logic portion of your program. Pixels being on or off is really just an 2D array. I suggest having the logic of which parts of the fortress are damaged/standing stored in some kind of simple 2D array. Then, your drawing system would read the same array and draw appropriately, whether using sprites or textures, or some other system.

Another option could be to use 2D tilemaps. But depending on the size of the grid that might not be the best solution.

\$\endgroup\$
7
  • \$\begingroup\$ I'm mostly trying to figure out the drawing system. If I drew it with sprites, how would that work? Can Unity make new sprites on the fly? Would it be more straightforward with textures? How would that work? Etc., etc. What technologies should I be looking into, because there is a lot of stuff in Unity and the documentation doesn't explain things very well. \$\endgroup\$ Jun 13 at 16:23
  • 2
    \$\begingroup\$ "Can Unity make new sprites on the fly?" What does the API documentation tell you about that? (You can also use a RenderTexture, so you can draw explosion cavities into it with normal rendering operations on the GPU, rather than assigning it pixel by pixel from the CPU side) \$\endgroup\$
    – DMGregory
    Jun 13 at 16:29
  • \$\begingroup\$ Thanks, Cuz! I think that's what I was looking for! \$\endgroup\$ Jun 13 at 17:10
  • \$\begingroup\$ @MattGregory If the RenderTexture suggestion works out for you, please consider circling back & posting a your solution. Good luck with your game! \$\endgroup\$
    – Pikalek
    Jun 13 at 20:45
  • \$\begingroup\$ @Pikalek I will do my best. Thank you! \$\endgroup\$ Jun 13 at 22:59
5
\$\begingroup\$

(Another old-timer here, been writing games for ZX Spectrum, so I think I can feel your pain).

In modern frameworks the "actual" display is logically very far from the "logical display". There is no reasonably straightforward (like in the 80') way to go from screen pixel to "pixel within a sprite" (you can use hacks, but they will not work universally).

It's enough to think that 2D sprites are always emulated through displaying a texture on a 3D quad (there are no "sprites" at all in the GPU pipeline, there are just quads and textures) - and that there are at least two additional programs (fragment shader and vertex shader) that can affect the position of the pixels.

Also, modern frameworks tend to punish people who go against the grain - and reward programmers who try to use their facilities to the fullest.

So - I would just make each pixel of each base a separate sprite (same for explosion) (edit, for clarification: by "sprite" I mean a full-fledged GameObject). This will give me a very clean model, immediately usable with all the Unity's APIs. I actually think this is the most elegant method to solve the problem.

If I wanted to design the shape of the bases as PNG files, I would write a short script that creates the sprite instances programmatically.

EDIT: There seems to be a knee-jerk reaction, saying that "Argh! It will be slow". I don't see any reasons for it to be too slow.

Why not?

  1. With modern GPU, there's no cost of "a sprite". You only pay for:
  • logic per screen pixel (not a texture pixel! these are free),
  • logic per vertex,
  • number of vertices,
  • number of screen pixels touched (transparent or not).

Logic is same in both cases. Using sprite-per-base-pixel approach, you have more vertices, but less screen pixels (because GPU never visits "gone" pixels, and doesn't need to render transluent parts of bases, as is the case with rectangular base sprites). This is usually an optimization, not a problem! Many games employ non-rectangular sprites for performance, even though it costs more vertices.

  1. The number of "game pixels" in the bases is really small for today's standards. Bases are built afaik on a grid of 24x16 game pixels, so they might have - perhaps - 350 lit pixels in them or less. it's only around 1000 sprites in the whole game.

  2. The amount of calculations and memory management you need is the same, whether you use particle systems, sprites, custom 2D arrays of position objects, or whatever. The performance gain of using particle systems etc. comes from them being less generic and more "crippled". So yes, it makes no sense to use sprites for a simple explosion.

On the other hand, if you implement some 2D array scheme on top of particles, trying to trace them down to their screen coordinates (and further on -> coordinates on a different texture), you will lose all the performance gain and basically reimplement sprites, only without the experience and time that went into the Unity sprites.

Bottom line: the "sprite tax" that everyone mentions is connected to all the runtime management of the Unity's sprite container. It is real, and it is the reason why particle systems in Unity are not implemented on top of sprites (and the reason for the emergence of the "new" ECS). I cannot rule out that for your specific use-case, the sprite approach will not prove too slow, for some obscure reasons (judging performance is hard).

But as someone who has written and optimized games both in low-level assembly (Z80 and Motorola 6800), limited virtual machines (J2ME on feature phones) and modern Android devices - I would go with sprite-per-game-pixel first.

\$\endgroup\$
14
  • \$\begingroup\$ btw. the explosion would also be a group of one-pixel sprites. \$\endgroup\$
    – fdreger
    Jun 14 at 9:16
  • 1
    \$\begingroup\$ I would not recommend one-pixel sprites. Unity has a certain amount of overhead per object, so multiplying your discrete object count by a factor of hundreds unnecessarily can come at a significant cost — particularly on mobile where you don't want to waste battery life. \$\endgroup\$
    – DMGregory
    Jun 14 at 11:06
  • 1
    \$\begingroup\$ @fdreger For explosions I would recommend particle systems. Particles have much less overhead than sprites represented by gameObjects. \$\endgroup\$
    – Philipp
    Jun 14 at 11:33
  • \$\begingroup\$ @DMGregory I think you strongly overestimate impact of the sprites on the performance of the game (same goes for @Philipp). I have written and optimized multiple games (some of them in assembly, some of them for archtectures as old as Zilog80 or Motorola 68000; some of them for limited virtual machines found on old mobiles - in Java J2ME) - and I am ready to bet you that the impact of a couple of hundred of one pixel sprites will be negligible. Guess I will put that in the answer. \$\endgroup\$
    – fdreger
    Jun 14 at 11:58
  • 2
    \$\begingroup\$ It's not the sprites I'm concerned about, it's the GameObjects. Just pushing thousands or even millions of quads to the GPU isn't bad, if you do it through a particle system as Philipp recommends, or potentially with Unity's DOTS ECS systems. But Unity's GameObjects are heavier-weight than just a Sprite you're used to using on those older architectures. The overhead is manageable, but not something to neglect when multiplying it hundreds of times over. \$\endgroup\$
    – DMGregory
    Jun 14 at 12:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .