0
\$\begingroup\$

I have the following:

public class Item
{
    [SerializeField]ItemData _data;

    public ItemData data { get { return _data; } }
}

public class Weapon : Item
{
    [SerializeField]WeaponData _data;

    public WeaponData data { get { return _data; } }
}

public class ItemData : ScriptableObject { }
public class WeaponData : ItemData { }

It seems like a pretty common setup to me, data is separated from logic classes - and I can use single scriptable objects to define stats for alot of items.

However, Unity gives me this error message:

The same field name is serialized multiple times in the class or its parent class. This is not supported:

I understand what's going wrong, but I don't get how to work around it, I want the data objects to inherit so I don't need to keep two (or more, further into inheritance) separate data objects per weapon.

I also need the item inheritance for inventory/merchant list management. Using hiding screws up the serialization of the baseclass, which means I can't create default items - not feasible.

The issue is the same when using public instead of [SerializeField].

Any pointers?

\$\endgroup\$
3
  • \$\begingroup\$ My immediate thought is "if you need to do this, you're almost certainly doing something wrong." e.g. if I have a Weapon object instanced, called weap and I do weap.data, what should I get back? An ItemData or a WeaponData? \$\endgroup\$ Commented Nov 30, 2017 at 2:28
  • 1
    \$\begingroup\$ You are on the right track(logic-wise), but looking at the code I think some misunderstanding of inheritance concept is taking place. Serialization message just misleads you from the real problem(redeclaration of the same field in derived class?). I strongly advice looking at Unity provided example of inheritance, this might help unity3d.com/learn/tutorials/topics/scripting/inheritance \$\endgroup\$ Commented Nov 30, 2017 at 2:28
  • \$\begingroup\$ Whether or not this is the right approach, usually serialization issues like this stem from the variable name itself. Typically auto serialization generates a getter and setter based on the variable name. Just like in a class you cant have two variables with the same name in the same scope, the same applies to inheritance without override. \$\endgroup\$
    – Stephan
    Commented Nov 30, 2017 at 3:26

1 Answer 1

2
\$\begingroup\$

It looks to me like you might actually want an IItem interface, or abstract class, a bit like this:

// Establish the contract that any "Item-ish"
// object must be able to provide ItemData
// through a standard property (could be abstract
// instead of an interface if you have code or
// members you want to share between item types.
public interface IItem
{
   public ItemData data { get; };
}

public class Item : IItem
{
    // Expose an inspector field of the concrete
    // type we want - this will accept ItemData
    // or any type inheriting from it.
    [SerializeField] ItemData _data;

    // Return this inspector-set property as our
    // IItem-mandated data property  
    public ItemData data { get {return _data; } }
}

public class Weapon : IItem
{
    // Expose an inspector field of the concrete
    // type we want - this will accept only WeaponData
    // not ItemData instances that aren't weapon-specific.
    [SerializeField] WeaponData _data;

    // Return this specialized WeaponData as an ItemData
    // when requested.
    public ItemData data { get {return _data; } }
}

Now any code can work with a mixed group of Items and Weapons by treating them all as items. It can also use casts or the as keyword to get at Weapon/item-type-specific data when it knows it has a particular item type.

If you go much further with this, you may want to consider applying the principle of Composition Over Inheritance. Especially in Unity's setup, this can give you a lot more flexibility - letting you make things like a spiked shield that has both a DefensiveItem component and a WeaponItemComponent, without needing to refactor two separate branches of the inheritance hierarchy to handle such exceptions and hybrids.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .