Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How do you create a customizable property system?

Discussion in 'Scripting' started by kebrus, Jun 4, 2015.

  1. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    Here's the deal, I have a property system where one Item can have many properties and each property has the potential of being different from one another even if they are from the same kind. For example lets say the item is a weapon and one of it's properties is the damage.

    In the current context we must be able to give each item one of the needed properties, so if it's a weapon it has damage but if it's a consumable it has not. So far we have been using scriptable objects to do this. We create a new instance of a property every time we need one and place it next to the item itself in the project folder.

    This soon became a problem because the amount of properties are growing so the project is filling up with instances of scriptable objects. We are now adding even more sub-properties (basically effects to each property) and the only solution we can think of is using scriptable objects yet again which will increase the amount of objects in the project exponentially.

    Does anyone knows a better way to deal with this? We thought of hierarchical class based systems but the problem with them is that you can't just add a list of configurable properties that have different different attributes in each of them.
     
  2. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Sounds like a job for a dictionary.
     
  3. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    maybe consider setting up the properties as Interfaces?
     
  4. fox4snce

    fox4snce

    Joined:
    Jan 25, 2014
    Posts:
    74
    Why aren't you just adding these components to the object?

    Like you would add a particle system.

    Or, why aren't you just creating a script and adding the script to the item?

    If these things don't sound reasonable, perhaps I misunderstand the problem.
     
  5. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    That would work, maybe I should have said that our game is working in multiplayer and we have a setup where we have as little scripts as possible at any given object, in this case, items only have one script that doesn't even have an update in order to save some performance, what it has is a list of scriptable objects that configure the object and its behavior. So if I want a certain object to do something when used or over time we grant that object and only that object a scriptable object that has the necessary code to do so. For example lets say I have a weapon that has a fire aura effect, the aura is a property that finds objects around the weapon to apply a fire damage effect. That said, scriptable objects actually lets us do exactly what normal scripts would, the only problem now is that we are rapidly filling the project folder with multiple instances of those scripts.

    Could you elaborate on that? How could i select a certain element from the dictonary and con configure it on the inspector? Or did I miss the use of it?

    The idea is to give the properties to a list of the main object, since "property" is a general concept how can I use interfaces to specify what property it is? Don't interfaces force you to use a set of methods? If one property is how much damage the item deals and the other a property of how much time a stun effect is applied, how can place them under the same list while being able to configure the two?
     
  6. Deleted User

    Deleted User

    Guest

    Having many components on an object might save on performance but it shouldn't impact multiplayer. Multiplayer performance is all about sending the bare minimum of messages required.
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You are totally barking up the wrong tree in terms of performance. Adding components beats scriptable objects any day if the week. My suggestion was a Dictionary<string, property>. This lets you add and remove properties at will, and search for a property by its string name.
     
    fox4snce likes this.
  8. fox4snce

    fox4snce

    Joined:
    Jan 25, 2014
    Posts:
    74
    I don't understand why any directories are filling up. They should either be directly attached to the object, or there should be one of each of these effects and it checks for all objects with it's tag or something similar. (Like BoredMormon says) and then acts accordingly. There would only be one instance of it.
     
  9. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    You got me concerned now because everything is setup that way. Why would scriptable objects be slower than mono behaviors? They are basically a trimmed down version of them. In fact we did a few tests in the beginning and Mono behaviors were indeed heavier.

    True, but what I meant in performance was the program performance, not exactly the multiplayer transmission of data. Because it's a multiplayer world the server needs to process a lot more stuff, thats why we want to keep it to a minimum.

    They are filling up because we are instancing scriptable objects in editor to specify different sets of data. Lets say I have one property of damage. For each object the damage is different so we need a new instance of that particular scriptable object to define each object damage. Because the idea is to have a dynamic system with multiple properties we end up having multiple instances of each property all over the place. Right now one single objects might have up to 10 different properties which would mean 10 different instances for one object alone.
     
    Last edited: Jun 8, 2015
  10. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,201
    Are you aware that you can nest scriptable objects?

    If you use AssetDatabase.AddObjectToAsset, you can nest one .asset file under another. So you'd have one main .asset for each item, and then add properties to it as subassets. That will help a lot with the project mess.

    I don't think you can add .asset files to prefabs, but I haven't actually tried that, so who knows. But you can definitely add the subproperties in this way - so if you have a damage property, you can add a damage type as a subasset.
     
  11. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    I'm with BoredMormon... why are you using ScriptableObject for any of this?

    This sounds like over engineering gone way out of hand.
     
    Kiwasi likes this.
  12. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Yup. If you are going to build your own custom system in a way that was never intended by the designers of Unity, expect your own custom headache. Good luck!
     
  13. RabenFutter

    RabenFutter

    Joined:
    Dec 30, 2012
    Posts:
    38
    Ok here is the methode which i use:

    Code (CSharp):
    1.  
    2. public Item[] allMyItems
    3. [System.Serializable]
    4. Public struct Item{
    5.    public int dmg;
    6.    public int type;
    7.    public Sprite icon;
    8.    public GameObject prefab;
    9. }
    you can put all your data inside the struct, even sub arrays and it is easly readable and changeable the editor.
     
    Last edited: Jun 8, 2015
    Kiwasi likes this.
  14. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    Thx, I didn't know about that, I actually tried but not using that so I dismiss it.

    It could very well be. The initial idea was to have data disconnected from the object itself so it could easily be saved and transmitted over the internet. Eventually we ended up with a system where data and functionality ended up in the same place and scriptable objects seemed to be the right choice.

    But I'm still concerned about mono behaviors, we made a few tests before and the performance was really bad. Keep in mind that the server needs to update a ton of stuff around each player so it has a lot of work to do. Am I right to assume the best solution to be a custom class or struct? Are monos actually faster than SOs? Why?
     
  15. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    In what way was the performance bad?

    I have had over a thousand entities constructed of several gameobjects each, with around 25+ MonoBehaviours attached to the gameobjects. I've never seen any "bad" performance. They have a performance impact, as would any object. But nothing extraordinarly impactful.
     
  16. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    We tested with something like 5k if I recall correctly. Just by adding the Update function that would kill the performance. And this is just one script with an empty Update function. Right now we are using a manager where items register their own update function through a delegate so we only update the items that really need to be update and they dynamically add and remove themselves when necessary.

    Granted, I could add monos without the update function and use the same delegate system but there is an overhead of useless information and functions that we don't need in the class, I can't see it being any faster than a regular class or a scriptable object. Scriptable Objects seemed to be the right choice because we only wanted their data.

    I'm now revising everything to see if it's feasible to refactor everything to a simpler concept but it feels like a complete waste of resources to have a ton of instantiate objects in the scene. With scriptable objects we were instantiating the objects only when they were being interacted with. So lets say I have 500 apples in my scene, they are all pointing to the same scriptable object and would only instantiate a new one if the character picks one. Basically every item in the game right now only has a pointer and it's void of any other information unless we specify we actually need it.
     
  17. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Well yes, 5000 update functions will kill performance.

    But ScriptableObject doesn't allow for Update function anyways.

    So don't have update functions on MonoBehaviours... no cost incurred.

    I don't see how having this delegate system in a MonoBehaviour vs a ScriptableObject impacts overhead of useless information. It's going to exist may it be in one or the other.
     
  18. JakeLeB

    JakeLeB

    Joined:
    Apr 18, 2013
    Posts:
    25
    Personally I'd create a Class for each Item type, Weapon, Consumable, then have another Class handle them and a script attached to a GameObject to create new instances of these on Start, you can even Serialize it to save them if you need to.
     
  19. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    Thx JakeLeB, I'm inclined to use that. I'm still not convinced with monos because these items need to get inside virtual containers and still retain their properties and as far as I know I can't have components without gameobjects and since they are just virtual it would mean to hide the objects somewhere which doesn't seem efficient at all.

    I wonder how bigger studios handle inventories.
     
    Last edited: Jun 12, 2015