Skip to main content

Weapon Based Animation Set

✍ Last Updated : September 8, 2022

🚪 Prequisite Knowledge (Optional)

Describe Initial Knowledge that reader need to know before reading this article

❓ Key Question / Problem / Issue

How to change player’s animation based on equipped weapon

✅ Expected Output/Definition of Done]

A system where player’s animation can be changed by changing weapon

🎁 Resulting Solution

To assign player different animation set when they change weapon, we can use AnimatorOverrideController and assign it into player’s animator.RuntimeAnimatorController

For more details on AnimatorOverrideController

Animator Override Controllers

We don’t have to assign all override animation, only the one that need to override the base animations.

AnimatorOverrideController from BaseAnimator

Male Sword Animator Override Controller

Male Sword Animator Override Controller

Male Bow Animator Override Controller. Note that we don’t assign any override since the base animator is already using Male Bow animations

Male Bow Animator Override Controller. Note that we don’t assign any override since the base animator is already using Male Bow animations

To store animatorOverrideControllers in weapon, we can use a list which contains WeaponAnimationData inside Weapon class.

using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class WeaponAnimationData
{
    public PlayerData.Race race;
    public PlayerData.Gender gender;
    public AnimatorOverrideController   animatorOverrideController;
    [HideInInspector] public AnimationClipOverrides       animatorClipOverrides;
}

public class Weapon : MonoBehaviour
{
    public enum Type{SWORD, AXE, BOW, GUN, STAFF, TOME, TWO_HANDED_SWORD};

    [SerializeField] Type type;
    [Tooltip("Is the weapon held in right hand?")]
    [SerializeField] bool rightHandEquipped = true;

    [SerializeField] List<WeaponAnimationData> weaponAnimationDatas;

    public WeaponAnimationData GetWeaponAnimationData(PlayerData.Race race, PlayerData.Gender gender) => weaponAnimationDatas.Find(o => o.gender == gender && o.race == race);

    public Type weaponType => type;
    public bool righthand  => rightHandEquipped;

    // Start is called before the first frame update
    void Start()
    {
        
    }
}

With race and gender defined in PlayerData class

public class PlayerData : MonoBehaviour
{
    public enum Race {HUMAN, DRIAD, ELVEN}
    public enum Gender {MALE, FEMALE, UNKNOWN}
    public Race     race;
    public Gender   gender;
}

Assigning each character’s race and gender to weapon prefab

Every possible character’s race and gender need to have their own animator override controller assigned

Bow prefab with assigned animator override controllers for male and female human

Bow prefab with assigned animator override controllers for male and female human

Sword prefab with assigned animator override controllers for male and female human

Sword prefab with assigned animator override controllers for male and female human

Then when equipping/switching weapon, first we need to get matching weaponAnimationData from the equipped weapon then assign the weaponAnimData animatorOverrideController into character’s animator.runtimeAnimatorController, and the character animator will have a new set of animations according to the equipped weapon

		WeaponAnimationData SwitchWeapon(Weapon weapon)
    {
        if(weapon.weaponType == currentWeapon?.weaponType)
            return weaponAnimData;
            
        if(currentWeapon)
        {
            currentWeapon.gameObject.SetActive(false);
            weaponPool.Add(currentWeapon);
        }
        
		//Check if weapon pool already have weapon with the same weapon type
        currentWeapon = weaponPool.Find(o => o.weaponType == weapon.weaponType);
        if (currentWeapon == null)
        {
            currentWeapon = Instantiate<Weapon>(weapon);
            //Equip weapon in corresponding hand
            if (currentWeapon.righthand)
                currentWeapon.transform.SetParent(rightHand);
            else
                currentWeapon.transform.SetParent(leftHand);

            //Reset weapon transformation
            currentWeapon.transform.localScale = Vector3.one;
            currentWeapon.transform.localEulerAngles = Vector3.zero;
            currentWeapon.transform.localPosition = Vector3.zero;
        }
        else
            currentWeapon.gameObject.SetActive(true);

		//Get corresponding weaponAnimationData
        weaponAnimData = currentWeapon.GetWeaponAnimationData(playerData.race, playerData.gender);

        //Initialize AnimationClipOverrides
        if(weaponAnimData.animatorClipOverrides == null)
            weaponAnimData.animatorClipOverrides = new AnimationClipOverrides(weaponAnimData.animatorOverrideController.overridesCount);

        //Reset layer weight
        for(int i = 0; i < animator.layerCount; i++)
            animator.SetLayerWeight(i, 0);

        animator.runtimeAnimatorController = weaponAnimData.animatorOverrideController;
        return weaponAnimData;
    }