- Home /
Practical differences between overriding and shadowing Start(), Update()...
Hi,
I am looking for the most efficient way to "override" Unity's engine methods like Update() in C#.
Note: Amongst other purposes this is to ease the process of freezing all in-game objects when timeScale == 0. I don't want to use FixedUpdate() on objects because I need to access some members at each frame, and because I guess FixedUpdate() is more processor-heavy than Update(); but correct me if I'm wrong.
=> I make a base class called InGameBehaviour that inherits from MonoBehavior. All my scripts used in-game are subclasses of InGameBehavior, and their own Update() method may access InGameBehaviour.Update() using base.Update()
From what I read the "new" modifier in a method's declaration should hide the base method. However if I declare Update() in a subclass with "new protected void Update() {}", I can still access InGameBehaviour.Update() using base.Update()...
This is the same as if I overrode the method with "override protected void Update() {}": in both cases the base method can be accessed with base.Update(), and in both case the base method is not called unless I use base.Update().
So, is there a practical difference/benefit in using "override" instead of "new" (or vice versa), in a case like this where both methods have the same signature?
Answer by hvilela · Sep 25, 2012 at 01:26 PM
Thanks for the link, it's very interesting! This point is actually worth knowing when accessing classes indirectly (would I have not known it I would've probably been much confused if the problem arose someday) So I guess it's always better to "properly" derive a method from another, i.e. using override.
Answer by Bunny83 · Sep 25, 2012 at 02:15 PM
The main point of virtual functions are that you have a common interface in the base class and subclasses can override it. The important point is when you access your class via a baseclass reference.
An example:
// Case 1: hiding
public class MyBaseClass
{
public void Test()
{
Debug.Log("MyBaseClass::Test()");
}
}
public class Derived1 : MyBaseClass
{
new public void Test()
{
Debug.Log("Derived1::Test()");
}
}
Our test case:
Derived1 C1 = new Derived1();
C1.Test(); // --> "Derived1::Test()"
MyBaseClass B = C1;
B.Test(); // --> "MyBaseClass::Test()"
Now the same case with a virtual function and override
// Case 2: virtual and override
public class MyBaseClass
{
public virtuel void Test()
{
Debug.Log("MyBaseClass::Test()");
}
}
public class Derived1 : MyBaseClass
{
public override void Test()
{
Debug.Log("Derived1::Test()");
}
}
The same test case:
Derived1 C1 = new Derived1();
C1.Test(); // --> "Derived1::Test()"
MyBaseClass B = C1;
B.Test(); // --> "Derived1::Test()"
The point of inheritance is to define an exact behaviour for your derived class, no matter how you use it. When you use the base keyword you always access the function from the base class. You can't remove the base class behaviour in your derived class. The base class is what it is. Virtual functions can be overridden, but with the "base" keyword you always reach the baseclass itself.
Good class about inheritance! I'm still confused about the fact that the main role of the "new" modifier is to hide the base member from the overridden member – at least that's how it is described in C# reference – but all examples seem to show the other way around: it's more like if there's a "broken link" from the base member to the overridden member, but the communication from the overridden member to the base member still works like a regular override... But at least I got the facts, and I can go along with it. :)
Edit: ...I think I got all of it! :) Thanks Bunny for your enlightening example!
Well, the important thing is that the base class and your derived class is not something totally different. The derived class is also a base class. When you just declare the same method that already exists in the base class in your derived class you hide the original method which is also part of your derived class.
Hiding elements will cause compiler warnings because this should generally be avoided. The "new" keyword just tells the compiler you want to hide it on purpose.
BTW Thank you for this further explanation. It's now perfectly clear to me!
There is a special Unity added confusion that can arise with Unity functions like Update etc - that is that as you never call Update yourself - which one get called? The answer is that it is the one in the most derived class which is called.
The general rule with this kind of standard method is do not make calls like Update or Start virtual if the base class has processing that should always happen - for example you would write a concrete implementation of Update in your base class and defer processing to a virtual function - perhaps called OnUpdate. This allows for both standard handling and derived class handling and removes the fragility of forgetting to call a base class's method when it has something that must happen. When you do this it is a compiler warning when you write a new Update function in a derived class, so you are re$$anonymous$$ded that you shouldn't do that (or do it with the knowledge of the effect by adding the new keyword).
Thx. At first I didn't want to add my own parallel implementation of Update() because I didn't want to make a useless function call every frame on every object. So I explicitely declared base Update() virtual (and protected) and explicitely declared derived Update() override. But as you say, it was not secured, I could still implicitely hide a base Update() without any warning from the compiler. I realize I was going after nickel and dime and the involved risk may not worth it, so I made my own, strongly typed overridden, myUpdate().
Your answer
Follow this Question
Related Questions
Overriding a function. 1 Answer
Create a new script object from a class which inherits from MonoBehavior 4 Answers
Can't Override Virtual Method In Inherited Class 1 Answer
How do I override objects that aren't in the Hierarchy? 0 Answers
Overriding a subtype's variable with its own subtype 1 Answer