简体   繁体   中英

If two scripts inherit from the same class and a function can be called to effect both, how can I find out which one it affects?

I have a script called Player with a TakeDamage function in it:

    public void TakeDamage(float value)
    {
        SetHealth(currentHealth - value * takeDamageMultiplier);
    }

I have 2 other scripts called AIPlayer and HumanPlayer which inherit from Player. Essentially, I want to store the damage dealt if the HumanPlayer deals damage to the AIPlayer.

My thought process was to create another function inside of Player called SetDamageDealt and call this right after Player.TakeDamage was called in any other scripts.

My SetDamageDealt looks like this:

    public void SetDamageDealt(float value)
    {
        LeaderboardVariables.damageDealt += Convert.ToInt32(value * takeDamageMultiplier);
        Debug.Log(LeaderboardVariables.damageDealt);
    }

This adds the damage dealt to the correct variable but does it for when both the AIPlayer and HumanPlayer take damage.

How can I change this so that I only store the damage if the AIPlayer deals damage to the HumanPlayer?

A class is a recipe to define how the object is created. With the recipe you create an instance , which is the object itself. The class is:

public class Foo {
    int whatever;
    public Foo() { 
    
    }
    public void whatever(){
        //...
    }

} 

and you would make a new instance with Foo myFoo = new Foo();

The calling method wont affect the inherited script but the instance its called from. Meaning that if you have;

public class Foo1: FooBase {
    int whatever;
    public Foo1() { 
    
    }
}

public class Foo2 : FooBase {
    int whatever;
    public Foo2() {

    }
}

Foo1 myFoo1 = new Foo1();
myFoo1.whatever();
Foo2 myFoo2 = new Foo2();
myFoo2.whatever();

The whatever method will be called for each of the instances respectively.

What you should do is to look into the basic principles of OO inheritance and all of the features it brings. (method redefinition, abstraction, etc).

To get you started, I would say, the easy (but wrong) way is to solve it that way: ditch the SetDamageDealt function and:

public void TakeDamage(float value)
{
    if (this is HumanPlayer) 
        LeaderboardVariables.damageDealt += Convert.ToInt32(value * takeDamageMultiplier);

    SetHealth(currentHealth - value * takeDamageMultiplier);
}

This works, but is wrong in terms of Software Engineering, as a rule of thumb, when you use the 'is' Operator in a base class to find out which special class you are, you are violating some of the most basic SE Principles (SRP; OCP, LSP)

So, you should define the additional behaviour into your special classes.

This can be solved in many ways, but one example would be:

In the base class:

protected void OnDamageTaken(float value)
{
   // do nothing in base class
}

public void TakeDamage(float value)
{
    SetHealth(currentHealth - value * takeDamageMultiplier);
    OnDamageTaken(value);
}

in the derived classes:

public class HumanPlayer : Player
{
    protected override void OnDamageTaken(float value)
    {
        base.OnDamageTaken(value);

        LeaderboardVariables.damageDealt += Convert.ToInt32(value * takeDamageMultiplier);
    }
}

If you get more fit in these concepts, you could also decide that every player must be either a HumanPlayer or an Ai Player, and ditch the empty body in the base class and make it abstract, etc...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM