Creating a Melee Combat System in Unity

Melee combat in games refers to close-range fighting where players use weapons or their own bodies to attack enemies. This type of combat is crucial in many game genres, including action-adventure, role-playing, and fighting games. Melee systems add depth to gameplay, providing players with a visceral and immersive experience that differs from ranged combat. Implementing a melee system in Unity involves scripting, animation, and collision detection to ensure smooth and responsive combat mechanics.

In this article, we will guide you through the steps to create a basic melee combat system in Unity, suitable for beginners. We will cover setting up the player character, creating melee attack animations, scripting the attack logic, and implementing collision detection to register hits.

Importance of Melee Combat in Games

Melee combat is essential in certain types of games for several reasons:

  • Immersive Gameplay: Close-quarters combat can create intense and engaging gameplay experiences, making players feel more connected to the action.
  • Variety: Adding melee combat to a game that primarily features ranged combat provides variety and keeps gameplay fresh and interesting.
  • Character and World Building: Melee combat can reflect the character's abilities and the game's setting, enhancing the overall narrative and world-building.
  • Strategic Depth: Players must consider positioning, timing, and weapon choice, adding layers of strategy to the gameplay.

Setting Up the Player Character

  1. Create a New Project: Open Unity and create a new 3D project.
  2. Add a Player Character: Import or create a 3D model for your player character. You can use free assets from the Unity Asset Store if needed.
  3. Set Up the Animator Controller: Create an Animator Controller to handle the player's animations. Import the necessary animations (idle, walk, attack) and set up the animation states and transitions.

Creating Melee Attack Animations

  1. Import Attack Animations:
    • Download or create attack animations for your character.
    • Import these animations into Unity and add them to your Animator Controller.
  2. Set Up Animation Transitions:
    • Create transitions between the idle, walk, and attack states in the Animator Controller.
    • Use parameters such as 'isAttacking' to control these transitions.

Scripting the Attack Logic

We will write a C# script that handles the player’s melee attack logic, including triggering the attack animation and detecting hits.

  1. Create a New Script:
    • Right-click in the Project window, select 'Create -> C# Script', and name it 'PlayerCombat'.
  2. Script Implementation:
    • Double-click the script to open it in your preferred code editor (e.g., Visual Studio Code).
    using UnityEngine;
    
    public class PlayerCombat : MonoBehaviour
    {
        public Animator animator;
        public Transform attackPoint;
        public float attackRange = 0.5f;
        public LayerMask enemyLayers;
        public int attackDamage = 40;
        public float attackRate = 2f;
        private float nextAttackTime = 0f;
    
        void Update()
        {
            if (Time.time >= nextAttackTime)
            {
                if (Input.GetButtonDown("Fire1"))
                {
                    Attack();
                    nextAttackTime = Time.time + 1f / attackRate;
                }
            }
        }
    
        void Attack()
        {
            animator.SetTrigger("Attack");
    
            // Detect enemies in range of the attack
            Collider[] hitEnemies = Physics.OverlapSphere(attackPoint.position, attackRange, enemyLayers);
    
            // Damage them
            foreach (Collider enemy in hitEnemies)
            {
                enemy.GetComponent().TakeDamage(attackDamage);
            }
        }
    
        void OnDrawGizmosSelected()
        {
            if (attackPoint == null)
                return;
    
            Gizmos.DrawWireSphere(attackPoint.position, attackRange);
        }
    }
  3. Assigning the Script:
    • Attach the 'PlayerCombat' script to your player character.
    • Set the 'Animator', 'Attack Point', and other fields in the Inspector.

Implementing Enemy Logic

  1. Create an Enemy Script:
    • Right-click in the Project window, select 'Create -> C# Script', and name it 'Enemy'.
    • Double-click the script to open it in your preferred code editor.
    using UnityEngine;
    
    public class Enemy : MonoBehaviour
    {
        public int maxHealth = 100;
        int currentHealth;
    
        void Start()
        {
            currentHealth = maxHealth;
        }
    
        public void TakeDamage(int damage)
        {
            currentHealth -= damage;
    
            if (currentHealth <= 0)
            {
                Die();
            }
        }
    
        void Die()
        {
            // Add death animation or effects
            Destroy(gameObject);
        }
    }
  2. Assigning the Script:
    • Attach the 'Enemy' script to your enemy objects.

Adding Visual and Audio Feedback

Enhancing the melee combat experience with visual and audio feedback is crucial for player satisfaction. Here’s how to do it:

  1. Add Hit Effects:
    • Create particle effects for when an attack hits an enemy.
    • Instantiate these effects in the 'Attack' method when an enemy is hit.
  2. Add Sound Effects:
    • Import sound effects for the attack and hit impacts.
    • Use the 'AudioSource' component to play these sounds during attacks and when enemies are hit.
    using UnityEngine;
    
    public class PlayerCombat : MonoBehaviour
    {
        public Animator animator;
        public Transform attackPoint;
        public float attackRange = 0.5f;
        public LayerMask enemyLayers;
        public int attackDamage = 40;
        public float attackRate = 2f;
        private float nextAttackTime = 0f;
        public AudioClip attackSound;
        public AudioClip hitSound;
        private AudioSource audioSource;
        public GameObject hitEffect;
    
        void Start()
        {
            audioSource = GetComponent();
        }
    
        void Update()
        {
            if (Time.time >= nextAttackTime)
            {
                if (Input.GetButtonDown("Fire1"))
                {
                    Attack();
                    nextAttackTime = Time.time + 1f / attackRate;
                }
            }
        }
    
        void Attack()
        {
            animator.SetTrigger("Attack");
            audioSource.PlayOneShot(attackSound);
    
            // Detect enemies in range of the attack
            Collider[] hitEnemies = Physics.OverlapSphere(attackPoint.position, attackRange, enemyLayers);
    
            // Damage them and play hit effect
            foreach (Collider enemy in hitEnemies)
            {
                enemy.GetComponent().TakeDamage(attackDamage);
                audioSource.PlayOneShot(hitSound);
                Instantiate(hitEffect, enemy.transform.position, Quaternion.identity);
            }
        }
    
        void OnDrawGizmosSelected()
        {
            if (attackPoint == null)
                return;
    
            Gizmos.DrawWireSphere(attackPoint.position, attackRange);
        }
    }

Conclusion

Implementing a melee combat system in Unity can significantly enhance the gameplay experience, particularly in genres where close-quarters combat is essential. By following this guide, you can create a basic melee system, complete with animations, attack logic, and collision detection. As you become more comfortable with Unity, you can further refine the system to fit your needs.