0

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;
    }
}
6
  • 2
    Every WepGun is a Weapon but not every Weapon is a WepGun... Commented Apr 18, 2017 at 17:58
  • What DavidG said. Let's do this using different analogies: You have base class Person and a class BaseballPlayer that inherits from Person. Every BaseballPlayer is a Person, but not every Person is a BaseballPlayer. Commented Apr 18, 2017 at 18:01
  • 1
    But if I define the value of the field as a WepGun then attempting to get it as a WepGun shouldn't fail. If I defined it as a WepStaff I would expect the cast to fail. Is this something that magically forgets its own shape when put into a bucket of a different shape? Commented Apr 18, 2017 at 18:11
  • 1
    No it can't "forget" what it was, so you must be giving it the wrong type object. Commented Apr 18, 2017 at 18:12
  • You haven't proven that your invalid cast is coming from the JESSIE field, which from the looks of it should work fine. Use the debugger to get a call stack when the exception is thrown. A MCVE example would be helpful for both you and us. Commented Apr 18, 2017 at 18:18

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.