Adventure Creator and UCC - Custom actions for equip/unequip

nathh

New member
Hey, I'm trying to make two custom actions for Adventure Creator that tell UCC to either equip or unequip my melee weapon. I'm using the third person Opsive package. I have the weapon set to be equipped by UCC by default, that's all working as intended with attack animations etc all fine.

So, as for the custom AC actions, they are triggering fine, the weapon disappears and reappears and the player changes stance between the one for holding a melee item and one without. However I'm having some weird results with the players arms after having run either action, seems something is going wrong with the IK, they are sort of moving about further from the characters waist then normal and twist around the character when turning.

I'm guessing the code I'm using isn't telling UCC everything it needs to control stuff like the IK correctly. I've posted the two (mostly identical) scripts below but the only UCC commands I'm using really are:

inventory.AddItem(item, true, true);
inventory.EquipItem(m_ItemType, m_SlotID, true);


and then for the unequip:

inventory.RemoveItem(m_ItemType, i, 1, false);
inventory.UnequipItem(m_SlotID);


Any help would be greatly appreciated.

Here are the scripts in full (you can ignore the removeAll part):

C#:
using UnityEngine;
using System.Collections.Generic;
using Opsive.UltimateCharacterController.Inventory;


#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AC
{
    [System.Serializable]
    public class ActionEquipWeapon : Action
    {
        [Tooltip("The character that should drop the item.")]
        [SerializeField] protected GameObject m_Character;
        [Tooltip("The ItemType that the character should remove.")]
        [SerializeField] protected ItemType m_ItemType;
        [Tooltip("The Slot that the character should Unequip.")]
        [SerializeField] protected int m_SlotID;
        [SerializeField] private bool isPlayer;
        [SerializeField] public bool removeAll;

        public ActionEquipWeapon()
        {
            this.isDisplayed = true;
            category = ActionCategory.Custom;
            title = "Equip Weapon";
            description = "Equip a weapon added to the itemset";
        }


        public override float Run()
        {
            if (isPlayer)
            {
                m_Character = AC.KickStarter.player.gameObject;
            }
            var inventory = m_Character.GetComponent<InventoryBase>();

            // A single ItemType can exist in multiple slots. Drop all of the items.

            if (removeAll)
            {
                inventory.UnequipItem(m_SlotID);
                inventory.RemoveAllItems(false);
            }
            else
                for (int i = 0; i < inventory.SlotCount; ++i)
                {
                    var item = inventory.GetItem(m_ItemType, i);
                    if (item != null)
                    {
                        //inventory.AddItem(item, true, true);
                        inventory.EquipItem(m_ItemType, m_SlotID, true);
                    }
                }

            if (!isRunning)
            {
                isRunning = true;
                return defaultPauseTime;
            }
            else
            {
                isRunning = false;
                return 0f;
            }
        }


        public override void Skip()
        {
            Run();
        }


#if UNITY_EDITOR

        public override void ShowGUI()
        {
            isPlayer = EditorGUILayout.Toggle("Is Player?", isPlayer);
            if (!isPlayer)
                m_Character = (GameObject)EditorGUILayout.ObjectField("Character:", m_Character, typeof(GameObject), true);
            removeAll = EditorGUILayout.Toggle("Remove All Items?", removeAll);
            if (!removeAll)
                m_ItemType = (ItemType)EditorGUILayout.ObjectField("Item Type to remove", m_ItemType, typeof(ItemType), true);
            m_SlotID = (int)EditorGUILayout.IntField("Slot ID:", m_SlotID);

            AfterRunningOption();
        }


        public override string SetLabel()
        {
            return string.Empty;
        }
#endif
    }
}



C#:
using UnityEngine;
using System.Collections.Generic;
using Opsive.UltimateCharacterController.Inventory;


#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AC
{
    [System.Serializable]
    public class ActionUnequipWeapon : Action
    {
        [Tooltip("The character that should drop the item.")]
        [SerializeField] protected GameObject m_Character;
        [Tooltip("The ItemType that the character should remove.")]
        [SerializeField] protected ItemType m_ItemType;
        [Tooltip("The Slot that the character should Unequip.")]
        [SerializeField] protected int m_SlotID;
        [SerializeField] private bool isPlayer;
        [SerializeField] public bool removeAll;

        public ActionUnequipWeapon()
        {
            this.isDisplayed = true;
            category = ActionCategory.Custom;
            title = "Unequip Weapon";
            description = "Unequip a weapon added to the itemset";
        }


        public override float Run()
        {
            if (isPlayer)
            {
                m_Character = AC.KickStarter.player.gameObject;
            }
            var inventory = m_Character.GetComponent<InventoryBase>();

            // A single ItemType can exist in multiple slots. Drop all of the items.

            if (removeAll)
            {
                inventory.UnequipItem(m_SlotID);
                inventory.RemoveAllItems(false);
            }
            else
                for (int i = 0; i < inventory.SlotCount; ++i)
                {
                    var item = inventory.GetItem(m_ItemType, i);
                    if (item != null)
                    {
                        //inventory.RemoveItem(m_ItemType, i, 1, false);
                        inventory.UnequipItem(m_SlotID);
                    }
                }

            if (!isRunning)
            {
                isRunning = true;
                return defaultPauseTime;
            }
            else
            {
                isRunning = false;
                return 0f;
            }
        }


        public override void Skip()
        {
            Run();
        }


#if UNITY_EDITOR

        public override void ShowGUI()
        {
            isPlayer = EditorGUILayout.Toggle("Is Player?", isPlayer);
            if (!isPlayer)
                m_Character = (GameObject)EditorGUILayout.ObjectField("Character:", m_Character, typeof(GameObject), true);
            removeAll = EditorGUILayout.Toggle("Remove All Items?", removeAll);
            if (!removeAll)
                m_ItemType = (ItemType)EditorGUILayout.ObjectField("Item Type to remove", m_ItemType, typeof(ItemType), true);
            m_SlotID = (int)EditorGUILayout.IntField("Slot ID:", m_SlotID);

            AfterRunningOption();
        }


        public override string SetLabel()
        {
            return string.Empty;
        }
#endif
    }
}
 
Last edited:
Hey, bit of an update.

I have since gone through the Runtime Item Pickups tutorial on the Opsive youtube channel (a step I had overlooked before).

On my player under the Inventory (Script) component I have the weapon defined under the default loadout with an amount of 0 (to prevent the player having this item equipped on start)

I can then run over the runtime pickup for the item and the player will equip the item and use it correctly with animations, IK working etc.

If I then run an AC action calling inventory.UnequipItem(m_SlotID); the weapon disappears and you are unable to attack however the player model stays in the animation pose as if they were holding the weapon still.

After this, I can then run a separate action with inventory.EquipItem(m_ItemType, m_SlotID, true); to make the weapon reappear and re-enable attacking. After this the player is again able to attack with correct animations etc.

It seems that when calling inventory.UnequipItem the player is not reverting back to their animation state for holding no weapon.

I've noticed if I also add inventory.RemoveItem(m_ItemType, i, 1, false); alongside the UnequipItem code the player does correctly revert back to their no weapon animation states, however the EquipItem action does not work correctly afterwards (the item reappears in their hand but animations are broken and attack doesn't work).

I'm sure this is something simple I'm missing but any help would be apprecaited.

Thanks.
 
Third time's the charm.

Seems I needed to add:

using Opsive.UltimateCharacterController.Items;
using Opsive.Shared.Events;

and then for the function itself I needed to call the EventHandler stuff:

EventHandler.ExecuteEvent<Item, int>(m_Character, "OnAbilityWillEquipItem", item, m_SlotID);
inventory.EquipItem(m_ItemType, m_SlotID, true);

The only issue I have now is that if the player choose to unequip the item midway through an attack animation the character stays in the attack animation upper body state until the time for that animation has passed. Is there a way to prompt the character to quickly transition back to a default unequipped state whenever the unequip event is called?
 
Glad you are making progress Instead of calling equip or unequip directly on the inventory you should instead start the EquipUnequip ability. This will ensure the item is managed properly:

 
Top