# Can't access properties of a class

Sorry for the bad title, but I couldn't think of a way to word my problem for a title.

So I have this script, with two classes:

using UnityEngine;
using System.Collections;

public class GameItem {

public string ItemName { get; set; }

public string ItemDesc { get; set; }

public Item_Type ItemType { get; set; }

public int ItemValue { get; set; }

public int ItemID { get; set; }

public GameItem() {

}

public GameItem(string name, string desc, Item_Type type, int value, int id) {
this.ItemName = name;
this.ItemDesc = desc;
this.ItemType = type;
this.ItemValue = value;
this.ItemID = id;
}
}

public class Weapon : GameItem {

public string WeapEnch { get; set; }

public float WeapEffic { get; set; }

public Weapon() {

}

public Weapon(string name, string desc, string ench, float effic, int id) {
this.ItemType = Item_Type.WEAPON;
this.ItemName = name;
this.ItemDesc = desc;
this.WeapEnch = ench;
this.WeapEffic = effic;
this.ItemID = id;
}

public void Attack() {

}
}

public enum Item_Type {
APPAREL,
WEAPON,
TOOL,
CONSUMABLE,
BOOK,
MISC
}


And then I have a script for adding items to a list using the constructors:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class InventoryManager : MonoBehaviour {

public List<GameItem> GameItems { get; set; }

void Start () {
GameItems.Add(new Weapon("Sword", "It's just a sword.", null, 5, 0));
}

void Update () {
if(Input.GetButtonDown("Interact")) {
Debug.Log(GameItems[0].ItemName);
}
}
}


So when I create a new Weapon in the list, I can access everything from the GameItem class, but nothing from the Weapon class, even though I used the Weapon constructor. So I can't use the Attack () function, or access the Weapon's variables. How can I get around this problem?

The thing is that with your list you dont know if the element is a weapon or a apple. It's just a GameItem. To be able to use the weapon specific properties you need to retrieve the element and cast it back to a Weapon. For example the update in inventory manager will look like this.

 void Update()
{
if (Input.GetKeyDown("a"))
{
Debug.Log(GameItems[0].ItemName);
Weapon currentWeapon =(Weapon)GameItems[0];
Debug.Log(currentWeapon.ItemName);
currentWeapon.Attack();
}
}


What you can do is add a virtual method UseItem() to your GameItem class if you dont want it to be abstract(I would say that it should be). Example :

 public virtual void UseItem()
{

}


Then your weapons class you can do this :

  public override void UseItem()
{
Attack();
}


Now if you call UseItem on a elemet from your GameItems list and it was added as a weapon it go and call the Attack method from the Weapons class.

An alternative design is to use interfaces to specify different logical boundaries. For example

interface IItem
{

}
interface IWeapon : IItem
{

}
interface IFood : IItem
{

}
interface IRangedWeapon: IWeapon
{

}
void ProcessItems()
{
foreach (var item in Items)
{
if (item is IWeapon) //do some logic
if (item is IFood) //do some logic
if (item is IRangedWeapon) //do some logic
}
}


Note this is more or less a pseudo implementation. I also suggest you read up on Polymorphism. For a bit more in depth look and information check out this question

• Damn, you beat me with that edit. – Tyyppi_77 Jun 24 '16 at 8:05
• Which one I made like 3 of them :P – Uri Popov Jun 24 '16 at 8:06
• No you didn't (it shows only one for me), but with the addition of the virtual method. I had just written my answer on that approach, as your was missing that when I started typing. – Tyyppi_77 Jun 24 '16 at 8:08
• Ah yes It popped into my head after I added the interface solution and I jumped back to my PC to write it as quickly as I could saying to myself that someone will beat me to it :D – Uri Popov Jun 24 '16 at 8:10