Take the role as a small demon, tired of the underworld and one day decides to emigrate to the heaven.

Post news Report RSS Demox #5 - Destruction

For those of you who’ve either played my previous game or have seen my previous dev logs regarding Demox, it should come as no surprise that there is quite alot of blood in my games- and Demox will be no different. I’ll spend this article on trying to describe some of the methods I’m using for Demox.

Posted by on

.AVATAR DAMAGE MODELS

Starting off with character dismemberment and damage models, I spent alot of time writing the dismemberment system I used for LBKR, which at the time suited my needs however, I didn’t want to use it due to some quite annoying issues- also managing and editing the code was a pure pain. The foremost reasons for discarding this system was


  • Dismembered character models ended up with texture anomalies that could be visible when examined closely
  • Dismemberment models were generated at runtime and caused a huge load time when a new map was loaded.
  • Generated dismemberment models allocated unnecessary amounts of memory.
  • Gore fills/models would rarely connect the vertices bordering the character’s mesh, making it possible to see through the character
  • Rigging and setup of the character when implemented to the dismemberment system was complicated and quirky.

For Demox, I initially began experimenting with shaders to cut up meshes. I’ve seen this done in other games, and I currently use a similar technique to hide objects obstructing the camera view, but I never got it to work very well for characters, and there was still the issue of rendering the gore-model properly that should replace the dismembered limbs.

I soon began testing to make pre-cut meshes in Blender3D and discovered that there weren’t much performance cost at all, compared to my LBKR system it was as if comparing day and night. It is also an approach that I feel work well enough for the game.

On the downside of using this technique though is that any dismemberment event is final, the character can’t be dismembered any more afterwards. Well… technically it could, but that would require a massive amount of extra meshes and likely some mad code-nesting.

The damage models are very similar to those used in LBKR, each limb of a character is included but in Demox there’s also a damage model for non-dismembered corpses and a mid-slice damage model.

The idea behind the non-dismembered model is that damage done with bare hands or blunt weapons should not tear limbs of a character for obvious reasons, the mid-slice model is basicly the character split in half- it’s used by very specific attacks and weapons.

As mentioned in dev log #4 – Water Behaviour, corpses float in water in Demox. This also required me to add some buoyancy code for the corpses and limbs.

Tweet of LBKR dismemberment
Dismemberment Model generated for Loot Burn Kill Repeat, as seen in an old Tweet of mine.


Pre-cut meshes of the monster ”Hound”, prepared in Blender3D for Demox


And just as in LBKR, bodies can be fully gibbed ( shred to pieces ) in Demox. In LBKR this happened if the character was killed with a critical hit but for this project I use a value to determine how much additional damage was applied to the character, if it exceed a specified amount the body will be gibbed.

public float gibThreshold = -25f;    //Amount of health on death required to gib, set to negative 25 just as example
public void OnActivateCorpse( DeathInfo info ) {
    if( info.finalHealth < gibThreshold ) {
        FullyGibCorpse();   //Fully dismember the corpse if conditions are met
        return;
    }
}

.GIBS

A dead demon’s head, used as a weapon.


The gibs ( dismembered limbs of the character. ) work exactly as they did in LBKR, each damage model has a limb type and character type defined in order for the Corpse component to determine what limb to pull from the object pool.

Most limbs can be picked up in-game and used as weapons though, it was originally just a weird feature I added for fun while prototyping the game but I found this feature to fit really well with the gameplay, also it made the dismembered limbs serve a purpose for the player.

.ENVIRONMENTAL DESTRUCTION

Just as in LBKR I intend to make alot of the environment destructible, and I’m using a similar approach this time aswell. Each destructible object hold a minimum of 1 intact mesh and 1 fully destroyed copy.

When the object is destroyed, the destroyed copy will be activated- which is a collection of the objects gib models.

Some more detailed objects may also hold additional ”partially damaged” models that are enabled when the object has sustained enough damage.

.DECAL PROJECTION IMPLEMENTATION

Another aspect, adding to the havoc, is the use of decals to project blood splatter, or dirt left after an explosion etc. I will once again make a reference to my old project Loot Burn Kill Repeat, I used a similar system for projecting (some) decals in-game however, it was a third-party plugin so I didn’t have that much options to modify it to my needs. It only worked for dynamic decals, furthermore the system was not well optimized and more or less broke Unity’s occlusion culling and could lead to quite extreme frame drops. Another slightly annoying thing about it was the setup of assets. It was rather time-consuming and confusing to create and implement assets for use within the system and to apply settings.

I did like the idea of the plugin and how the decals were projected, instead of simple Quads placed at exact distance from the surface a decal should affect so I was determined to create something similar, but less complicated and more adaptable to my needs.

Goals:


  • New shader that projects a texture within a 3D volume
  • Enable projections to be animated
  • Possibility to use both with dynamic decals pulled from the object pool aswell as decals pre-positioned in the game environment

First of all, I’ve come to understand that this method of projecting decals is quite common in game development, but I weren’t sure how to actually write the shader (I’m still new to writing shaders) but after some searching around in Google-land I did find some reference material on how something like this could be achieved. So once I had created my shader the rest was relatively easy to set up!

A class was created for DynamicDecalProjections that handled animation and default behaviour of the objects, behaviour was also implemented in the object pool for dynamic instantiation of important decals such as blood splatters among other things.

For the dynamic decal projections I wanted, as mentioned earlier, the possibility to animate the projections. Either, dynamic scaling, rotation over lifetime, movement or to shift the texture offset as a 2D sprite sheet.

public void OnManagedUpdate(){
    if( !_update ){
       return;    //Don't update this instance when inactive
    }

    if( _parent != null ){
       if( !_parent.gameObject.activeInHierarchy ){
           StopManagedUpdate();
           return;    //Stop updating if the current parent is no longer active
        }

       //Parent is cached within the class and continuously updates the position
       //I avoid placing this instance within the parent object's hierarchy in case the parent 
       //object is disabled
       transform.position = _parent.position;
    }

    //Determine how much of the animation has been played
    float aDist = ( Time.time - _startTime ) * sharedData.animationSpeed;
    float fraction = aDist / sharedData.animationLength;
    
    //Animate the object
    Vector3 size = Vector3.Lerp( Vector3.zero, new Vector3( _targetSize.x, _targetSize.y, _targetSize.z ), fraction );
    
    if( sharedData.lockYSize ) {
        size.y = _targetSize.y;     //Set fixed size along y-axis, if intended
    }

    transform.localScale = size;    //Apply current scale

    if( fraction >= 1f ) {
        StopManagedUpdate();    //Stop updating, animation playback has finished
    }
}

Above is an example of how I animate the scale of the decal projection while active. Other animations are handled in similar fashion. Since the 3D volume is what is beeing animated (Except in the case of texture sheet animation, which is handled by the objects material.) it is wise to not attach colliders to the volume, since the Unity Engine does not handle scaling colliders very well, or atleast not in the version I’m using, Dunno if it has been improved after Unity5 or not.

Decal placement in editor.


I noticed quite fast however, that the textures of the decal volumes were awkwardly stretched on vertical surfaces, this is due to the volume’s uv beeing projected flat and in object space. I initially considered making the shader in a Triplanar fashion however I discovered that the issue was slightly (Not entirely though) reduced when using a sphere volume instead of a cube.

Decal using a sphere-volume, slightly reduces stretched vertical surfaces


What about implementation and use of these projections then? It’s as easy a a few lines of code which can be seen below.

DecalProjection splat = DecalManager.Current.PullDecal( DynamicDecalNames.Blood_Splatter );
    
if( splat != null ){
    splat.DeployDecal( transform.position + -info.atkDir );  //Deploy splat decal if found
}


Post comment Comments
Bazlik_Commander
Bazlik_Commander - - 312 comments

-If you are using all this ifs in one step, game will run very slowly.

Reply Good karma Bad karma+1 vote
Kakburk Author
Kakburk - - 61 comments

I can't see why it would, and the game does not run slow. None of the if-blocks in the attached code snippets refer to or call anything that is very costly at all regarding performance to use.

Reply Good karma+2 votes
booman
booman - - 3,651 comments

Yet another great developer discussion... I don't understand most of it, but I know your game is going to be good.

Reply Good karma Bad karma+2 votes
Kakburk Author
Kakburk - - 61 comments

Thanks, and thanks for the feedback! I'll try to make the next dev log easier to grasp, it's a bit tricky right now since most of the development is focused on programming but I'll keep it in mind! :)

Reply Good karma+2 votes
booman
booman - - 3,651 comments

I think its really cool that you post programming related problems, solutions and ideas... I think other programmers really like that as well. Maybe just a small summary at the begging for us gamers and then a warning about programming tech-lingo... Its your page, do it they way you want to.

Reply Good karma Bad karma+2 votes
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: