- Home /
Missing Reference with an Interface
Hey all, thanks for having a look:
I'm getting a MissingReferenceException on prevActiveControl
in the following chunk of code
if(prevActiveControl != null)
{
if(prevActionControl is IUIListObject)
{
if(prevActiveControl.gameObject.transform.parent != null) //<-Error happens here
{
//Do code
}
}
}
Full error:
MissingReferenceException: The object of type 'UIListItemContainer' has been destroyed but you are still trying to access it.
For clarity prevActionControl is an interface reference of type IUIListObject, and at the time of the error is holding (or should be anyway) a reference to an UIListItemContainer object which implements the IUIListObject interface.
I double checked on the MSDN and null checks should function as expected with Interface references, so I'm a bit perplexed by how it can end up "missing" on the same frame that I verified it was still there. Any thoughts?
Thanks again
The gameObject that has the script containing UIListItemContainer is being destroyed.
Yes, I gathered this much from the error. The null check should detect that scenario, but it is not. Any thoughts on why?
Would you $$anonymous$$d posting the whole script? It could be another part of the code I'm not looking at. Some people can figure things out without seeing the whole code, but I'm better at it when I have a whole script to actually test out in Unity.
Unfortunately this is happening in a business partner's plugin and I can't share it. Following after you original thought, perhaps I have a flawed understanding of the null check. $$anonymous$$y assumption was that as the script is attatched to the gameobject, that it would be destroyed at the same time as the gameobject, and thus the null check would suffice. If this is not actually the case, (perhaps there is a one frame gap between an object's destruction and the removal of it's component scripts) then I may need to do an explicit check on the gameObject as well?
I was going to suggest checking if the gameObject is null INSTEAD of the script. Say you check if the gameObjetc is null, then check if the gameObject contains the component with if(GetComponent().. I'll give a short example of what I'm thinking. Say gameObject go has script script1.
GameObject go;
void Update()
{
go = GameObject.Find("go");
if(go != null)
{
if(go.GetComponent<script1>())
{
//Code
}
}
}
Agreed, I actually appreciate that these are all comments. As long as it doesn't have an answer people will still look at it. I'd much rather have 20 comments than 20 incorrect/half answers
$$anonymous$$d = blown - ignore this answer, but I want to leave it so the commentary below remains...
If you have a reference to an object, and there is the potential for that object to be destroyed, you need to explicitly set the references to null, or provide some other method to deter$$anonymous$$e whether or not the object still exists.
e.g.
Destroy(prevActiveControl);
prevActiveControl = null;
...
if (prevActiveControl != null)
{
}
A reference isn't set to null for you when the object is destroyed.
If I define the gameObject in update, and it is destroyed, it returns null... Say I'm watching a gameObject from a script, and as long as it exists, aka isn't null, the code does its work. Then I can make an else statement for if it IS null, and that part of my code works once that gameObject is destroyed. I also know defining a gameObject in update isn't the best thing to do though lol.
@Dave_Carlile That seems counter intuitive. It's a reference, not a copy. If the source data is deleted, the reference -should- return null if accessed. In my use case the object is being destroyed by a scene-load (as I expect it to) and I have no easy way to set the reference to null manually.
DEFINITELY, a GameObject var DOES return null when it is empty. other members do too, such as transform, etc
http://docs.unity3d.com/Documentation/ScriptReference/Object-operator_Object.html
Answer by Memige · Jul 23, 2013 at 10:42 PM
Found the answer! It is a combination of my original misgivings and Dave's instinct. Interfaces do not share Monobehaviour's ability to handle Object destruction out of the box. This link goes over the details, (Checking For Destroyed Components using Interface references) but for anyone running into this, here is the answer:
You must cast your interface variable as a Component in order for an != null check to return false after the gameObject has been destroyed
so my original code has been modified to this:
if((Component)prevActiveControl != null)
{
if(prevActionControl is IUIListObject)
{
if(prevActiveControl.gameObject.transform.parent != null)
{
//Do code
}
}
}//<-Runs perfectly
Call out to @clunk47 and @Dave_Carlile and @seth_bergman for their help in tracking this down.
Okay, I will, was nervous about accepting my own, but as long as someone else agrees, I'll do so :)
Always accept your own answer if it is the resolution to your issue, then others will know where to look :D
Answer by amirebrahimi · Nov 24, 2016 at 04:28 AM
The fix above didn't work for me, but it's possible that it stopped working during the 5.x era. Here's a workaround that I found:
Equals(obj, "null")
Your answer
Follow this Question
Related Questions
Camera in Interface 1 Answer
How to create an agenda or timetable system? 1 Answer
GUI.Label positioning for many device resolutions 1 Answer
Flash inside Unity 3 Answers