Combat Controller | Unity3D

If you want to skip the tutorial, there is a unitypackage download on my patreon

I'm the type of guy to where before I waste time reading or watching something I need to see the end result.

Keep in mind this tutorial will teach you some of the best, easiest and most useful systems for any type of combat or AI game, animations are a very important aspect to any game and without the right ones it wont look the best!

So these are free Animations I used from Mixamo.com for testing purposes, feel free to use your own animations!

So here it is:

Image for post
Image for post
Image for post
Image for post

Picking up where we left off from our last two tutorials, Locomotion Controller & Camera Controller Combining these two we should have a working, moving character controller!

Image for post
Image for post

There are a few lines of code we need to change in our older scripts to get our character to work correctly.

Camera Controller

Image for post
Image for post

We start off by opening our Camera Controller script and we remove everything except this chunk of code. That should be it for our camera controller as of now!

Player Brain

Image for post
Image for post

A little trick I learned after having to grab variables between scripts, is making a central brain. This is where we can place most of our important references and voids to keep the rest of our code clean and to avoid having to constantly pull up the same components, giving us great optimization!

So we create a new C# script and call it “PlayerBrain”.

First, we add the variables that will be used across most of our scripts such as the Animator, Health, HealthState, and some references. Since this will be our brain we will handle controlling some core functions here such as the taking damage, etc.

We also create an “isDead” bool so we can always detect when we are dead and if we die call a certain void.

Image for post
Image for post

Once all the variables are setup we can handle grabbing our references on Start(), making sure our curHealth matches our max health, then grab the Animator component.

Image for post
Image for post

GetHit() is a simple function that when called will take away from the current health, only after checking our “isDead” boolean, when this bool gets checked it will run our function and check the health. If we arent below 0, then it will continue to take away health, if we are, we will turn to the Dead health state.

Image for post
Image for post

Don’t forget to drag the Camera Root reference. This is the parent of the Camera.

Image for post
Image for post

Player Controller

Now we have some small updates to our PlayerController. First, we need to get access to our PlayerBrain, we add a new variable for PlayerBrain and on start, we search our game object for that component.

Image for post
Image for post

We add a new void that will handle rotating our player to look in the direction of the camera. This will use the “CameraRoot” from our player brain, so to access it we need to type “brain.cameraRoot”.

Image for post
Image for post

Then we just add the void after our move function.

Image for post
Image for post

With these changes, our controller should now be able to look in our camera direction and walk with no issues.

Image for post
Image for post

Combat Animator

Getting to the final part we can add combat to our controller, first, let’s update our animation controller.

Image for post
Image for post

We add two new Triggers to our controller variables, “StrikeR” and “StrikeL”. For our combat, we will be using Mouse1 & Mouse2 to add with our left and right hands.

After adding new variables we added a second layer and called it to combat. Be sure to edit the settings and make the weight 1.

Right-click and create a “Sub-State Machine”.

Image for post
Image for post

Now we need at least two animations to test, we have Punch Left and Punch Right, so we named them accordingly. Our entry comes from “Any State” and we make sure the triggers match the animation and unclick “Has Exit Time”.

You can exit them at “Exit” and this doesn’t require anything inside the parameters or conditions to work just leave it empty.

Image for post
Image for post

Damage Collider

So here comes one of the good parts, we need to create a new script and call it “damageCollider”. One of the hardest subjects I had difficulty learning was how to handle damage and impacts in a professional way.

Some say Raycasts, some say colliders, others have their own methods. Raycasts are great but they are very heavy on optimization and can easily cause lag. So the best method to go for as a base setup is colliders.

So I am going to teach you one of the best and easiest ways to handle damage to both enemies and players in the same script.

First, we create our enum to detect which hand our collider is in. Later we can add more options to fit our game needs.

We add a minDamage and maxDamage to give us full control over each individual damage and finally we create an “ignoreThis” GameObject because we don’t want to be hitting ourselves.

Image for post
Image for post

After adding the variables we need to create one more script and leave it blank, for now, create a new script and call it “AIBrain”, this will be our enemy version of PlayerBrain.

Image for post
Image for post

So we don’t have to drag our “ignoreThis” object to every damage collider we use we can instantly search for our PlayerBrain & AIBrain, stopping any future issues of hurting ourselves with our own weapon.

Image for post
Image for post

Now here is where the glory happens, we use Random.Range to give us a mix between our two damage values, then we check if our collider has either of our brain components, if it does we call the GetHit() function and watch the magic happen.

Combat Controller

We will get to the AIBrain and I know right now there is an error showing for the enemy GetHit() side. If it bothers you feel free to copy and paste the PlayerBrain GetHit() function into AIBrain, we will be going over that soon!

So let's create a new script and call it “Combat Controller”, adding the variables we need such as PlayerBrain, our references for “damageCollider[]” and some variables for timers.

Image for post
Image for post

First, make sure we grab our PlayerBrain.

Image for post
Image for post

Next, we work on our Timers, this will help us have a structured sense of time and intervals for how long it takes us to attack. We make sure to check if our “rhCD” or “lhCD” is true before counting, then if we go over our timer we stop the timer and set it back to false, meaning we can start it again.

So we only need to check for if (!rhCD) then we can attack and while it's true, that means we are under cooldown.

Image for post
Image for post

Then to control our damageColliders, we create a coroutine and call it “flashWeaponColliders”, and add our enum HandSlot as a receiver, this will check every damage collider, and check the hand type to ensure it activates every left or right-handed damage Collider, then turn it back off.

Image for post
Image for post

The last piece is calling it all, we create another function called “AttackTrigger” and check for pressing the left or right mouse button and double-checking that rhCD or lhCD isn’t activated before attacking.

If everything checks out, we call our animation trigger, call the weapon flash for the right or left hand and set our CD to true, starting our timers.

Finnally adding the Timers() and AttackTrigger() functions into Update().

Image for post
Image for post

AI Brain

Image for post
Image for post
Image for post
Image for post

For the most part, everything is the same as PlayerBrain as of now so you can almost copy and paste that script.

Image for post
Image for post

The one difference is for visual effect and we add a “GetHitFlash” coroutine which will change our enemy’s color to red and back to white(default).

Setting It Up

Image for post
Image for post

To start let’s add our GameObject of choice, for us we added a capsule collider then attached our “AIBrain” script.

Then we set up the Player’s new damage system by first adding two new GameObject cubes onto our characters rig, under both the right hand and his left hand.

Set the “Box Collider” to be a trigger, add a rigidbody to detect collisions, click “isKinematic” to stop a rigidbody from using their default forces, then add the damageCollider script to each hand and set its variables.

Image for post
Image for post

Finally, attach the CombatController script, drag your damageColliders & set your timers!

Image for post
Image for post

You can see the final result here!

Image for post
Image for post
Image for post
Image for post

Links:

Patreon (Download):
https://www.patreon.com/posts/42485017

Twitter:
https://twitter.com/GooSlimeDevs

Written by

Indie Game Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store