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\$
  • \$\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\$ – Draco18s Nov 30 '17 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\$ – metamorphling Nov 30 '17 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 Nov 30 '17 at 3:26
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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.