Project Status At this Point

I have to admit I followed along for quite awhile, working ahead at times, but keeping pace and implementing things as per the instruction. But as tend to happen with me, I had some Ideas to “improve” things(at least to my taste). So I might have worked ahead of the Weapon HitBox and Damage Dealing sections… But mainly it was becuase I already had similar systems in place already.
So I what I did was implement a system that will allow dynamic changes the weapon, all animations, Combo Data, and Attack Data for those combos;
Here is the system in Action:

I started by creating a ComboData class.

[System.Serializable]
public class ComboData 
{
    [FoldoutGroup("Combo Attack Data"), SerializeField] AttackData[] attackComboData;

    public AttackData[] AttackComboData { get => attackComboData; }
}

I then replaced the AttackData in PlayerStateMachine.CS with a ComboData currentComboData,
and created a new public method: PlayerStateMachine.SetComboData(ComboData comboData).

public void SetComboData(ComboData comboData)
    {
        this.currentComboData = comboData;
    }

The biggest changes happened with WeaponHandler.cs.
I wanted a system where the player could hold items/weapons in either hands, or both hands.
so I created a public enum.

public enum WeaponHand { RightHanded, LeftHanded, DualHanded };

Then I created two new transforms, a lh_WeaponTransform (lefthand), and a rh_WeaponTranform (rightHand), on my prefab.
I created a Transform on WeaponHandler.cs for each of my weaponTransforms, with the right hand being the cast enum for the right hand (int)WeaponHand.RightHanded, and the left hand being cast for the left (int)WeaponHand.LeftHanded; I can then use the enum later to enable and disable the corresponding weapon colliders, with WeaponHandler.WeaponColliders;

I then created a WeaponType :MonoBehavior base class which, among other things, has a public ComboData, that can then be used to Set the stateMachine.SetComboData() by the weaponHandler, when a Weapon is Equipped;
The WeaponType also Holds an animatorOverRideController, which allows the animations to be overridden based on the weapon the player is holding (I currently have a punching weapon, which does a R,L,R combo, and a Pistol weapon which does a single PistolWhip animation, but changes the locomotion animations to be holding the pistol in a ready pose)

I also added a new PlayerRunState, which is basically a copy of the PlayerFreeLookState with some paramters changed, such as the movement speed. I did this by Adding a 3rd animation to the FreeLook blend tree, specifically a walk animation, and set the PlayerFreeLookState to set the “FreeLookSpeed” to .5 instead of 1, then in the PlayerRunState I set that speed to be 1, allowing for the 3rd animation to be triggered;

my WeaponHandler.cs

using UnityEngine;
using Sirenix.OdinInspector;
using System;

public enum WeaponHand { RightHanded, LeftHanded, DualHanded };

public class WeaponHandler : MonoBehaviour
{
    public event Action<ComboData> OnWeaponEquipped;

    [Title("Weapon Handler", "Hit Box Logic", TitleAlignments.Centered)]
    [FoldoutGroup("Weapon Colliders"), SerializeField]
    Transform lh_WeaponTransform;
    [FoldoutGroup("Weapon Colliders"), SerializeField]
    Transform rh_WeaponTransform;

    [BoxGroup("Current Weapon"), SerializeField, Tooltip("Serialized for debugging purposes")]
    WeaponType currentWeapon;

    [FoldoutGroup("Collider Transforms"), ShowInInspector]
    Transform[] weaponColliderTransforms;

    [FoldoutGroup("Collider Transforms"), ShowInInspector]
    Collider[] weaponColliders;

    WeaponType testingSwapWeapon;
    WeaponType initialWeapon;

    int arrayLength = 0;

    private void Awake()
    {
        weaponColliderTransforms = new Transform[GetArrayLength()];

        if (lh_WeaponTransform != null)
        {
            weaponColliderTransforms[(int)WeaponHand.RightHanded] = rh_WeaponTransform;
        }
        if (lh_WeaponTransform != null)
        {
            weaponColliderTransforms[(int)WeaponHand.LeftHanded] = lh_WeaponTransform;
        }


    }
    private void Start()
    {
        initialWeapon = Resources.Load<WeaponType>("Weapons/pf_Fist - RLR");
        testingSwapWeapon = Resources.Load<WeaponType>("Weapons/pf_Pistol_PistolWhip");
        EquipWeapon(initialWeapon);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            if (currentWeapon == initialWeapon)
            {
                EquipWeapon(testingSwapWeapon);
            }
            else
            {
                EquipWeapon(initialWeapon);
            }
        }
    }
    private int GetArrayLength()
    {

        if (lh_WeaponTransform != null)
        {
            arrayLength++;
        }
        if (rh_WeaponTransform != null)
        {
            arrayLength++;
        }
        return arrayLength;
    }

    public void EnableWeaponCollider(WeaponHand attackingHand)
    {
        //weaponColliderTransforms[(int)attackingHand].gameObject.SetActive(true);
        weaponColliders[(int)attackingHand].enabled = true;
    }
    public void DisableWeapon(WeaponHand attackingHand)
    {
        //weaponColliderTransforms[(int)attackingHand].gameObject.SetActive(false);
        weaponColliders[(int)attackingHand].enabled = false;
    }

    public void EquipWeapon(WeaponType weapon)
    {
        WeaponType rh_Weapon;
        WeaponType lh_Weapon;
        foreach (Transform transform in weaponColliderTransforms)
        {
            if (transform.childCount == 0)
            {
                continue;
            }
            GameObject child = transform.GetChild(0).gameObject;
            Destroy(child);
        }

        currentWeapon = weapon;

        if (currentWeapon.WeaponHand == WeaponHand.DualHanded)
        {
            rh_Weapon = Instantiate(currentWeapon, rh_WeaponTransform);
            lh_Weapon = Instantiate(currentWeapon, lh_WeaponTransform);
            SetWeaponColliders(2);
            weaponColliders[0] = rh_Weapon.WeaponCollider;
            weaponColliders[1] = lh_Weapon.WeaponCollider;

        }
        if(currentWeapon.WeaponHand == WeaponHand.LeftHanded)
        {
            lh_Weapon = Instantiate(currentWeapon, lh_WeaponTransform);
            SetWeaponColliders(1);
            weaponColliders[0] = lh_Weapon.WeaponCollider;

        }
        else if(currentWeapon.WeaponHand == WeaponHand.RightHanded)
        {
            rh_Weapon = Instantiate(currentWeapon, rh_WeaponTransform);
            SetWeaponColliders(1);
            weaponColliders[0] = rh_Weapon.WeaponCollider;
        }

        

        OnWeaponEquipped?.Invoke(currentWeapon.ComboData);


    }

    void SetWeaponColliders(int numOfColliders)
    {
        weaponColliders = new Collider[numOfColliders];
    }

}

my WeaponType.cs

public abstract class WeaponType : MonoBehaviour
{
    [Title("Weapon", "Weapon Data", TitleAlignments.Centered), SerializeField] protected string weaponName; 
    [TabGroup("Weapon Info"), SerializeField] protected Transform weaponPrefab;
    [TabGroup("Weapon Info"), SerializeField] protected bool isDualHanded;
    [TabGroup("Weapon Info"), EnumToggleButtons, SerializeField] protected WeaponHand weaponHand;
    [TabGroup("Weapon Info"), SerializeField] protected Collider weaponCollider;
    [TabGroup("Weapon Info"), SerializeField] protected int damage;

    [TabGroup("Combo Data"), SerializeField] protected ComboData comboData;

    [TabGroup("Combo Data"), SerializeField] protected AnimatorOverrideController animatorOverrideController;


    

    public string WeaponName { get => weaponName; }
    public ComboData ComboData { get => comboData; }
    public Transform WeaponPrefab { get => weaponPrefab; }
    public bool IsDualHanded { get => isDualHanded; }

    public WeaponHand WeaponHand { get => weaponHand;}

    public AnimatorOverrideController AnimatorOverrideController { get => animatorOverrideController; }
    public Collider WeaponCollider { get => weaponCollider;}
    public int Damage { get => damage;}

    Animator animator;

    private void Awake()
    {
        animator = GameObject.FindWithTag("Player").GetComponent<Animator>();
    }
    private void OnEnable()
    {
        animator.runtimeAnimatorController = animatorOverrideController;
    }





}

I am actually incorporating the State Machine we are creating into an existing project of mine. Its based off an Idea I had for a game jam that I did not complete, but I did take the time since the jam to finish out the majority of what I had wanted to do for the jam. In the meantime I had the idea to add a 3rd person platforming section to the game… The theme idea I had is a spoof on Indiana Jones, hence the Explorer, and the Desert Car Chase, but here is the ProtoType I have so far…

1 Like

Also, I have been using Sirenix’s Odin Inspector, and while it definitely not necessary, and It took sometime to figure out how it all works, I do have to say it is very helpful in organizing the inspector. And, I know it does a whole more that I’m not using yet.




1 Like

Privacy & Terms