MissingReferenceException: The object of type ‘Armor’ has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
I think it may have something to do with the fact that the inventory is a static list, such as this declaration:
private static List<Item> _inventory = new List<Item>();
I am just trying to access the Armor component to get the damage ratings. I do the above check to make sure
the object is an Armor and not a Weapon or just an Item. Can anyone tell me how to get this done please?
I should mention that I am trying to access the inventory from a script that is on an inventory slot button.
I am trying to get the rating values to turn them on and off on mouse overs. The first code lines that I
posted are from the script attached to the slot.
I don’t think it’s because of the static list. If it says it’s been destroyed, then it probably was. In one line you are comparing a tag, in the other you are getting a component and those are two completely different things. The armor in the GetComponent would have to be a type, usually a script. Is your script named armor? Do you have a tag named Armor?
The script component that I am trying to access is of the type Armor and it resides on an inventory object that is
of the type Item. In other words, PlayerCharacter.Inventory[0] may have either an Armor or a Weapon script
attached to it and both derive from Item.
I need to confirm that the Item is an Armor or a Weapon so I can get either the armor class or weapon damage
values from the components. Since the Item can also be a book or some other type of object, I can’t just grab the
Armor or Weapon components without checking if they exist first. That is where I am running into the error.
The two different statements (compare tag, null check) represent the two approaches I have taken to check if I
can access the component, which is what wolfhunter said I should do. The thing is, I know this object isn’t destroyed
because I can access general values from it’s Item component.
What I suspect is that because the inventory is a static list, it can’t be found in the object hierarchy at runtime.
I don’t know if I have to change my approach to the inventory or if it is possible to drill down to the Armor or Weapon
component after checking it it is either of the two.
Yes, I created an “Armor” and a “Weapon” tag to get past the error since it happened when I used the != null approach.
It’s a static list, the game objects, however are not static. If you don’t specify them to DontDestroyOnLoad(), then they will be destroyed when the scene changes, thus leading to your missing reference.
No scene transitions happen before this object is checked and as I mentioned,
the object exists because I can grab its name and value from its base component.
If it derives from item, it has to be recast to Armor. When it’s in the item list, it’s an item. I don’t understand your code though, so maybe that doesn’t apply.
In my Creation methods, the Items are cast as either Armor or Weapon (I think… Could this be the issue?).
A switch that checks what type to make takes an Item and adds another component to it.
Then it calls the Create() to set up some variables in the appropriate component and returns
the item as either Armor or Weapon. Since it is returned as those types, I think they are cast.
The switch looks like this:
GameObject tempItem = new GameObject();
Item item = tempItem.AddComponent<Item>();
// Determine type for temp Item
switch( type ) {
case ItemType.MeleeWeapon: // Melee Weapon
item = tempItem.AddComponent<Weapon>();
item = CreateMeleeWeapon();
break;
case ItemType.Armor: // Armor
item = tempItem.AddComponent<Armor>();
item = CreateArmor();
break;
and the Creation methods handle casting like these:
// CREATE MELEE WEAPON
private static Weapon CreateMeleeWeapon() {
GameObject tempMeleeWeapon = new GameObject();
Weapon meleeWeapon = tempMeleeWeapon.AddComponent<Weapon>();
GameObject.Destroy(tempMeleeWeapon);
// Set some variables
return meleeWeapon;
}
// CREATE ARMOR
private static Armor CreateArmor() {
GameObject tempArmor = new GameObject();
Armor armor = tempArmor.AddComponent<Armor>();
GameObject.Destroy(tempArmor);
// Set some variables
return armor;
}
Why are you destroying the GameObject? Pretty positive it’ll go through and destroy it’s components as well…remember, all objects are put on the heap and, unless you deep copy to another object, are handled by references. So tempArmor still references the armor component, which is also referenced by item. So if tempArmor destroys it, then it’s destroyed for everything it’s attached to.
Everything from the temp object was copied over so it was safe to delete it and work with the new object.
The evidence that it should work is that I have access to all the Weapon component’s variables inside
this method.
UnityEngine.Object.Destroy() doesn’t appear to instantly destroy an object and it’s components, instead it would appear that it either waits until the end of the frame (or somesuch), or possibly just sets the GC to pick it up on the next collection. Either way, it’s going to eventually go through and destroy everything attached to that object.
On the new object, I have access to all the variables of the component that I added to the temp object
before copying and deleting. Therefore, I don’t believe that it is deleted and the object is correctly
cast as Weapon or Armor when it is returned.
The error you are getting, however, is stating that the object has been destroyed. Like I said, Destroy doesn’t immediately destroy the object (DestroyImmediate would though). And without doing a deep copy, all you are copying are references.
Why don’t you have CreateMeleeWeapon() and CreateArmor() take a gameobject as a parameter and just directly attach to the game object you want it attached to? In addition to the destroy issue, you’re generating a bunch of temporary data that has to get garbage collected…which can wind up killing framerate eventually. By having them take the gameobject to attach to as a parameter, you’d fix both issues.
A better question would be why these have to be Components attached to GameObjects in the first place. You’re storing a list of objects but in order to create those objects you make a new, empty GameObject, attach a Component to it, Destroy the GameObject (which will make that Component reference resolve to null), and then return the Component. Seems convoluted, and ultimately what you end up with is a list of null references.
A second, also good question, is why this has to be stored in a static list.