- Home /
Inventory Programming: Derived Class Issue (C#)
Hello everyone!
I think this might be more of a general programming problem than a Unity one, but I hope some of you fine folk will be able to help me out.
I am working on an inventory and item system for my game. The basic idea at first was to have a base Item class, and then derive the types of items for specific classifications. For example:
Item
Weapon : Item
Shield : Item
Broadsword : Weapon
Iron Shield : Shield
And so on and so forth, this way each item only would have properties it needs and not a bunch of irrelevant information.
But then I run into issues when making my inventory. It would be a list of items:
public List<Item> inventory;
inventory.Add(new Broadsword);
Debug.Log(inventory[0].damage); //ERRORZ as the Item class doesn't have this var
The only idea I have for solving this at the moment is to cast the item back to it's original type when the information is need, using a variable to determine what to cast to, like so:
if (inventory[0].itemType == "Weapon")
Weapon myWeapon = (Weapon)inventory[0]
Debug.Log(myWeapon.damage) //Huzzah, we have the value!
This seems a bit... inelegant to me. I was wondering if anyone had any other ideas on fixing this particular problem. Also related, I would like to be able to see the derived classes' public variables in the Inspector when looking at the Inventory script, but currently it would only show fields that Item has. I assume I would need a custom inspector to fix this (or is this fixable at all)?
itemType looks to be slow and useless. If you really need it, use an enum, not a string. http://msdn.microsoft.com/en-us/library/scekt9xw(v=vs.71).aspx http://msdn.microsoft.com/en-us/library/cscsdfbt(v=vs.71).aspx
Looks like I wouldn't need it! Using 'is' works as a better replacement. Thanks!
Answer by Owen-Reynolds · Jun 15, 2013 at 01:15 AM
A few comments before this gets closed for being too general:
You would have a specific master list of Weapon, another of Shield and so forth, where you should be able to see all the variables. Since they are also Items, you can add them to an Item list as you spawn them.
Another way to check itemType is cast then null check: Weapon ww = (Weapon)A; if(A!=null)
. You have to cast anyway, to look at the weapon properties, so this usually works better.
IronShield would probably not be a subclass of Shield. It would be a type of shield with different stats.
The first time you make real derived classes is usually a learning experience, and needs to be junked after.
Thanks for the information!
I take it from your guys' responses that casting back to the Weapon class is the way to go in terms of retrieving the properties. I appreciate the explanations on how else to do this: my program$$anonymous$$g is a bit rusty! Your method seems to make the most sense so far.
You are correct in the fact that the specific items shouldn't be classes of their own (they don't introduce any new properties after all..) so I did a bit of looking, and found something that fits my fancy. I made custom assets for my item types following this tutorial (http://www.jacobpennock.com/Blog/?p=670). I think this is a better approach, especially since it makes it easy to edit them in the inspector.
Thanks again. :)
If you read up on the history of why classes were made, we used to have to make a type variable and "if(type==weapon)... " the way you were suggesting. But with proper classes, the system atomically does that for you.
For example, subclassing and virtual functions allows you to write Item[0].equip()
and the system will automatically check the type and equip appropriately (or do nothing for a junk item.) If you aren't using that trick, subclasses are just cutesy, and any other way is just as good.
Answer by GerryM · Jun 15, 2013 at 04:20 PM
Apart from the discussed issues of object oriented design, you might want to consider using "as" for a slightly more elegant access solution (just the last line):
using UnityEngine;
using System.Collections.Generic;
public class Baseclass {
public int baseVal;
}
public class Derivative : Baseclass {
public int derVal;
}
public class Inherit : MonoBehaviour {
public List<Baseclass> inventory;
void Start() {
inventory = new List<Baseclass>();
inventory.Add(new Derivative());
(inventory[0] as Derivative).derVal = 5;
Debug.Log ("Val ="+(inventory[0] as Derivative).derVal);
}
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
How to make public variable read-only during run-time? 3 Answers
Get game view window current width & height in script 1 Answer
Accessible collection of Type 1 Answer