- Home /
How to correctly access interface of a subclass?
I'm running into the following situation, and I have absolutely no idea what's going on. By all of my understanding of OOP, this is not how this should work.
public interface ValueHolder{
bool ValueHeld();
void SetHeldValue(bool newVal);
}
public class BaseThing : Monobehavior, ValueHolder {
private bool sneakyValue = true; //Private. Not serialized.
public bool ValueHeld(){
return sneakyValue;
}
public void SetHeldValue(bool newVal){
sneakyValue = newVal;
}
}
public class UniqueThing : BaseThing { } //There are several of these. Performs unrelated tasks.
//Doing some code things
GameObject thingObj = Instantiate(PrefabWithUniqueThingOnIt);
thingScript = thingObj.GetComponent<UniqueThing>();
thingStript.SetHeldValue(false);
Debug.Log(thingObj.GetComponent<UniqueThing>().ValueHeld()); //False, as expected
Debug.Log(thingObj.GetComponent<BaseThing>().ValueHeld()); //True??
Debug.Log(thingObj.GetComponent<ValueHolder>().ValueHeld()); //Also True??
The problem is that I want to have a single function that can get several variations of UniqueThing and check their ValueHeld. When I set the value on BaseThing and get it using ValueHolder, I do get the expected result, so I expect the problem is more related to inheritance than interfaces.
The more I think about this, the more I think this is a Unity bug. I can't think of any good reason for this behavior. Isn't the exact point of interfaces to allow the thing I am trying to do?
Answer by Bunny83 · Jun 21, 2019 at 05:52 PM
This is certainly not a Unity bug. The most likely explanation for this is that you actually attached a UniqueThing as well as a BaseThing to the same object. GetComponent will return the first instance it finds on the object. When you do GetComponent<UniqueThing>()
and there's only one UniqueThing component on the gameobject it will return that one. However GetComponent<BaseThing>()
as well as GetComponent<ValueHolder>()
would match both classes. So you probably have a "BaseThing" component besides the UniqueThing component attached.
It's not 'certainly' anything yet.
I should not have both instances on the object. Earlier in the Doing some code things
bit, I do AddComponent(UniqueThing)
and call a function inside BaseThing
that ends with Destroy(this)
. Is removing the component asynchronous?
Yes, the destruction of objects is asynchronous. Try this code:
void Start ()
{
var rb = gameObject.AddComponent<Rigidbody>();
Destroy(rb);
var test = GetComponent<Rigidbody>();
if (rb == test)
Debug.Log("Same");
}
This will print "Same". If you use DestroyImmediate ins$$anonymous$$d of Destroy this would not happen. However you should use DestroyImmediate with care.
Is there a good way to prevent GetComponent
from finding destroyed components? I'm fine with doing the destruction at the end of the frame for the sake of efficiency, so I would say Getting destroyed components is the undesired behavior. DestroyImmediate
sounds like it is a solid hit to speed (and is followed by a cloud of fearmongering), and I need to do this a lot, quickly.