Bug: Perspective Monitor Null Renderer

Woods

New member
UCC version: 3.0.15

When my character dies the perspective monitor is throwing a blocking null ref from the renderers in TryUpdateDeathMaterials().

Its probably something we caused since we only want a specified number of weapons on a character at a time and we need them to be fully destroyed when unequipped so we have a custom inventory that does this, but the perspective monitor doesn't clean up the renderers list when its removed.

C#:
        private bool TryUpdateDeathMaterials(bool fromDeathEvent)
        {
            // Ensure no first person weapons are equipped before enabling the third person objects.
            if (m_CharacterLocomotion.FirstPersonPerspective) {
                for (int i = 0; i < m_Inventory.SlotCount; ++i) {
                    if (m_Inventory.GetActiveCharacterItem(i) != null) {
                        // If an item is still equipped then the material shouldn't be switched until after it is no longer equipped.
                        if (fromDeathEvent) {
                            EventHandler.RegisterEvent<CharacterItem, int>(m_GameObject, "OnInventoryUnequipItem", OnUnequipItem);
                        }
                        return false;
                    }
                }
            }

            // All items are unequipped. Update the renderers.
            for (int i = 0; i < m_Renderers.Count; ++i) {
                var invisibleObject = false;
                if (m_DeathVisibility == ObjectDeathVisiblity.AllInvisible) {
                    invisibleObject = m_CharacterLocomotion.FirstPersonPerspective;
                } else if (m_DeathVisibility == ObjectDeathVisiblity.ThirdPersonObjectDetermined) {
                    var thirdPersonObject = m_RendererThirdPersonObjects[i];
                    invisibleObject = m_CharacterLocomotion.FirstPersonPerspective &&
                        (thirdPersonObject != null && !thirdPersonObject.FirstPersonVisibleOnDeath && !thirdPersonObject.ForceVisible);
                }
                //Throws null here
                m_Renderers[i].materials = (invisibleObject ? m_InvisibleMaterials[i] : m_OriginalMaterials[i]);
            }
            return true;
        }

There is probably two approaches to fix and make the perspective monitor more error proof.

The easy: Check if the renderer is null before trying to set the materials, this should work for any use-cases and no extra overhead. This is what I have done for now.
The robust: Remove renderers from the list when they are unequipped, this might not be feasible for some use-cases if items are unequipped but still supposed to be visible.
 
Are you able to tell me how to reproduce the error? What specifically is your inventory doing that is causing this error to occur? I'd like to reproduce it so can come up with an appropriate fix.
 
I am pretty sure its because we dont use object pooling to spawn character items. I overrode it in Inventory so that its instantiated and destroyed completely. This is so that changes by our gun powerup system don't carry over when the player drops it and picks up the same gun later.

C#:
        //Override to remove pooling from character items so that they get completely destroyed when unequipped
        //This ensures that any upgrade values do not carry over
        public override CharacterItem SpawnCharacterItem(CharacterItem characterItemPrefab, IItemIdentifier itemIdentifier)
        {
            var character = m_GameObject;
            // Spawn the item under the character's ItemPlacement GameObject.
            if (m_ItemPlacement == null)
            {
                Debug.LogError($"Error: ItemPlacement doesn't exist under the character {character.name}.");
                return null;
            }

            var additionalPoolKey = character.GetInstanceID();
            var previousActiveState = characterItemPrefab.gameObject.activeSelf;
            characterItemPrefab.gameObject.SetActive(false);
            var itemGameObject = Instantiate(characterItemPrefab.gameObject, Vector3.zero, Quaternion.identity, m_ItemPlacement.transform);
            itemGameObject.name = characterItemPrefab.name;
            itemGameObject.transform.localPosition = Vector3.zero;
            itemGameObject.transform.localRotation = Quaternion.identity;

            var instancedCharacterItem = itemGameObject.GetComponent<CharacterItem>();
            instancedCharacterItem.Initialize(itemIdentifier);

            characterItemPrefab.gameObject.SetActive(previousActiveState);
            itemGameObject.SetActive(true);

            OnCharacterItemSpawned(instancedCharacterItem);

            return instancedCharacterItem;
        }

Inventory settings for remove and destroy are all enabled
1696405479465.png
 
Top