2

I'm developing a 2D space-shooter in Unity game engine.

I have a base class containing the variables shared among all the enemy space ships and that base class contains functions that are meant to be called by every instance of the derived classes. Take this void Start() function for example:

Base Class

public class EnemyBaseScript : MonoBehaviour { // some public/protected variables here protected void Start () { // some initializations shared among all derived classes } . . . } 

Derived Class

public class L1EnemyScript : EnemyBaseScript { // Use this for initialization void Start () { base.Start (); // common member initializations hp = 8; // hp initialized only for this type of enemy speed = -0.02f; // so does speed variable } } 

I think you get the idea. I want the common initalizations to be done in the base.Start() function and for the class-specific initalizations to be done in this Start() function. However, I get the warning:

Assets/Scripts/L1EnemyScript.cs(7,14): warning CS0108: L1EnemyScript.Start() hides inherited member EnemyBaseScript.Start(). Use the new keyword if hiding was intended

I lack experience in OOP and C#, so what is the correct way to do what I think? What does this warning mean and how can I do it right?

3 Answers 3

7

In C#, inheriting a function with the same function signature will hide the previous one.

Take the example from Microsoft's website:

class Base { public void F() {} } class Derived: Base { public void F() {} // Warning, hiding an inherited name } 

However hiding the function is probably not what you want:

class Base { public static void F() {} } class Derived: Base { new private static void F() {} // Hides Base.F in Derived only } class MoreDerived: Derived { static void G() { F(); } // Invokes Base.F } 

Instead what you could do is make your base function "virtual":

public class EnemyBaseScript : MonoBehaviour { // some public/protected variables here public virtual void Start () { // some initializations shared among all derived classes } . . . } 

Then we can override it:

public class L1EnemyScript : EnemyBaseScript { // Use this for initialization public override void Start () { base.Start (); // common member initializations hp = 8; // hp initialized only for this type of enemy speed = -0.02f; // so does speed variable } } 
Sign up to request clarification or add additional context in comments.

Comments

5

You need to tell the compiler that Start is supposed to be overridden:

protected virtual void Start () { ... } 

and that you are in fact overriding it on purpose in your derived class:

protected override void Start () { ... } 

See the documentation for virtual and override for reference; there is more information here.

You current code defines two separate Start methods which happen to share the same name but are not otherwise related.

4 Comments

Hmm. I always thought virtual functions were left empty to be filled later on by override 'ing them which, I thought, completely overrides the virtual one (disregards whats in it) and rendering the previous code that is written in virtual function irrelevant. Now I learnt it's sort of extending the base Start() which is great and exactly what I needed. Please correct me if I got it wrong and thanks for the answer.
@Varaquilex: Overriding a method does make the overridden code irrelevant (unless you call base.Start in the override). Why do you think it's extending?
Oh, even though we override it, the way I call the function (base.start()) triggers the previously written code. I thought this was impossible after overriding it. Everything is much clear now :)
No @Varaquilex. Those are abstract members.
1

In C#, methods/properties are non-virtual by default. You must declare the method/property virtual if you wish to override it in the subclass. If you do not then:

EnemyBaseScript s = new LIEnemyScript(); s.Start(); // calls EnemyBaseScript.Start() 

while

L1EnemyScript s = new L1EnemyScript(); s.Start(); // calls L1EnemyScript.Start() 

What you want is to make the method virtual in the base class and override it in the subclass

class EnemyBaseScript { protected virtual void Start() { //... } } class L1EnemyBaseScript : EnemyBaseScript { protected override void Start() { base.Start(); //... } } 

1 Comment

I scoured the Internet, and your concise examples are the only thing that really made it 'click' for me. Thank you

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.