Weapon Based Animation Set
✍ Last Updated : September 8, 2022
🚪 Prequisite Knowledge (Optional)
UploadDescribe InInitial ProgressKnowledge 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
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 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
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;
}