Home Artists Posts Import Register

Content

Overview

Note: Initially, I've posted this article a few months ago, for "Unity Capsule" tier patrons only. However, people have asked me about the effects before and this will come in handy as something I can refer them to, in the future!

In this post, I want to give a more detailed outline of how the damage effects in the game are put together.

The final effect is a combination of...

  • Damage Models
  • Mesh Manipulation
  • Particle Effects
  • Shader Animation

So, let's have a look!


1. Damage Models

Models like this are a classic way of displaying damage: You have several versions of the same object, with each showing a different level of destruction. All you need to do then, is swap models based on the object's health.

In addition to the damage models, I also have "debris" meshes: Larger chunks that will be spawned as physical objects, when damage models are swapped.

Having these elements make the destruction a bit more dynamic, and also helps make the visual switch from one damage model to another less jarring. 


2. Mesh Manipulation

This is the most complicated (but also most exciting) part of the damage effects: Manipulating the meshes at runtime!


2.1 Manipulating Vertex Positions

My damage system is fairly complex: Every time damage is dealt, it comes with a number of extra parameters and properties, such as damage strength, position, size (i.e. taken from the hit box of hands or feet) and direction. From these parameters, I calculate a positional offset and a a spherical fall-off, which are applied to all vertices of a mesh and deform it accordingly.

These calculations are pretty intense, since they need to be performed on many thousands of vertices, every time a mesh is deformed. This is especially true, since a single object (i.e. a building) will usually consist of more than one deforming mesh: Different floors, fire exit stairs, etc.

To improve performance, I'm utilizing Unity's C# Job System to handle the mesh manipulation: This way, the game will take advantage of multi-threading to perform the calculations a lot more efficiently.


2.2 Manipulating Vertex Colors

In addition to positions, damage will also manipulate a mesh's vertex colors: Every time damage is applied to a part of the mesh, the affected vertices' colors are modified so their alpha value is increased. I'm then using this alpha value, to drive the opacity of a damage texture, in the shader:

This is what the damage textures look like for the cars, to give an impression of crumpled sheet metal:


2.3 Configuration

Per damageable object, I have one DamageEffectsPlayer component that is in charge of translating damage to deformation (as well as play shader animations, more about that later). One of the cool things it allows me to do, is assign a DamageEffectsSettings asset: This ScriptableObject holds a bunch of settings/parameters for how to display the damage. It allows me to share common configurations between different objects...

This way, a car will not deform the same way a building does: I can give objects different physical properties or rigidness, depending on what config I use. The parameters are a bit finicky, but they can be a lot of fun to play around with, haha!


3. Particle Effects

They are particle effects. Nothing too special going on here.

Although, I do have a couple of helper scripts that tweak particle effects, in certain ways:

My DamageEffectScaler script will modify certain parameters of a particle effect, corresponding to the size of the damage that has been dealt. That means an impact effect will not look the same when it was spawned from characters of two wildly different sizes, for instance.

And for cars I use another fun helper script that will match the color of the particles to the main color of the car. Just a little thing, but it adds to the believability!


4. Shader Animation

Last but not least, my custom building shader comes with a couple of handy parameters that allow me to animate a shockwave or ripple, whenever a building is hit.

Not gonna lie, it's a bit of a mess and far from perfect, but it's definitely "good enough" to help sell the effect! I mean, look at that juicy wobble.

From a practical perspective, it adds a little extra motion, to both hide the damage model swap and visually smoothen the mesh deformation: It really helps tie everything together.

The DamageEffectsPlayer component is in charge of animating each deformable mesh's materials. Similar to the mesh deformation, it uses the DamageEffectsSettings to easily re-use setups between different objects, i.e. to configure how wobbly they are.


5. Conclusion

This should give you a pretty good overview, of how the damage effects are put together.

There are still a bunch of parts and systems I want to streamline and refactor, but overall I'm very happy with how things work and look!

Because of the modular approach, it should be pretty simple to enable/disable certain elements of the effects, if necessary. This could be the case on older hardware, which might not able to handle excessive mesh deformation, for instance. So far the performance of the effects has looked very promising, but I still need to run more tests on older/weaker machines, to be sure.


Thank You!

I hope you have enjoyed this post – if you have any questions, just let me know!

Comments

No comments found for this post.