UIS AmmoData and Weapon Fire Infinite Loop

Zaddo

Active member
The code is going into an infinite loop when firing a weapon. This started happening when I created the AmmoData attribute for the weapon in UIS and mapped this on the weapon in UCC. I was following the training video on this.

I am not sure what I did wrong here. I have copied the call stack below, I hope this can help point at what is going wrong.

Below is a screen capture of the ShootableAction on this weapon. I am guessing one of these modules should not be there or has a bug?

1679489516873.png


Code:
     Void Opsive.Shared.Events.EventHandler:ExecuteEvent (Object, String)+0x47 at :-1    C#
     Void Opsive.UltimateInventorySystem.Core.ItemObject:ForceChangeEvent ()+0xe at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\ItemObject.cs:[82:13-82:84]    C#
     Void Opsive.UltimateInventorySystem.Core.Item:NotifyAttributeChanged (AttributeBase)+0x44 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\Item.cs:[537:17-537:53]    C#
     Void Opsive.UltimateInventorySystem.Core.AttributeSystem.AttributeCollection:AttributeChanged (AttributeBase)+0x15 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\AttributeSystem\AttributeCollection.cs:[608:13-608:51]    C#
     Void Opsive.UltimateInventorySystem.Core.AttributeSystem.AttributeBase:NotifyChange ()+0xe at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\AttributeSystem\AttributeBase.cs:[281:13-281:50]    C#
     Void Opsive.UltimateInventorySystem.Core.AttributeSystem.Attribute`1:NotifyChange ()+0x2 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\AttributeSystem\Attribute.cs:[190:13-190:33]    C#
     Void Opsive.UltimateInventorySystem.Core.AttributeSystem.Attribute`1:SetOverrideValue (AmmoData, Boolean, Boolean)+0xdd at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\AttributeSystem\Attribute.cs:[182:13-182:28]    C#
     Void Opsive.UltimateCharacterController.Integrations.UltimateInventorySystem.InventoryAmmoDataClip:SetAmmoData (AmmoData, Boolean)+0xa1 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Integrations\UltimateInventorySystem\Scripts\ItemActionModules\InventoryAmmoDataClip.cs:[124:17-124:66]    C#
     Void Opsive.UltimateCharacterController.Integrations.UltimateInventorySystem.InventoryAmmoDataClip:NotifyClipChange ()+0x2c at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Integrations\UltimateInventorySystem\Scripts\ItemActionModules\InventoryAmmoDataClip.cs:[247:13-247:45]    C#
     Void Opsive.UltimateCharacterController.Integrations.UltimateInventorySystem.InventoryAmmoDataClip:ReloadClip (Boolean)+0xf5 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Integrations\UltimateInventorySystem\Scripts\ItemActionModules\InventoryAmmoDataClip.cs:[326:13-326:32]    C#
     Void <>c:<ReloadClip>b__87_0 (IModuleReloadClip, Boolean)+0x2 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\ShootableAction.cs:[464:90-464:111]    C#
     Void Opsive.UltimateCharacterController.Items.Actions.CharacterItemAction:InvokeOnModulesWithType (Boolean, Action`2)+0x59 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\CharacterItemAction.cs:[353:21-353:41]    C#
     Void Opsive.UltimateCharacterController.Items.Actions.ShootableAction:ReloadClip (Boolean, Boolean)+0x28 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\ShootableAction.cs:[464:17-464:113]    C#
     Void Opsive.UltimateCharacterController.Items.Actions.Modules.Shootable.GenericReloader:ReloadItem (Boolean)+0x40 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\Modules\Shootable\ReloaderModule.cs:[738:13-738:95]    C#
     Void <>c:<ReloadItem>b__95_0 (IModuleReloadItem, Boolean)+0x2 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\ShootableAction.cs:[571:86-571:107]    C#
     Void Opsive.UltimateCharacterController.Items.Actions.CharacterItemAction:InvokeOnModulesWithType (Boolean, Action`2)+0x59 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\CharacterItemAction.cs:[353:21-353:41]    C#
     Void Opsive.UltimateCharacterController.Items.Actions.ShootableAction:ReloadItem (Boolean)+0x4b at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Scripts\Items\Actions\ShootableAction.cs:[571:13-571:109]    C#
     Void Opsive.UltimateCharacterController.Integrations.UltimateInventorySystem.InventoryItemAmmo:SetConsumableItemIdentifier (IItemIdentifier)+0x81 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Integrations\UltimateInventorySystem\Scripts\ItemActionModules\InventoryItemAmmo.cs:[224:13-224:47]    C#
     Void Opsive.UltimateCharacterController.Integrations.UltimateInventorySystem.InventoryItemAmmo:SetItem (Item)+0xe8 at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Integrations\UltimateInventorySystem\Scripts\ItemActionModules\InventoryItemAmmo.cs:[187:13-187:92]    C#
     Void Opsive.UltimateCharacterController.Integrations.UltimateInventorySystem.InventoryItemAmmo:SetItem ()+0x1d at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateCharacterController\Integrations\UltimateInventorySystem\Scripts\ItemActionModules\InventoryItemAmmo.cs:[148:17-148:44]    C#
     Void Opsive.Shared.Events.InvokableAction:Invoke ()+0x6 at :-1    C#
     Void Opsive.Shared.Events.EventHandler:ExecuteEvent (Object, String)+0x47 at :-1    C#
     Void Opsive.UltimateInventorySystem.Core.ItemObject:ForceChangeEvent ()+0xe at C:\UnityProjects\DeadFear3Upg\DeadFear3\Assets\Opsive\UltimateInventorySystem\Scripts\Core\ItemObject.cs:[82:13-82:84]    C#
 
Last edited:
Here is a visual of the infinite loop.

I don't understand why SetConsumableIdentifier is calling ReloadItem?

1679485788395.png

One thing I noticed when debugging is that in InventoryDataAmmoClip, the ClipRemainingCount keeps toggling between 49 and 1 between iterations. The clip size is set to 50.

1679488400627.png

My best guess is that this has something to do with the Clip module. So here are screen shots of the Clipmodule config and the AmmoData config:

1679489572641.png

Note, clip remaining was zero. But I was guessing that this might be part of the problem, so I tried changing it to 50. But both 0 and 50 make no difference.
1679488539602.png
 
Last edited:
I spent another night debugging. I cannot work out how to fix this. I don't understand the logic well enough to know how each of these modules integrates with all UIS & UCC systems. I don't know if this will help, but I have updated my notes on what is happening, including the entry point for the infinite loop.

Note, aside from some debug log output, this is all unmodified code.

Please help.

1679576711197.png
 
Thank you so much for the very detailed bug report.
I am looking at the code. and I'm wondering if the InventoryItemAmmo that you are using is incorrectly setup.
It's as if you are using an ItemDefinition for the ammo that is not a UIS itemdefinition. Is it possible you somehow linked an ItemIdentifier that is not of type "Item" (from UIS)?

Could you try ticking the "Use Ammo Data" option so that it can get the Ammo ItemDefinition from the AmmoData?
1679583414297.png
 
Thanks @Sangemdoko, that pointed me to a work around that works :)

The "Use Ammo Data" was checked on. So, I tried unchecking this, and just using "Ammo Item Definition" to map to the Bullet. This worked :)
I confirmed my Assault rifle item definition had the AmmoData correctly setup for the correct bullet. I can only conclude that for some reason, something is not working in my project when retrieving the Item Definition from AmmoData? I have to go to work now, but I will try to debug this tomorrow, to see if I can work out what is happening.

Rather than doing lots of screen captures. I did a quick video of the setup. Hopefully this cover everything. I did miss the CharacterItem, so I just did a screen shot for that.


1679604610427.png
 
I think I found the problem. I had mutable turned on for the Consumable Item Category. In V2 this did not affect weapon fire and consuming bullets. Turning off mutable avoids the infinite loop.

I have this turned on so that I can set durability on consumables, like food items, so they can go rotten over time. I have customised UIS so that these items are still stackable, averaging the durability when stacked.

I understand this is an edge case and most people won't have a mutable/non-unique item. But it might be nice to include a warning for this, otherwise this scenario is very hard to debug. Perhaps in InventoryItemAmmo. Something like this works:

C#:
        /// <summary>
        /// Set the ItemIdentifier which can be consumed by the item.
        /// </summary>
        /// <param name="itemIdentifier">The new ItemIdentifier which can be consumed by the item.</param>
        public virtual void SetConsumableItemIdentifier(IItemIdentifier itemIdentifier)
        {
            if (m_AmmoItem == itemIdentifier) { return; }

            var previousAmmoIdentifier = m_AmmoItem;
            m_AmmoItem = itemIdentifier as Item;
            m_AmmoItemDefinition = new DynamicItemDefinition(m_AmmoItem?.ItemDefinition);

            // Add back the previous consumable item to the inventory.
            var itemInfo = new ItemInfo(previousAmmoIdentifier, ShootableAction.ClipRemainingCount);
            m_AmmoItemCollections.AdjustItem(itemInfo);
            // Set the ClipRemaining to 0 so the new consumable item can be loaded from the inventory.
            ShootableAction.MainClipModule.EmptyClip(false);

            NotifyAmmoChange();

            // Avoid infinite loop. Ammo cannot be mutable
            if (((Item)itemIdentifier).IsMutable)
            {
                Debug.LogError($"Ammo cannot be mutable. This will result in an infinite loop. Please fix {((Item)itemIdentifier).name}");
                return;
            }

            ShootableAction.ReloadItem(false);
        }
 
Last edited:
That's a great find! Thank you for letting us know.
I'll add it to the list of things to investigate.

If the ammo for your weapons don't need to change over time, I would recommend splitting Consumable and Ammo categories. This way you can have rotten consumable foods, but your bullets can be immutable.
 
Top