I’m getting a null reference exception from the line of code inside the start menu. Don’t know why this is happening, could it be due to the abstract class? Even though I have a class deriving from it? Doesn’t make sense…
public abstract class NPC : MonoBehaviour
{
protected PlayerStats player;
[SerializeField]
protected float interactRadius;
public delegate void OnInteract();
public event OnInteract OnInteractWith;
private void Start()
{
player = FindObjectOfType<PlayerStats>().GetComponent<PlayerStats>();
}
}
Well, firstly, the line in question is redundant. FindObjectOfType() already returns the PlayerStats component to you. That’s its job. Calling GetComponent() on that will either return the same thing right back to you, or throw a NilReferenceException.
Since it’s doing the latter, that means that it’s not finding an object of that type. Check the objects in your scene hierarchy, and make sure you really have what you think you have.
Ah — you shouldn’t try to override or shadow the magic Unity methods like Start and Update in a class hierarchy. It doesn’t work.
Instead, for each such magic method, you must implement it in only one place in each class lineage. So either implement it in the base class, or implement it in each of the subclasses. But don’t try to do both.
Ah okay, the reason was I had the Start function in the derived class for a delegate event. Also I’ll edit the code tags in I couldn’t actually find them when I was posting the code.
Not in my experience, it doesn’t. Unity is looking them up by name — in such a case you have two implementations with the same name/signature. You’d expect the subclass one to get invoked but (again, in my testing at least), that doesn’t reliably happen.
Two implementations with the same name but contained in different classes. Now I can see the likelihood of failure being high if the base class has a virtual method and the invoking class does not have its own implementation, so maybe that’s what you experienced?
OK, time for me to back off and admit I was wrong. Maybe.
Thinking more carefully, I think what I experienced is actually what sober minds would expect it to do: it invokes only the method in the subclass. The problem may have been that we’re just so conditioned to thinking of these magic methods as reliably invoked. But this behavior opens a way for a subclass to break a base class, even if the base class method was not declared virtual.
So for example, you make a base class, grab some references you know you’re going to need in Awake or Start, and do your thing. Then 7 months later you derive a subclass that just needs to add a little behavior, and it happens to also have some references to grab, so you implement Awake or Start there too… and suddenly all the base-class code is throwing NOEs because its Awake/Start never runs.
Fairly obvious once you see it, but a bit of a gotcha, and one from which the base class really can’t protect itself (which is unusual in C#, where normally only virtual methods can be overridden).
The need for subclasses in Unity doesn’t come up very often for me — I tend to favor a very shallow class hierarchy, with interfaces. But the above has bitten me once or twice, and so now when I do need to use subclasses, I’m very careful to define which level of the hierarchy is going to implement each magic method. Or I make them virtual, but ensure the subclass calls the base class implementation. Or I implement them only in the base class, and have that call a virtual method that subclasses are welcome to override.