EDIT 2
This is what is being shown in the unity debugger when I look at the list of Items. It is seeing the baseball bat as an Item type, not WeaponItem type.
EDIT 1
This is currently all I have in my ItemsContainer ( my old file has the bloated xml file)
<?xml version="1.0" encoding="utf-8" ?>
<ItemsContainer>
<Items>
<!--Weapon Items-->
<WeaponItem Name = "Baseball Bat" ID="501">
<!--General Info-->
<Description>A wooden bat that may have belonged to somone famous</Description>
<!--Weapon Item-->
<Damage>4</Damage>
<Targets>1</Targets>
</WeaponItem>
</Items>
</ItemsContainer>
ORIGINAL POST
I'm working on a complex inventory system for a 2D game in Unity.
I read game data with XML serialization and have set up a drag/drop system that works using an Item class. I've also gotten pretty far with a dialogue system that can tell what items are in certain characters inventories.
Issue:
Want to be able to downcast to an item subclass in order to access specific data about it on a UI hover (At least that's what I think I need to do), or find another solution on how to setup my item database
For eg:
- When you hover over a WeaponItem - it shows you damage information + desc
- When you hover over a general Item - it only shows you desc
History:
What I have right now is a very bloated Items.xml file that has all tags necessary, regardless of item category. This is really painful to maintain as I come up with new Items and categories - so I wanted to try inheritance.
At first, my initial approach was:
<ItemsContainer>
<Items>
<Item>
<!-- Generic tags or attributes: ID, Name, Description etc -->
<!-- Other tags that define the item, is there in every item!-->
</Item>
</Items>
</ItemsContainer>
and now it's this:
<ItemsContainer>
<Items>
<WeaponItem>
<!-- Generic tags or attributes: ID, Name, Description etc -->
<!-- WeaponItem specific tags: Damage, Targets Etc -->
</WeaponItem>
<ClothingItem>
<!-- Generic tags or attributes: ID, Name, Description etc -->
<!-- ClothingItem specific tags: Exposure, ArmorRating Etc -->
</ClothingItem>
.
.
.
</Items>
</ItemsContainer>
My Item class looks like this:
public class Item
{
[XmlAttribute("Name")]
public string Name;
[XmlAttribute("ID")]
public int ID;
// General Info
public string Description;
public virtual string GetDetails()
{
return
"\nName: " + Name +
"\nID: " + ID +
"\nDescription: " + Description;
}
}
While my subclass WeaponItem looks like this:
class WeaponItem : Item
{
public int Damage;
public int Targets;
public override string GetDetails()
{
return
base.ToString() +
"\nDamage: " + Damage +
"\nTargets: " + Targets;
}
}
Here's what my ItemsContainer looks like:
[XmlRoot("ItemsContainer")]
public class ItemsContainer
{
[XmlArray("Items"),XmlArrayItem("WeaponItem"), XmlArrayItem("ClothingItem"),...]
public List<Item> Items = new List<Item>();
public static ItemsContainer Load(string path)
{
TextAsset _xml = Resources.Load<TextAsset>(path);
XmlSerializer Serializer = new XmlSerializer(typeof(ItemsContainer));
StringReader reader = new StringReader(_xml.text);
ItemsContainer items = Serializer.Deserialize(reader) as ItemsContainer;
reader.Close();
return items;
}
}
My ItemUI class contains:
- Item variable
- Several public game objects (I have a prefab of the game object this class is attached to)
- OnDrag, EndDrag, BeginDrag methods
What I want to do in ItemUI - is sort of something like this:
public void HoverOn()
{
if(Item.Class == "Weapon")
{
WeaponItem WeaponItem = (WeaponItem) Item; // Downcast Fail
Damage.txt = WeaponItem.GetDamage() + "";
Damage.gameObject.SetVisible(true);
}
else if(Item.Class = "Clothing")
{
ClothingItem ClothingItem = (ClothingItem) Item; // Downcast Fail
Exposure.txt = ClothingItem.GetExposure() + "";
Exposure.gameObject.SetVisible(true);
}
ItemInfo.gameObject.SetVisible(true);
}
Question:
With the fact that I want my items in separate categories in XML, how would I accomplish showing Item information based on the subclass of the Item, if all I have at the time of access is a higher level Item class type?
ToString()
, but it certainly sounds like it's not deserializing to the specific types... – Jon SkeetXmlArrayItem("WeaponItem", Type=typeof(WeaponItem))
etc - but I don't know enough about XML serialization to know if that would work. I'd experiment with this outside Unity btw, just because it'll be a simpler environment to prototype in. – Jon Skeet