Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Prefabs and Dictionaries

Discussion in 'Editor & General Support' started by baylor, Jun 6, 2010.

  1. baylor

    baylor

    Joined:
    Oct 29, 2009
    Posts:
    25
    Two questions

    1. Is there a doc explaining what, precisely, prefabs are and how they work?
    My guess - they are normal objects that, when put in a prefab, serialize to a disk file somewhere and when Unity loads, Unity sets their state from the seralized data. Therefore, prefabs should work with anything that serializes. i'm assuming this means the object must implement ISerializable

    2. Any idea how to use Dictionary<> in a prefab?
    We moved from loading scripts to prefabs and the game went to hell. After testing, looks like prefabs don't work with dictionaries, at least not the built in C# one. Works at runtime, but restart the game and the prefabs are empty. Not sure but sounds like C# dictionaries aren't serializable (can't to XML, other info seems unclear about to binary; not sure how to write test to work with Prefabs)

    As an accompaniment to #2, does Unity provide an alternative Dictionary class that does work with prefabs? i noticed it had a few other custom Unity classes, figured it doesn't hurt to ask
     
  2. rytis

    rytis

    Guest

    Joined:
    Jul 11, 2008
    Posts:
    138
    #1: I think closest is: http://unity3d.com/support/documentation/Manual/Prefabs.html

    #2: Unity uses internal serialization system to persist values. It does not work on all types. Generic List is supported, Dictionary is not. Could get ugly if you use those a lot, but you could use two lists to simulate dictionary.
     
  3. baylor

    baylor

    Joined:
    Oct 29, 2009
    Posts:
    25
    Thanks rytis. Sadly for us, we use tons of dictionaries for both AI values and resource management. We really like reference by name. Our game is an (oddly enough) AI-heavy fashion game with several hundred pieces of clothing. We add pieces all the time so tracking with integer index values into an array has been awful. We have a lot of code that looks sort of like:

    behavior.face = faceDictionary["perplexed"];
    behavior.animation = animations["shakeHead"]

    We could use two arrays but that would require a linear scan of the first array (and in the case above, hundreds of string compares) to find the key, which isn't very efficient

    Is there any way to make prefabs work with dictionaries? For example, could i subclass dictionary and implement some interface unity needs (ISerializable or whatever Unity wants)?

    Alternately, it seems like for animations we're able to get items by name. For example:
    Animation.CrossFade("string name of animation")
    i'm not sure what Unity is using that allows it to get objects by name. Does Unity have its own internal dictionary class? Is this just two lists and a linear search?
     
  4. rytis

    rytis

    Guest

    Joined:
    Jul 11, 2008
    Posts:
    138
    Can you do it with enums? Having things in strings is generally bad idea because your code does not get checked at compile time.

    enum Animations {ShakeHead, Walk}
    behavior.animation = animations[Animations.Walk];

    It would be the cleanest and fastest way.

    Also with some effort, you can have two Lists one for keys one for values, have the lists sorted, and then search would be of O(log n) complexity, which is more than good enough for hundreds of items.

    First sort lists. You'd need to implement your own sort function. List<>.Sort won't do cause you need to also track values array. Having your own function you can sort keys List and be moving around values from both keys and values lists at same time.

    Then e.g. GetAnimation("ShakeHead") -> (do binary search in keys list and return item from values list with that index).

    To make it cleaner you could put this into a separate class. Beware that you need to inherit that class from ScriptableObject, and either make fields you want to serialize public, or keep them private and add attribute [SerializeField]. To confuse you more, this class would need to somehow be in the scene. E.g. attached as a component to some game object, or be a public or private [SerializeField] in some class that is attached to a game object.

    Hope this helps at least a bit.
     
  5. duke

    duke

    Joined:
    Jan 10, 2007
    Posts:
    763
    Alternatively, and without having tried it, you could be really tricky and store raw JSON or BSON data in a variable and have Unity serialize that to get around it's ..retardation.
     
  6. laurie

    laurie

    Joined:
    Aug 31, 2009
    Posts:
    638
    I'm not quite clear what that question means... use a Dictionary how? It sounds like you're expecting run-time changes to the dictionary content to be saved back to the prefab, and visible the next time the game is started? If that's what you're expecting, I'm afraid prefabs don't work like that; they aren't a persistence mechanism. A prefab is just an assembly of GameObjects/Components and their state at design/build time. If you instantiate a prefab, then make changes to the state of the instantiated object, those changes are not automatically saved, either to the prefab or anywhere else.

    Sorry if I'm missing the point; if so, you might want to try explaining the workflow you're looking for in more concrete terms.