0

So I've been working on a state machine for a player character in a Unity game, and thought a hierarchical system would work well. However, I'm having some trouble getting methods to traverse the inheritance chain. If someone could point out my mistake for me, I'd greatly appreciate it.

Here's my PlayerScript : Monobehavior script:

public PlayerState State;

public void Start() {
   State = new StoppedState();
   State.Enter(this);
}
public void Update() {
   State.Update(this);
}

And here are the PlayerStates:

public class PlayerState {
   public virtual PlayerState Update(PlayerScript player) {
      Debug.Log("Blorp");
      return null;
   }
   public virtual void Enter(PlayerScript player) {}
}

public class LowPriorityState : PlayerState {
   public new virtual PlayerState Update(PlayerScript player) {
      Debug.Log("Blop");
      PlayerState newState = base.Update(player);
      //Do state stuff, determine if state should change
      return newState;
   }
}

public class StoppedState : LowPriorityState {
   public override PlayerState Update(PlayerScript player) {
      Debug.Log("Blip");
      PlayerState newState = base.Update(player);
      //Do state stuff, determine if state should change
      return newState;
   }
   public override void Enter(PlayerScript player) {
      Debug.Log("Entered Stopped State");
   }
}

The expected output after 1 frame is:

Entered Stopped State

Blip

Blop

Blorp

but instead I'm getting:

Entered Stopped State

Blorp

...which is completely baffling, because it's clearly using the overridden "Enter" method but not using the overridden "Update" method. Does anyone know what I'm doing wrong and how to fix it?

Caleb
  • 3
  • 2
  • 1
    Try changing `LowPriorityState`'s Update method signature from `new virtual` to `override`. – Iggy Aug 10 '21 at 01:55
  • Does this answer your question? [Why does calling a method in my derived class call the base class method?](https://stackoverflow.com/questions/17717570/why-does-calling-a-method-in-my-derived-class-call-the-base-class-method) – SpicyCatGames Aug 10 '21 at 05:31
  • That post did not answer my question. I found plenty of examples of basic base-derived class relationships, but none of base-derived-derived classes. – Caleb Aug 10 '21 at 14:30

1 Answers1

0

The "new" modifier is used to hide a method of the base class and create a completely new method. This way, if the variable is of type BaseClass, it will call the method in the base class, and if the variable is of type DerivedClass, it will call the method in the derived class.

So in the LowPriorityState you are creating a new method, not overriding the one from PlayerState. So your field State of type PlayerState will continue to call the method from the base class.

And then you override this new method in StoppedState, but as your field State is of type PlayerState, it continues to call the method from the base class.

So just replace the new keyword with override.

SpicyCatGames
  • 863
  • 7
  • 25
  • 1
    It wouldn't let me use "override" and "virtual", and previously it wouldn't let me override and then override again, so I guess I thought that was off limits, but replacing "new virtual" with "override" appears to have fixed it. Thank you. – Caleb Aug 10 '21 at 13:36