Search code examples
c#game-engine

Allways call base.Method in Override without mentioning it for simple Scripts


I am trying to implement C# as a scripting language for my game engine. Everything works fine, only one major problem occurred in my design.

I have the class BaseEntity. And another class BossEntity that derives from BaseEntity. Then I want to be able to create a new entity via script. So I create a class in my script let's say Boss1, that derives from BossEntity.

BaseEntity has an virtual Update Method. BossEntity overrides it and calls also base.Update(). All fine in the design.

But now to my problem. In my script I also want to be able to override the Update Method. So I go ahead and override it again. All works as supposed, the BossEntity override gets lost, as I now override the BaseEntity Update again.

But for simplicity I do not want to have to call in my script base.Update() to have the same behavior as in BossEntity. That's a thing that can be forgotten, which would be for me as for a scripting language bad design.

When scripting you just add functionality not remove some in my opinion.

So my general question is, is there any way to accomplish a call to base.Update() without even calling it extra in my script?

I assume no, or maybe just with a trick, but you never know.


Solution

  • As far as I know, there is no way to automatically invoke the base class's virtual method when an overridden one is invoked. You must explicitly call it.

    One of the things you can do is break the parent method up a bit more. Instead of having all of the code in a single overridable method like this:

    public class Foo
    {
        public virtual void Update()
        {
            // Do stuff
        }
    }
    
    public class Bar : Foo
    {
        public override void Update()
        {
            // Replaces the parents implementation of the 
            // Update method due to not calling base.Load();
        }
    }
    

    Instead, you can use the Template Method Pattern to break it up in to multiple parts, so that the user can override the part that is meant explicitly for them.

    public class Foo
    {
        public void Update()
        {
            this.OnUpdating();
            this.PerformUpdate();
            this.OnUpdated();
        }
    
        public virtual void PerformUpdate()
        {
            // Leave this empty. Let the subclass override it and
            // do their own thing. Your parent code will still
            // get called when Update() is called.
        }
    
        public void OnUpdating()
        {
            // Invoke code that you want to guarantee is always
            // executed PRIOR the overridden PerformUpdate() method
            // is finished.
        }
    
        public void OnUpdated()
        {
            // Invoke code that you want to guarantee is always
            // executed AFTER the overridden PerformUpdate() method
            // is finished.
        }
    }
    
    public class Bar : Foo
    {
        public override void PerformUpdate()
        {
            // Do custom stuff, don't have to call base.PerformUpdate()
            // because it already does it's code in OnUpdating() 
            // and OnUpdated().
        }
    }
    

    Hope this makes sense. This is what I do in my game engine. I then document that a call to base.PerformUpdate() is not needed. Another option is to make the PerformUpdate() method abstract, forcing children to implement it. That makes it a bit more clearer that there is no need to invoke base.PerformUpdate().

    public class Foo
    {
        public void Update()
        {
            this.OnUpdating();
            this.PerformUpdate();
            this.OnUpdated();
        }
    
        // Child class is required to implement this method. 
        // Only downside is you will no longer be able to instance 
        // the base class. If that is acceptable, then this is really 
        // the preferred way IMO for what you are wanting to do.
        public abstract void PerformUpdate();
    
        public void OnUpdating()
        {
            // Invoke code that you want to guarantee is always 
            // executed PRIOR the overridden PerformUpdate() method is finished.
        }
    
        public void OnUpdated()
        {
            // Invoke code that you want to guarantee is always 
            // executed AFTER the overridden PerformUpdate() method is finished.
        }
    }
    

    In the end, this approach lets your base class handle its update code safely, by forcing children to implement their own update method that you do not depend on. Your base class can run through its update stuff before and after the child-class has run through its updates.

    This basically lets you do this in your game code:

    Bar myFoo = new Bar();
    myFoo.Update();
    

    And you can rest assured that your base class update methods get called, and the child update code will get called as well.