Inheritance, need advices - c#

Let's say I have an ai or player, I want him to be able to use different weapons.
My design with weapons:
public class Weapon()
{
public virtual void FireWeapon(){} // this is useless for melee weapons
public virtual void SwingMelee(){} // this is useless for guns
public virtual void Reload(){} // this is also useless for melee weapons
}
Then in the ai controller class I simply call the function I want him to do.
This is where the ugly part is (I think)...
Controller class have a list containing some different weapons of ai and a weapon which is being used.
public class WeaponController
{
private List<Weapon> someWeapons;
private Weapon aWeapon;
public void Main()
{
if(/*"Some action or a button click" &&*/ aWeapon.CanSwingMelee() )
aWeapon.SwingMelee();
if(/*"Some action or a button click" &&*/ aWeapon.CanReload() )
aWeapon.Reload();
}
}
What is the better way to implement this? do you have any advices?
Seems that for every different action in a new weapon, I need to implement a function in the most parent Weapon class and I don't think it's a good idea...

The capability of an in-game object can be represented by an interface; you can check if a capability is present by attempting to cast to the interface. What's more, these interfaces can overlap, e.g. both melee and ranged weapons might both have an Attack method.
So for example:
public interface IWeapon
{
void Attack();
}
public interface IRangedWeapon
{
bool IsInRange(ITargetable target);
}
public interface IRequiresAmmunition
{
void Reload();
int AmmoRemaining { get; set; }
}
public class Sword : IWeapon
{
public virtual void Attack() { //code }
}
public class Rifle : IWeapon, IRequiresAmmunition, IRangedWeapon
{
public virtual void Attack() { //code }
public virtual void Reload() { //code }
public virtual int AmmoRemaining { get { } set { } }
public virtual bool IsInrange (ITargetable target) { //code }
}
public class LaserGun: IWeapon, IRangedWeapon
{
public virtual void Attack() { //code }
public virtual bool IsInrange (ITargetable target) { //code }
}
public class WeaponController
{
private List<IWeapon> someWeapons;
private IWeapon aWeapon;
private ITargetable currentTarget;
public void Weapon_OnUse()
{
if (!currentTarget.IsHostile) return;
if (this.IsInMeleeRange(currentTarget))
{
aWeapon.Attack();
return;
}
var w = aWeapon as IRangedWeapon;
if (w != null && w.IsInRange(currentTarget)
{
aWeapon.Attack();
return;
}
context.HUD.Warn("Out of range");
}
public void Weapon_OnReload()
{
var w = aWeapon as IRequiresAmmunition;
if (w != null)
{
w.Reload();
context.HUD.DisplayAmmo(w.AmmoRemaining);
}
}
}

This seems like what abstract classes and inheritance is for:
public abstract class Weapon {
public abstract void Attack();
public abstract void Reload();
}
public class MeleeWeapon : Weapon {
public override void Attack() {
// swing sword
}
public override void Reload() {
// ignore reload
}
}
public class GunWeapon : Weapon {
public override void Attack() {
// fire gun
}
public override void Reload() {
// load weapon from inventory
}
}
public class WeaponController {
private List<Weapon> someWeapons;
private Weapon aWeapon;
public void Main() {
if (/*"Some action or a button click" */)
aWeapon.Attack();
else if (/* some other button click */)
aWeapon.Reload();
}
}

I don't recommend an approach that requires you to create new interfaces for every new behavior and check the type of the weapon. What about something like this:
(This is a very rough draft.)
public abstract class Weapon
{
protected Weapon(WeaponCommandStrategy[] commandStrategies)
{
CommandStrategies = commandStrategies;
}
protected IEnumerable<WeaponCommandStrategy> CommandStrategies { get; }
public void Use(WeaponCommand command)
{
var strategy = CommandStrategies.FirstOrDefault(c => c.Command == command);
strategy?.Execute();
}
}
public enum WeaponCommand
{
Fire,
Swing,
Reload
}
public abstract class WeaponCommandStrategy
{
public WeaponCommand Command { get; private set; }
protected WeaponCommandStrategy(WeaponCommand command)
{
Command = command;
}
public abstract void Execute();
}
Now you can give a weapon whatever behaviors you want it to have in the form of various instances of WeaponCommandStrategy. If a command is sent to a weapon, it executes it. If it doesn't support a command it ignores it. You could add a property to a weapon exposing the available commands so that you could display a list of available commands.
public class Sword : Weapon
{
// Perhaps use dependency injection here
public Sword()
: base(new WeaponCommandStrategy[] { new SwordSwingStrategy() })
{
}
}
public class SwordSwingStrategy : WeaponCommandStrategy
{
public SwordSwingStrategy() : base(WeaponCommand.Swing) { }
public override void Execute()
{
// Do whatever it does
}
}
This essentially makes a Weapon a composition of various things that a weapon can do. If several weapons behave similarly they can share strategies vs. having code duplicated between various weapons.

Related

How to correctly use abstract and virtual methods?

I am trying to use virtual and abstract methods to make my game architecture better.
I'm using C# and Unity for this example.
I use a ShipComponent as a base Class because I want all the child classes to do the same thing.
But sometimes I want a certain ShipComponent to do something else.
The code will make it a lot clearer:
ShipComponent.cs:
public abstract class ShipComponent : MonoBehaviour
{
[HideInInspector] public ShipControl shipControl;
public virtual void Init(ShipControl control)
{
this.shipControl = control;
}
public virtual void IsPlayer()
{
SetListeners();
}
public abstract void IsNotPlayer();
public abstract void ReEnable();
public abstract void SetListeners();
}
One of the many child classes that inherits from ShipComponent:
public class Rudder : ShipComponent
{
[Header("Settings")]
public Transform rudder;
[Header("Debug Info")]
[SerializeField] float rudderSpeed;
[SerializeField][Range(-45, 45)] int setRudderAngle = 0;
[SerializeField][Range(-45f, 45f)] float realRudderAngle = 0f;
public override void Init(ShipControl shipControl)
{
base.Init(shipControl);
rudder = transform.GetChild(0).GetChild(4);
StartCoroutine(SmoothRudderChange());
SetListeners();
}
public override void IsPlayer()
{
base.IsPlayer();
}
public override void IsNotPlayer()
{
PlayerShipControl.OnRudderChange -= SetRudder;
}
public override void ReEnable()
{
StartCoroutine(SmoothRudderChange());
SetListeners();
}
public override void SetListeners()
{
PlayerShipControl.OnRudderChange -= SetRudder;
if (!shipControl.shipWrapper.ship.IsPlayer) return;
PlayerShipControl.OnRudderChange += SetRudder;
}
void OnDisable()
{
PlayerShipControl.OnRudderChange -= SetRudder;
StopAllCoroutines();
}
The main draw back I experience with this, is that I have to copy paste all 5 or 6 methods everytime I create a new ShipComponent class.
It seems messy and theres a lot of repeating code, most of the time the only difference in each ShipComponent is the SetListeners part, and StartCoroutines if any.
Is there a way to dynamically set delegate listeners up?
So I could set them in the base class ShipComponent?
Instead of setting each component individually?
Another script that inherits from ShipComponent for completeness:
public class Guns : ShipComponent
{
IEnumerator mouseAimCycle;
public override void Init(ShipControl shipControl)
{
base.Init(shipControl);
InitCannons();
SetListeners();
}
public override void ReEnable()
{
SetListeners();
}
public override void IsPlayer()
{
base.IsPlayer();
mouseAimCycle = AimCycle();
StartCoroutine(mouseAimCycle);
SetListeners();
}
public override void SetListeners()
{
PlayerShipControl.OnFireGuns -= TryFire;
if (!shipControl.shipWrapper.ship.IsPlayer) return;
PlayerShipControl.OnFireGuns += TryFire;
}
public override void IsNotPlayer()
{
StopCoroutine(mouseAimCycle);
PlayerShipControl.OnFireGuns -= TryFire;
}
void OnDisable()
{
PlayerShipControl.OnFireGuns -= TryFire;
StopAllCoroutines();
}
Calling the ShipComponent virtual and abstract methods:
public class ShipControl : MonoBehaviour
{
// Contains Ship + Cargo + Crew and a ref to this ShipControl
public ShipWrapper shipWrapper { get; private set; }
ShipComponent[] shipComponents;
// Gather all ShipComponents and Initialize them.
public void Start()
{
shipComponents = transform.GetComponents<ShipComponent>();
foreach (ShipComponent comp in shipComponents)
{
comp.Init(this);
}
}
// Call this to check if this is players current ship and set the components accordingly.
public void UpdateIsPlayer()
{
if (!shipWrapper.ship.IsPlayer)
foreach (ShipComponent component in shipComponents)
component.IsNotPlayer();
else
foreach (ShipComponent component in shipComponents)
component.IsPlayer();
}
And PlayerShipControl, which I use for input, broadcasting the input through delegates, and the theory is that only the players currently controlled ship will be listening for this input:
public class PlayerShipControl : MonoBehaviour
{
public static event Action<Transform> SetCamToPlayerShip;
public static event Action SetShipPanelUI;
public static event Action<bool> ToggleAnchorIcon, ToggleFlagIcon, ToggleAutofireIcon, ToggleBoatsIcon;
public static event Action OnFireGuns;
public static event Action<int> OnRudderChange;
public static event Action<int> OnSailStateChange;
public static event Action<bool> OnAllAnchorsCommand;
public static event Action<bool> OnAllBoatsCommand;
bool anchor, flag, autofire, boats;
ShipControl shipControl;
void Update()
{
if (Input.GetKeyUp(KeyCode.W)) // Raise Sails SailState++
{
OnSailStateChange?.Invoke(1);
}
if (Input.GetKeyUp(KeyCode.S)) // Furl Sails SailState--
{
OnSailStateChange?.Invoke(-1);
}
if (Input.GetKey(KeyCode.D))
{
OnRudderChange?.Invoke(1);
}
if (Input.GetKey(KeyCode.A))
{
OnRudderChange?.Invoke(-1);
}
if (Input.GetKeyDown(KeyCode.M))
{
OnRudderChange?.Invoke(0);
}
// Drop All Anchors
if (Input.GetKeyDown(KeyCode.V))
{
anchor = true;
ToggleAnchorIcon?.Invoke(anchor);
OnAllAnchorsCommand?.Invoke(anchor);
}
// Haul All Anchors
if (Input.GetKeyDown(KeyCode.H))
{
anchor = false;
ToggleAnchorIcon?.Invoke(anchor);
OnAllAnchorsCommand?.Invoke(anchor);
}
// Drop All Boats
if (Input.GetKeyDown(KeyCode.B))
{
boats = true;
ToggleBoatsIcon?.Invoke(boats);
OnAllBoatsCommand?.Invoke(boats);
}
// Take In All Boats
if (Input.GetKeyDown(KeyCode.U))
{
OnAllBoatsCommand?.Invoke(false);
// TO DO When all boats are back on deck, boatIcon + boatsBoolFlag should be turned off again.
}
if (Input.GetKeyDown(KeyCode.Space))
{
OnFireGuns?.Invoke();
}
}
}
Its a long string of scripts sometimes though so I have left out all the managers and such.
Ship ship inside shipWrapper.ship is a custom data class that stores the info about the ship, not a Monobehaviour, but it holds a bool called IsPlayer aswell. Nothing else of interest I can think of.
The main draw back I experience with this, is that I have to copy paste all 5 or 6 methods every time I create a new ShipComponent class. It seems messy and there's a lot of repeating code, most of the time the only difference in each ShipComponent is the SetListeners part, and StartCoroutines if any.
In the show example you have more differences between implementations then ones described. Without seeing the full code it is hard to suggest something meaningful.
Few notes on the current code:
In Rudder you don't need to specify IsPlayer because the following:
public override void IsPlayer()
{
base.IsPlayer();
}
does not add anything extra, so you can just skip implementation in the derived class.
Based on provided examples it seems that ReEnable can be defined as virtual in base class with default implementation set to calling SetListeners (the same approach as you have with Init and IsPlayer).
PlayerShipControl.Update possibly can be improved by moving handlers to dictionary. Something along this lines:
public class PlayerShipControl : MonoBehaviour
{
// ...
Dictionary<KeyCode, Action> keyActions = new() // not sure about the type
{
{ KeyCode.W, () => OnSailStateChange?.Invoke(1) },
// ...
{ KeyCode.V, () =>
{
anchor = true;
ToggleAnchorIcon?.Invoke(anchor);
OnAllAnchorsCommand?.Invoke(anchor);
}
},
// ...
};
void Update()
{
foreach (var kvp in keyActions)
{
if (Input.GetKeyUp(kvp.Key))
{
kvp.Value();
break;
}
}
}
}

Inheritance chain in state machine branching out

I am trying to do a state machine to controll ai behaviour in Unity 3D.
My question is regarding inheritance. Im trying to set up some base logic that handles how and why states shoul be changed. But further down the inheritance line i need different kind of characters to be able to do character speicfic things. But im not able to do this with inheritnance.
Can someone confirm that my thinking is not how its done? then i know to find another solution.
PSEUDO CODE:
// STATE CONTROLLERS CONTROLL THE CHARACETER BY CHOOSING WITCH STATE THEY SHOULD BE IN
abstract class StateController {
StateBase state;
int HitPoints;
int Hunger:
abstract void Update()
{
CheckIfStateShouldChange();
state.UpdateState(this);
}
}
WolfStateController : StateController {
WolfState state;
override void Update()
{
base.Update();
state.Update(this);
}
}
SheepStateController : StateController {
SheepState state;
override void Update()
{
base.Update();
state.Update(this);
}
}
// STATES CONTAINS LOGIC FOR BEHAVIOUR IN A CERTAIN STATE
StateBase {
virtual void UpdateState( StateController controller)
{
// Does things all inheriting classes should do
}
}
WolfState : StateBase {
override void UpdateState( WolfStateController wolfstate)
{
base.UpdateState(WolfStateController wolfstate)
//Does wolf specific things that needs to be done in all WolfStates
}
}
WolfStalkAndHuntState : WolfState {
override void UpdateState( WolfStateController wolfstate)
{
base.UpdateState(WolfStateController wolfState);
//Hunts sheep and attacks on sight
}
}
SheepState : StateBase {
override void UpdateState( SheepStateController sheepState)
{
//Does sheepy things
}
}
SheepReproduceState : SheepState {
override void UpdateState( SheepStateController sheepState)
{
base.UpdateState(SheepStateController sheepState);
// Looks for mate and gets freaky
}
}
I would suggest something like this:
Controller Class:
public class SoliderController : MonoBehaviour
{
[HideInInspector] public sState currentState;
[HideInInspector] public FireState fireState;
[HideInInspector] public IdleState idleState;
[HideInInspector] public ChaseState chaseState;
private void Awake()
{
fireState = new FireState(this);
idleState = new IdleState(this);
chaseState = new ChaseState(this);
}
private void Start ()
{
currentState = idleState;
}
private void Update()
{
currentState.Update();
}
Interface:
public abstract class sState
{
public abstract void Update();
public abstract void ToChaseState();
public abstract void ToIdleState();
public abstract void ToFireState();
}
Example Class
public class IdleState : sState
{
private readonly SoliderController controller;
public IdleState(SoliderController soliderController)
{
controller = soliderController;
}
public override void Update()
{
Patrol();
//Condition to change state
if (*expresion1*)
ToChaseState();
if (*expresion2*)
ToFireState();
}
private void Patrol()
{
//Your Logic for the behvaiour wanted.
}
public override void ToChaseState()
{
controller.currentState = controller.chaseState;
}
public override void ToFireState()
{
controller.currentState = controller.fireState;
}
public override void ToIdleState()
{
Debug.LogWarning("Can't transition to same state");
}
}
This way checking for changes is way easier and also you can impletement state specific behaviours as well. Also, adding a new state goes really easy, you just implement the new Class and ToNewState method in the interface.
Hope it helped.

Method from interface takes one parameter but it will be used with 2 different objects

I have to do a simple rpg game and there are 2 types of entities: heroes and monsters. Attack method will be implemented in both classes and it is contained by a interface called IAttack. The problem is that this method take a Monster type as parameter for hero class and a Hero type as parameter for monster class.
The code looks something like this:
The interface:
interface IAttack
{
void Attack(Object oponnnent);
}
The Hero class(which implements IAttack):
public void Attack(Monster opponent)
{
//code goes here
}
The Monster class(which implements IAttack):
public void Attack(Hero opponent)
{
//code goes here
}
The problem is I can not pass different types of arguments.
You could make an abstract class that Monster and Hero dervice from.
public abstract class PlayerType
{
public abstract int Health();
}
Then in your interface use the new abstract type:
interface IAttack
{
void Attack(PlayerType oponnnent);
}
Monster class:
public class Monster : PlayerType, IAttack
{
public override int Health()
{
return 100;
}
public void Attack(PlayerType hero)
{
}
}
Hero class:
public class Hero : PlayerType, IAttack
{
public override int Health()
{
return 500; // He is a hero afterall ;)
}
public void Attack(PlayerType monster)
{
}
}
Why not have two interfaces? Something that can attack and something that can be attacked?
public interface IAttackable
{
void OnAttacked(IAttacker attacker);
}
public interface IAttacker
{
void OnAttack(IAttackable opponet);
}
public class Hero : IAttacker, IAttackable
{
public void OnAttack(IAttackable opponet)
{
}
public void OnAttacked(IAttacker attacker)
{
}
}
public class Monster : IAttacker, IAttackable
{
public void OnAttack(IAttackable opponet)
{
}
public void OnAttacked(IAttacker attacker)
{
}
}

Nested Strategy Design Pattern

Suppose we have a player which controls a character named Player1. To enable switching weapons at runtime, I have the following code:
public interface IWeapon
{
void Fire();
}
public class Player1Weapon1 : IWeapon
{
...
void Fire()
{
//do actions of Weapon1
}
...
}
public class Player1Weapon2 : IWeapon
{
...
void Fire()
{
//do actions of Weapon2
}
...
}
public class Player1
{
IWeapon weapon;
Player1Weapon1 w1;
Player1Weapon2 w2;
public Player1()
{
w1 = new Player1Weapon1(this);
w2 = new Player1Weapon2(this);
SetWeapon(w1);
}
void Update()
{
if(SWITCH_BTN_HELD)
{
if(weapon.equals(w1)) SetWeapon(w2);
if(weapon.equals(w2)) SetWeapon(w1);
}
if(FIRE_BTN_HELD)
weapon.Fire();
}
void SetWeapon(w)
{
weapon = w;
}
}
That works perfectly.
But now a player can select another character named Player2.
Note that Player2's Weapons are different from Player1. So we can add Classes like this:
public class Player2Weapon1 : IWeapon
{
...
void Fire()
{
//do actions of Weapon1
}
...
}
public class Player2Weapon2 : IWeapon
{
...
void Fire()
{
//do actions of Weapon2
}
...
}
public class Player2
{
IWeapon weapon;
Player2Weapon1 w1;
Player2Weapon2 w2;
public Player2()
{
w1 = new Player2Weapon1(this);
w2 =new Player2Weapon2(this);
SetWeapon(w1);
}
void Update()
{
if(SWITCH_BTN_HELD)
{
if(weapon.equals(w1)) SetWeapon(w2);
if(weapon.equals(w2)) SetWeapon(w1);
}
if(FIRE_BTN_HELD)
weapon.Fire();
}
void SetWeapon(w)
{
weapon=w;
}
}
It will work again but it is very tight, if a player wants to play with Player3, I should addmore classes to the project .
I am wondering how to make Strategy Pattern for flayers like below:
interface IPlayer()
{
}
I don't know which methods will be placed in IPlayer? How can I create nested Strategy Design Patterns?
Not sure if I get what you are asking or if you don't know how/what to ask. Strategy pattern is not what you need the most here. I try to give my two cents.
First of all, I don't think it's a good idea to have concrete classes in your players, like Player1Weapon. It should only contain IWeapons. This way you don't need to specifically define which weapons your players use nor create new player classes for every variations.
Consider the following. You have these IWeapons in SomeNamespace namespace.
public interface IWeapon
{
void Fire();
}
public class Shotgun : IWeapon
{
public void Fire()
{
Console.WriteLine("Shotgun goes boom");
}
}
public class Knife : IWeapon
{
public void Fire()
{
Console.WriteLine("Stabbed teh sucker");
}
}
public class NuclearBomb : IWeapon
{
public void Fire()
{
Console.WriteLine("Game over for everyone!!1");
}
}
Now your Player class could look like below. Just add any level of abstraction you might need, here I just assume you don't.
public class Player
{
private IWeapon _wielded;
public Player(string name)
:this(name, null, null)
{}
public Player(string name, IWeapon primary, IWeapon secondary)
{
Name = name;
Primary = _wielded = primary;
Secondary = secondary;
Console.WriteLine(string.Format("Player '{0}' spawned", Name));
}
public void Switch()
{
_wielded = _wielded != Primary ? Primary : Secondary;
}
public void Fire()
{
if (_wielded != null)
_wielded.Fire();
}
public string Name { get; set; }
public IWeapon Primary { get; set; }
public IWeapon Secondary { get; set; }
}
To create "any player" you could have a simple factory to "spawn" them taking required attributes as parameter.
public class PlayerFactory
{
// key = player name, value = weapons
public Player Create(KeyValuePair<string, string[]> args)
{
var primary = Activator.CreateInstance(Type.GetType(args.Value[0])) as IWeapon;
var secondary = Activator.CreateInstance(Type.GetType(args.Value[1])) as IWeapon;
var player = new Player(args.Key, primary, secondary);
return player;
}
}
And now if you run the below "initialization"...
// this would come from config file or similar
var config = new List<KeyValuePair<string, string[]>>
{
new KeyValuePair<string,string[]>(
"Player1", new[] { "SomeNamespace.Shotgun", "SomeNamespace.Knife" }),
new KeyValuePair<string,string[]>(
"Player2", new[] { "SomeNamespace.NuclearBomb", "SomeNamespace.Knife" })
};
var factory = new PlayerFactory();
foreach (var entry in config)
{
var player = factory.Create(entry);
player.Fire();
player.Switch();
player.Fire();
}
... you end up with following console log
Player 'Player1' spawned
Shotgun goes boom
Stabbed teh sucker
Player 'Player2' spawned
Game over for everyone!!1
Stabbed teh sucker
When using the Strategy pattern, your design might look like
the UML diagrams below.
Player1 delegates performing the Fire() operation to one of different weapon classes Weapon1, Weapon2,...
For further discussion please see the Strategy design pattern
at http://w3sdesign.com.
public interface IWeapon
{
void Fire();
}
public class Weapon1 : IWeapon
{
...
void Fire()
{
//do actions of Weapon1
}
...
}
public class Weapon2 : IWeapon
{
...
void Fire()
{
//do actions of Weapon2
}
...
}
public interface IPlayer
{
void Update();
}
public class Player1 : IPlayer
{
private IWeapon weapon;
private IWeapon w1;
private IWeapon w2;
public Player1()
{
w1 = new Weapon1();
w2 = new Weapon2();
SetWeapon(w1);
}
void Update()
{
if(SWITCH_BTN_HELD)
{
if(weapon.equals(w1)) SetWeapon(w2);
if(weapon.equals(w2)) SetWeapon(w1);
}
if(FIRE_BTN_HELD)
weapon.Fire();
}
void SetWeapon(w)
{
weapon = w;
}
}

How to override a method in a custom library class

I have two projects: ClientProj and ServerProj, which both share a SharedLibrary containing the basics of my game.
Inside this library I have the class GameObject which is the base class from which many other game items inherit.
Inside GameObject is a SetPosition() method.
Here's my problem: When I run SetPosition() on the client, I wish to add some additional code / override the method completely. The code I wish to add however relates to classes that are only present in the ClientProj namespace, which the SharedLibrary knows nothing about.
Is there any clean way to override or extend the library methods?
Updated: Note that the instances of GameObject and all things that inherit it are defined, contained and handled all within the SharedLibrary namespace. For the most part the ClientProj and ServerProj only handle networking, users and input/output.
You can use the Proxy pattern and have the game objects inherit from the proxy class instead of the real class:
SharedLibrary:
public class GameObject
{
public virtual void SetPosition() { ... }
}
public class DelegatingGameObject : GameObject
{
public GameObject Inner;
public override void SetPosition() { Inner.SetPosition(); }
}
public class Tree : DelegatingGameObject
{
}
ClientLibrary:
class ClientGameObject : GameObject
{
public override void SetPosition()
{
if (isMonday) base.SetPosition();
}
}
var tree = new Tree { Inner = new ClientGameObject() };
tree.SetPosition();
SharedLibrary:
public class GameObject
{
public virtual void SetPosition() { Console.WriteLine("GameObject.SetPosition"); }
public static event Func<GameObject> Factory;
internal static GameObject CreateBase() { var factory = Factory; return (factory != null) ? factory() : new GameObject(); }
}
internal class GameObjectBase : GameObject
{
private readonly GameObject baseGameObject;
protected GameObjectBase() { baseGameObject = GameObject.CreateBase(); }
public override void SetPosition() { baseGameObject.SetPosition(); }
}
internal class Tree : GameObjectBase
{
public override void SetPosition()
{
Console.WriteLine("Tree.SetPosition");
base.SetPosition();
}
}
public static class Game
{
public static void Start()
{
new Tree().SetPosition();
}
}
ClientLibrary:
internal class ClientGameObject : GameObject
{
public override void SetPosition()
{
Console.WriteLine("ClientGameObject.SetPosition Before");
base.SetPosition();
Console.WriteLine("ClientGameObject.SetPosition After");
}
}
internal static class Program
{
static void Main(string[] args)
{
GameObject.Factory += () => new ClientGameObject();
Game.Start();
}
}
Make SetPosition method virtual and use override keyword to override its behaviour in ClientProj.
You can do it virtual in base class, override in derived, and in overriden method call your methods and after base class method.
A psudocode can look like this:
public class GameObject
{
public virtual void SetPosition()
{
//do something here
}
}
public class Derived: GameObject
{
public override void SetPosition()
{
// do something specific to Derived
base.SetPosition(); // CALL BASE CLASS METHOD AFTER
}
}

Categories

Resources