Search Unity

Making class extensions changeable from the inspector.

Discussion in 'Scripting' started by dottonecioni, Jul 21, 2017.

  1. dottonecioni

    dottonecioni

    Joined:
    Jul 21, 2017
    Posts:
    8
    Hello everyone.
    To put it shortly,i have a problem with a thing i need to do. As,in my project,i need to have multiple Prefabs for many,MANY different items,and all these items have different reactions when subjected to the same input (e.g. a piece of wood can be picked up safely while a red hot piece of metal will scald your hands),i thought it best to have a "Base Item" class that would only be used so that it can be extended by the real item classes,and these classes will override methods however they like.That way,i can have a single function in my player controller that simply does,"If it's an item then call this function on it (for example,pick it up)",and then the item can apply the various things it does differently based on how that function has been overridden in that item's class.There's only one problem: I can't set the various item classes to the various item prefabs.This means that i cannot simply click on an item in the editor and attach the item script it needs to it: To do that,they'd need to be MonoBehaviours,wich they obviously can't be because they already extend BaseItem.I've tried working around this by making an "ItemContainer" Monobehaviour wich contained a "BaseItem" type variable wich i could then set from the editor,but,again,the editor won't let me set the classes that extend BaseItem: It just opens up the tab you get when you need to set something in an editor-modifiable field,and there's nothing in it.
    Could somebody help me with this,please? I realize that the description is probably poor,but it's a complex problem that's difficult to explain like this.
    Attached you will find a photo of the inspector tab for the "ItemContainer" MonoBehaviour as it currently is. example.PNG
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Unity has a big problem with inheritance and serialization. This official blog post is a must-read, and explains the situation nicely.

    Now, it's not all bad. If BaseItem is a MonoBehaviour, then you can inherit from that and attach the inherited stuff to GameObjects and prefabs and it all works. BaseItem can even be abstract. You can still do GetComponent<BaseItem>().DoThing() and get the PieceOfWood and have it's DoThing called.

    If you need the item classes to not be MonoBehaviours, things get much trickier, fast. If that's the case, give some more details about what game you're making so it's easier to give advice about an appropriate approach.
     
  3. dottonecioni

    dottonecioni

    Joined:
    Jul 21, 2017
    Posts:
    8
    Well,thanks a lot! I don't think i can make BaseItem a MonoBehaviour,since i also need it to make Inventory and Database/Dictionary lists/dictionaries. This is also one of the the reasons why i wanted to have all the Item classes extend a BaseItem,so that i could make a BaseItem list that could still "Hold" all the different extending classes without problems. I'll take a look at the blog post,obviously; I'll evaluate the situation then and see if its convenient to put half a day into making a more accurate and detailed thread without turning it into an unreadable mess. Thanks!
     
  4. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @dottonecioni

    Hi, I'm too in process of learning how to create customizable items. Creating a proper inventory / item system that accepts different kind of items isn't that easy in Unity as it seems first. Simply put I came to realize that Unity serialization doesn't like custom classes.

    Unity basic tutorials don't do favor explaining base classes and how to create sub-classes out of them, as these won't seem to work very well at all with Unity Inspector / Editor, especially with collections like Lists and Arrays. If you create an Animal class, try putting Cat : Animal class instances in an array or a List (for this you'd need editor script), you'll end up having base class animals in your array after Unity does it's editor serialization thing when Play/Stop is pressed.

    You could also consider using ScriptableObjects. Not sure if it would help with what you are trying to do, but at least you don't need GameObjects, you can make multiple similar assets out of ScriptableObject class, or just instantiate them run-time.

    They have similar benefits as MonoBehaviours in regards to Unity serialization and inheritance, like @Baste mentioned, Monobehaviours don't suffer from this serialization stuff.

    It is also possible to add ScriptableObjects as children of other ScriptableObject to avoid having too many assets in your project, but this needs a little bit of editor scripting.

    Also, I'm thinking it might be better to create some sort of component / attribute based system, instead of making derived items for different items, it might be better to compose items out of different attributes and features they need. But I don't have anything more helpful to say about this, as I'm still in process to figure out how to do this!
     
  5. dottonecioni

    dottonecioni

    Joined:
    Jul 21, 2017
    Posts:
    8
    I am using ScriptableObjects for my items,but,it still seems that i can't use them to select a base class' extensions from the editor,wich is my problem.