Bug when dying during a roll

Hi all,

So this problem is sort of related to the agility pack, but the issue can only be reproduced with the deathmatch package. If I perform a roll with Aydan, but die during the roll, I get this error and I'm unable to equip any weapons after I respawn.
NullReferenceException: Object reference not set to an instance of an object
Opsive.UltimateCharacterController.Character.Abilities.Items.EquipUnequip.OnPickupItem (Opsive.UltimateCharacterController.Items.CharacterItem characterItem, System.Int32 amount, System.Boolean immediatePickup, System.Boolean forceEquip) (at Assets/Opsive/UltimateCharacterController/Scripts/Character/Abilities/Items/EquipUnequip.cs:210)
Opsive.Shared.Events.InvokableAction`4[T1,T2,T3,T4].Invoke (T1 arg1, T2 arg2, T3 arg3, T4 arg4) (at <d515f83de5944b65b7f28ce68e4a5f7c>:0)
Opsive.Shared.Events.EventHandler.ExecuteEvent[T1,T2,T3,T4] (System.Object obj, System.String eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) (at <d515f83de5944b65b7f28ce68e4a5f7c>:0)
Opsive.UltimateCharacterController.Inventory.InventoryBase.OnItemIdentifierPickedUp (Opsive.Shared.Inventory.IItemIdentifier itemIdentifier, System.Int32 slotID, System.Int32 amount, System.Boolean immediatePickup, System.Boolean forceEquip) (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/InventoryBase.cs:709)
Opsive.UltimateCharacterController.Inventory.InventoryBase.PickupItem (Opsive.Shared.Inventory.IItemIdentifier itemIdentifier, System.Int32 slotID, System.Int32 amount, System.Boolean immediatePickup, System.Boolean forceEquip, System.Boolean notifyOnPickup, System.Boolean spawnCharacterItems) (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/InventoryBase.cs:651)
Opsive.UltimateCharacterController.Inventory.InventoryBase.AddItemIdentifierAmount (Opsive.Shared.Inventory.IItemIdentifier itemIdentifier, System.Int32 amount) (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/InventoryBase.cs:563)
Opsive.UltimateCharacterController.Inventory.Inventory.LoadDefaultLoadoutInternal () (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/Inventory.cs:150)
Opsive.UltimateCharacterController.Inventory.InventoryBase.LoadDefaultLoadout () (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/InventoryBase.cs:245)
Opsive.UltimateCharacterController.Inventory.InventoryBase.OnRespawn () (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/InventoryBase.cs:1494)
Opsive.UltimateCharacterController.Inventory.Inventory.OnRespawn () (at Assets/Opsive/UltimateCharacterController/Scripts/Inventory/Inventory.cs:350)
Opsive.Shared.Events.InvokableAction.Invoke () (at <d515f83de5944b65b7f28ce68e4a5f7c>:0)
Opsive.Shared.Events.EventHandler.ExecuteEvent (System.Object obj, System.String eventName) (at <d515f83de5944b65b7f28ce68e4a5f7c>:0)
Opsive.UltimateCharacterController.Traits.Respawner.Respawn (UnityEngine.Vector3 position, UnityEngine.Quaternion rotation, System.Boolean transformChange) (at Assets/Opsive/UltimateCharacterController/Scripts/Traits/Respawner.cs:210)
Opsive.UltimateCharacterController.Traits.CharacterRespawner.Respawn (UnityEngine.Vector3 position, UnityEngine.Quaternion rotation, System.Boolean transformChange) (at Assets/Opsive/UltimateCharacterController/Scripts/Traits/CharacterRespawner.cs:144)
Opsive.UltimateCharacterController.Traits.Respawner.Respawn () (at Assets/Opsive/UltimateCharacterController/Scripts/Traits/Respawner.cs:176)
Opsive.Shared.Game.ScheduledEvent.Invoke () (at <447dfe34974641c19f0344babc64cad1>:0)
Opsive.Shared.Game.SchedulerBase.Invoke (Opsive.Shared.Game.ScheduledEventBase scheduledEvent, System.Int32 index) (at <447dfe34974641c19f0344babc64cad1>:0)
Opsive.Shared.Game.SchedulerBase.Update () (at <447dfe34974641c19f0344babc64cad1>:0)
To reproduce this, add the roll ability to Aydan. Then create a script that instantly kills the player like so:
C#:
public class InstantDeath : MonoBehaviour
{
    private Health m_Health;

    private void Start()
    {
        m_Health = gameObject.GetCachedComponent<Health>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.L))
            m_Health.ImmediateDeath();
    }
}
Attach it to Aydan. Then press F to roll but during the roll, press L. You'll notice that Aydan dies but respawns without any equipped weapons and the error above appears in the console. I couldn't reproduce it in the Agility pack demo scene, it only happens in the Spark scene during a deathmatch game. Any idea as to what's happening here?
 
I'm not able to reproduce it when I tried. Did you pickup any weapons? What is null on line 210 of EquipUnequip?
 
Odd, I created a new project to reproduce the error. Did you invoke the instant death during the roll animation? It won't work if you press it before or after it finishes. As for line 210, it begins with the if statement below:
C#:
if (unequipItem != null && m_ItemSetManager.IsCategoryMember(unequipItem.ItemIdentifier.GetItemDefinition(), m_ItemSetGroupIndex)) {
                                m_Inventory.UnequipItem(i);
                                EventHandler.ExecuteEvent(m_GameObject, "OnAbilityUnequipItemComplete", unequipItem, i);
                            }
I didn't pick up any weapons, I just hit play, performed the roll and hit L immediately to die instantly during the roll and that's when the error shows up.
 
I managed to get rid of the NullReferenceException by doing the following:
C#:
if (unequipItem != null && m_ItemSetManager != null && unequipItem.ItemIdentifier?.GetItemDefinition() != null && m_ItemSetManager.IsCategoryMember(unequipItem.ItemIdentifier.GetItemDefinition(), m_ItemSetGroupIndex)) {
                                m_Inventory.UnequipItem(i);
                                EventHandler.ExecuteEvent(m_GameObject, "OnAbilityUnequipItemComplete", unequipItem, i);
                            }
Then I was getting an error of a non-negative index at line 629 of ItemSetGroup, so I just added a try/catch block:
Code:
try
                {
                    newItemSet = ItemSetList[newActiveIndex];
                    if (newItemSet.Enabled == false)
                    {
                        newActiveIndex = -1;
                    }
                }

                catch
                {

                }
Now, if I respawn, I have to press the numbers to equip a weapon. Scrolling doesn't do anything until I use the numbers. Strange :unsure:
 
Actually, I think I fixed the issue. I just added a try/catch block at line 210 of EquipUnequip like so:
C#:
try
                            {
                                if (unequipItem != null && m_ItemSetManager.IsCategoryMember(unequipItem.ItemIdentifier.GetItemDefinition(), m_ItemSetGroupIndex))
                                {
                                    m_Inventory.UnequipItem(i);
                                    EventHandler.ExecuteEvent(m_GameObject, "OnAbilityUnequipItemComplete", unequipItem, i);
                                }
                            }

                            catch
                            {

                            }
I also disabled the two item slots for rolling and enabled forced uneqip during the roll. Now, whenever I die during the roll, I respawn and the weapons are automatically equipped. It's not the cleanest fix as far as the code goes, but I really don't know what's happening.
 
Top