Drawing decals

The last couple of weeks I have been working on getting decals to be drawn on my 2D levels. Decals are nothing more than sprites(pictures) that are drawn on an object. 3D games use this a lot, for example you can draw blood decals when a player gets shot in an shooter so that you see the blood splatters on the ground. But it is also used for when you shoot an object, this will show bullet holes on the object that is shot. These are nothing more than sprites that get drawn on that object on the position where you hit it.

Blood splatter effect without decals.

I wanted to incorporate this idea in my game because I think it’s a real cool effect for a 2D game. I got the original idea from Super Meat Boy where you leave blood marks on everything you touch. The idea, in that game, is that you are a peace of meat that leaves blood traces everywhere you walk. In my game however, I only wanted blood splashing around when you die. As a proof of concept I created a laserbeam that kills the player when he hits it, upon dying you explode and when the blood hits the walls blood traces are visible. I also wanted the blood traces to stay on the walls when you die, this is also something from SMB that I really liked.

I tried a couple of different things to get this to work in Unity. Well, showing the blood splatters wasn’t so hard. I just created a new object containing a blood splatter sprite everytime a blood particle hit a wall. But there was a problem when I did it that way. Collision checks are done every frame, so one blood particle can register dozens of hits in it’s lifetime. My blood splatter particle effect has a maximum of 50 particles, this resulted in creating +/- 1300 objects every time the player died. Because of this, the framerate would drop significantly when the player died a couple of times. After dying around 20 times the framerate would be 20fps, when initialy, before dying, it would be 525fps.

To counteract this behaviour I tried to find ways to create less objects. But this also resulted in slowdowns. I tried checking everytime I wanted to create a decal object if there was one in that spot already, but when there were a lot of objects already this slowed the game down a lot too.

So what I came up with in the end was adding an additional grid(tilemap) over my whole level. Now when a blood particle hits, for example, a wall I translate the coordinate of the hit into the correct position inside the tilemap and draw my blood decal(tile) there. This way there is only one object for all decals, the tilemap, which draws all the blood decals every frame and to my surprise, this is done extremely fast!!

 

Tilemap of the level used to place the walls/ceilings etc.

 

Tilemap used to draw decal tiles is added on top of the other tilemap.

 

The decals are now drawn on the decal tilemap.

But there was one downside in doing it this way, since it is a static tilemap it can only draw decals on the walls/ceilings/floors of my level. But I also want to have blood splatters shown on objects that can move/rotate. So I thought, what if I add a tilemap to every object that I want to draw decals on? If the tilemap is put on the object it will move/rotate together with the object itself. I was worried that this would affect the performance since I don’t know how Unity handles the moving/rotating of say 10+ grids in one level, but to my surprise this is also really fast!!

This is the tilemap which is added to the box which now rotates together with the box.

And the end result now looks like this:

Decals are now also drawn on rotating objects!

Standard