- Home /
Inheritance suddenly stopped working.
I have an enemy parent with the following code:
public class Enemy_Parent : MonoBehaviour
{
[SerializeField]
public Player _player;
public int _resistance;
public int _level;
void Start()
{
_player = GameObject.Find("Player").GetComponent<Player>();
print(_player);
}
public enum _enemy_resistance
{
Fire_1 = 0,
}
}
When I run it, the console displays "Player", which confirms that "Player" is found. Additionally, since it is a serializedfield the object also populates in the inspector under the enemy parent script.
I then have an enemy creature with the following code.
public class Creature : Enemy_Parent
In the Start function I have:
void Start()
{
print(_player);
}
However, Null is displayed in the console. Since I typed "public class Creature : Enemy_Parent" shouldn't my creature enemy automatically see it. Before I went to sleep last night everything was running fine. Today I launch Unity and I'm receiving errors because "_player" is null.
Answer by IINovaII · Jan 09, 2020 at 08:18 PM
When you call void Start()
from Creature, the line _player = GameObject.Find("Player").GetComponent<Player>();
from Enemy_Parent's Start function won't get called.
Personally, I prefer to keep Start() completely empty within base classes since they won't get called by inherited classes. If you really want to call Start() of base class, set base class' Start() to a virtual method. It would look like this;
virtual void Start()
{
_player = GameObject.Find("Player").GetComponent<Player>();
print(_player);
}
Start function in your inherited class would look like this then.
override void Start()
{
base.Start();
print(_player);
}
Make sure base.Start();
comes before any code so that whatever code you have in your parent class runs first.
Answer by evildead9000 · Jan 09, 2020 at 10:30 PM
Then is may be best to keep Enemy_Start empty. I may try the override, but my understanding of parent/child is lacking. I thought I was doing okay too!
Since Creature is a child of Enemy_Parent, I do not need to code: private Enemy_Parent _enemy_parent within Creature. Is that correct?
I was basically trying to store _player once, so it could be accessed from any enemy child I add. If I add it to all enemy child Starts by overriding and accessing from parent, would that be considered overkill? Or even if I call upon an Enemy_Parent function from a child to obtain _player.
I'm not sure how to move forward in the most efficient way. It is possible to store _player like I planned? Any guidance would be appreciated.
Well, it's pretty situational. Sometimes, it's best to make it a virtual method, sometimes not. There's always multiple ways to do the same thing. But in your case, you can set the Start()
method to virtual and override it in children components. Like I mentioned in my answer, make sure to add base.Start();
within the overridden method. What this does is that, it will ALSO call the Start()
method from the parent class. Within the parent class, you can get the reference to player and save it which can be accessed by children. So, yes, you can store the player like you planned.
I've implemented it and it works! However, I was only able to get it working when I declared both Starts() as public. Is that okay/safe?
Also just to clarify base.Start: If I have 10 Creature child enemies appearing at a random interval, the base.Start() called from the first Creature will store _player, so all other Creature children can use it? $$anonymous$$eaning that when other Creatures are instantiated after the fist one, they will not call upon base.Start()?
I just want to make sure I got it right and want to understand exactly what I'm doing. Thanks much!
Start() should never be declared as public. You don't want anything to access this method from outside. It should be either private or protected depending on the situation. I'm not sure if you are calling the Start() function manually. If you are, please don't that. It's a built-in method which runs automatically after the script is initialized.
When a Creature stores a value inside, it's keeping it for itself. It doesn't share it with other Creatures. Let's say you've created a Creature with an attack of 100. Any other creatures you created won't have their attack as 100 unless you set it so. BUT if you set the attack of the creature within that Start()
function to 100, then all the creatures, created using that class, will have an attack of 100.
Regarding the base.Start()
, classes are more like a blueprint to create objects. These blueprints contains instructions about what they values they can store, what functionalities they have and so on. So, if you create multiple creatures using the same Creature class, (in this case) they will all run the Start()
. You can only use base.OverriddenFunctionName()
when you are overriding a virtual function. What you are telling here is that, you want the code within the virtual function to run as well. You can add base.Start()
if you want to run the code from the virtual function. If you don't want to, then don't add it. I don't know if I'm explaining it to you well but if you have anymore questions, please do share it with me.
Your answer
Follow this Question
Related Questions
inheriting a class, but wanting it to instantiate on each gameobject it's applied to? 2 Answers
OnTriggerStay() Not Detected In Child Class 0 Answers
An OS design issue: File types associated with their appropriate programs 1 Answer
Putting a Child Class into a List of Parent Type and then casting it back to a Child 0 Answers