简体   繁体   中英

Instantiating an inherited object

Still fairly new to inheritance, so I need some help. Currently, I have an assignment to create a basic game that uses inheritance for 3 weapons. My base class:

public class Weapons : MonoBehaviour
{
    public int rateOfFire;
    public string myName;

    public Weapons(string Name)
    {
        myName = Name;
    }
}

And one of the child classes:

public class Rifle : Weapons
{
    public Rifle(string Name) 
        : base(Name)
    {
        myName = Name;
        rateOfFire = 5;
    }
}

My first question comes with the fact if I'm even doing this right?

My second question is how would I instantiate these into my Unity scene? I've written a method to switch weapons, which is an array on my player script, so would I insert an instantiate line here or create another method? Missing some lines, but here's the just of it:

public GameObject[] weapons;
public int currentweapon = 0;
private int invweap;
void Start()
{
    //Managing weapons
    invweap = weapons.Length;
    SwitchWeapon(currentweapon);
}
void SwitchWeapon(int index)
{
    for (int i = 0; i<invweap;i++)
    {
        if (i == index)
        {
            weapons[i].gameObject.SetActive(true);
        }
        else
        {
            weapons[i].gameObject.SetActive(false);
        }
     }
}

My first question comes with the fact if I'm even doing this right?

Pretty close. Let's look.

public class Weapons : MonoBehaviour
{

I assume it is a restriction of Unity that this type derives from the given base type. Normally one would never say that a weapon is a kind of "monobehaviour", whatever that is.

Is there any weapon that is not a more specific kind of weapon? No. So this should be an abstract class.

Classes should be named singular unless the class itself represents a group of things. This should be "Weapon", not "Weapons".

abstract class Weapon: MonoBehaviour 
{

Moving on.

public int rateOfFire;

Already we are in trouble. Public fields are a bad code smell in C#. If you want a public property then make it a property:

public int RateOfFire { get; set; }

More on the nose though: rate of fire only applies to ranged weapons. You have this in the base class, implying that it applies to all weapons. You don't fire a sword.

public string myName;

Again, public field, bad. Make it a property. Don't call it myName . Call it what it is: Name :

public string Name { get; set; }

Moving on.

public Weapons(string Name)
{
    myName = Name;
}

Use camelCase for parameters, PascalCase for properties:

public Weapon(string name)
{
    Name = name;
}

Will Name ever change? If not, please make it a get-only property.

public string Name { get; }

(Depending on what version of C# you are using that might not be legal. Try { get; private set; } if that doesn't work.)

That the name can be set in the ctor implies that every instance of a weapon has a name. Is that right? That doesn't seem right. Are there swords named Bob's Sword, and swords named "Stormbringer" and whatnot? I would have thought that the name would be associated with the type, not with a given instance. I would expect that the name would be an abstract property, overridden by the derived type.

public abstract string Name { get; }

Moving on to the derived type:

public Rifle(string Name) 
    : base(Name)
{
    myName = Name;
    rateOfFire = 5;
}

This is messed up. You've already set the name in the base class constructor; don't set it again! And why is the name set by the base ctor but the rate of fire set by the derived ctor? Either the rate of fire should be a property of the derived type, or it should be passed in along with the name.

Let's get rid of both of them and just make the name and rate of fire abstract properties overridden in a derived class. And let's improve the type hierarchy so that the weapon base class does not include things common only to ranged weapons.

So, put it all together:

public abstract class Weapon : MonoBehaviour
{
  public abstract string Name { get; }
}

public abstract class RangedWeapon : Weapon
{
  public abstract int RateOfFire { get; }
}

public class Rifle : RangedWeapon
{
  public override string Name { get { return "rifle"; } }
  public override int RateOfFire { get { return 5; } }
}

public class Sword : Weapon
{
  public override string Name { get { return "sword"; } }
}

Make sense?

My second question is how would I instantiate these into my Unity scene?

It is better to ask one question per question on StackOverflow, because usually what happens is the second question doesn't get answered. Like how I'm not answering it right here.

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