It's the Small Things that Matter


The Problem: Something is Missing...

The past week I focused on just fixing and improving existing features and mechanics. There were a few problems with enemies. One was that their weapon collider wasn't behaving the same way the player's was. The colliders would always be "on" and checking for collisions regardless of if the enemy was attacking or not, meaning the player could just walk into the enemy's arm that had the weapon collider and the player would take damage without the enemy attacking. This was because the enemy was using a different weapon object than the player character. There was another problem when the enemy was damaged, their damaged animation would be overwritten by the attack animation because the blackboard would keep telling the AI to attack so the damaged animation would never get a chance to play.

I also spent this past week trying to improve combat feedback. Because the enemy's weapon was different from the player it didn't have the functionality for spawning particle systems when an attack lands, which meant there wasn't very much visual feedback. Another problem with the combat feedback is when the player attacks the enemy. A single attack will often register as multiple overlap events causing damage to be applied to the enemy multiple times.


The Solution: It's a Bird, It's a Plane, It's Base Character!

Since a lot of the enemy's issues were already solved and accounted for in the player character, I decided to make a Base Character class that the enemy character and player character classes could inherit from, rather than duplicating the same functionality across multiple objects. The base character class is made up of some properties and functions I had in the player character. The most important was the reference to a MeleeWeapon object and two functions to play animation montages. The MeleeWeapon object allowed for spawning the hit effect when the player is hit as well as turning collision on and off for the enemy weapon. The two animation functions were defined as such:

float ABaseCharacter::PlayHighPriorityAnimMontage(UAnimMontage* HighPriorityMontage, float InPlayRate, FName StartSectionName) 
{     
    float Duration = 0.0f;      
    UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();      
    if (!AnimInstance->Montage_IsPlaying(HighPriorityMontage))         
        Duration = PlayAnimMontage(HighPriorityMontage, InPlayRate, StartSectionName);      
    return Duration; 
}  
float ABaseCharacter::TryToPlayAnimMontage(UAnimMontage* AnimMontage, float InPlayRate, FName StartSectionName) 
{     
    float Duration = 0.0f;      
    UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();      
    if (!AnimInstance->IsAnyMontagePlaying())         
        Duration = PlayAnimMontage(AnimMontage, InPlayRate, StartSectionName);      
    return Duration; 
}

The first function prioritizes playing the montage that is passed in. If the passed in montage is not playing, it plays it. The second function tries to play the passed in montage if no other montage is playing. These were useful for prioritizing being damaged and dodging while making actions like attacking low priority.

A few other things I did this past week to improve combat were adding a hit pause and fixing the issue where multiple overlaps were being registered. To fix the problem with multiple overlaps I add the actor that was hit to an ignore list, which is just an array of actors. If that same actor triggers an overlap event during that same attack, it will be ignored and the function will just return. The list is then emptied at the end of the animation notify state that is used to turn the weapon collider on and off. Finally, to add the hit pause, I slowed down time to about 1% for a very short moment. One-on-one, it's not very noticeable, however in a crowd of enemies it's very noticeable and I feel it adds a nice feeling of impact when attacking, but we'll have to see.

Get Lucifer's Hordes

Leave a comment

Log in with itch.io to leave a comment.