MattDahEpic
MattDahEpic

Reputation: 73

C# InvalidCastException while getting derived type

I'm making a 2D grid based game in Unity and have a Weapon class that has properties for getting the stats on the weapon. The stats are calculated by the parts that the weapon is made up of, and the number and type of parts is defined by the type of weapon WepGun, WepStaff, or WepSword. Every weapon type has an affinity and a grip. In order to allow the player to equip parts to the weapon, I have to get it's actual type (gun/staff/sword) so that I can use the fields on the weapon. The weapon is stored in the save data as a Weapon (which may be a problem idk) and is saved to disk with the Newtonsoft.Json json library.

When I attempt to assign the fields of Weapon, no problem, but when I try to assign the fields of the actual weapon type I get an InvalidCastException: Cannot cast from source type to destination type.. I'm pretty sure it's not downcasting since I create the characters with the type of weapon they start with. (this link shows an example that works somewhat similar to my situation)

Code in question:

[SaveData.cs]

[JsonProperty] public static CharacterSaveData JESSIE = new CharacterSaveData(...,new StatManager.WepGun());

public class CharacterSaveData {
    ...

    [JsonProperty] public StatManager.Weapon weapon;

    internal CharacterSaveData (..., StatManager.Weapon weapon) {
        this.weapon = weapon;

        weapon.affinity = StatManager.Part.ART_AFFINITY;
        ((StatManager.WepGun)weapon).barrel = new StatManager.Part(StatManager.PartType.GUN_BARREL, StatManager.AttackType.CARDINAL_SINGLE_TARGET, 3, 0, 0.2f); //error occurs here
    }

[StatManager.cs]

public abstract class Weapon {
    [JsonProperty] private Part _affinity;
    public Part affinity {...}
    [JsonProperty] private Part _grip;
    public Part grip {...}

    ...properties

    internal Weapon (Part affinity, Part grip) {
        _affinity = affinity;
        _grip = grip;
    }
}
public class Part {
    ...predefined parts (ART_AFFINITY is here)

    public PartType? partType; //enum
    public AttackType? attackType; //enum
    public int? attackRange;
    public int? damageRange;
    public float? modifier;
    public ModType? modifierType; //enum

    public Part (PartType? partType = null, AttackType? attackType = null, int? attackRange = null, int? damageRange = null, float? modifier = null, ModType? modifierType = null) {
        this.partType = partType;
        this.attackType = attackType;
        this.attackRange = attackRange;
        this.damageRange = damageRange;
        this.modifier = modifier;
        this.modifierType = modifierType;
    }
}

public class WepGun : Weapon {
    [JsonProperty] private Part _barrel;
    public Part barrel {...}
    [JsonProperty] private Part _sight;
    public Part sight {...}
    [JsonProperty] private Part _bullet;
    public Part bullet {...}

    ...properties

    public WepGun (Part barrel = null, Part grip = null, Part sight = null, Part bullet = null, Part affinity = null) : base(affinity,grip) {
        _barrel = barrel;
        _sight = sight;
        _bullet = bullet;
    }
}
public class WepStaff : Weapon {
    [JsonProperty] private Part _shaft;
    public Part shaft {...}
    [JsonProperty] private Part _head;
    public Part head {...}
    [JsonProperty] private Part _accessory;
    public Part accessory {...}

    ...properties

    public WepStaff (Part shaft = null, Part grip = null, Part head = null, Part accessory = null, Part affinity = null) : base(affinity,grip) {
        _shaft = shaft;
        _head = head;
        _accessory = accessory;
    }
}
public class WepSword : Weapon {
    [JsonProperty] private Part _blade;
    public Part blade {...}
    [JsonProperty] private Part _guard;
    public Part guard {...}
    [JsonProperty] private Part _accessory;
    public Part accessory {...}

    ...properties

    public WepSword (Part blade = null, Part guard = null, Part grip = null, Part accessory = null, Part affinity = null) : base(affinity,grip) {
        _blade = blade;
        _guard = guard;
        _accessory = accessory;
    }
}

Upvotes: 0

Views: 90

Answers (1)

Chuck Savage
Chuck Savage

Reputation: 11955

If this is the offending line, change it and debug it.

((StatManager.WepGun)weapon).barrel = new StatManager.Part(StatManager.PartType.GUN_BARREL, StatManager.AttackType.CARDINAL_SINGLE_TARGET, 3, 0, 0.2f); 

change to

var wepGun = weapon as StatManager.WepGun;
if(null != wepGun)
    wepGun.barrel = new StatManager.Part(StatManager.PartType.GUN_BARREL, StatManager.AttackType.CARDINAL_SINGLE_TARGET, 3, 0, 0.2f); 
else
{
   // debug code
}

PS I think you should be using Interfaces and not classes for weapon types. Someday you are going to want to merge two weapon types into one. You can't do that with classes.

Upvotes: 1

Related Questions