Search Unity

Full Inspector: Inspector and serialization for structs, dicts, generics, interfaces

Discussion in 'Assets and Asset Store' started by sient, Jan 23, 2014.

  1. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Also I needed to add a Warning comment to an InspectorButton, but is not supported. I tried to add AttributeTargets.Method to InspectorCommentAttribute, but it doesn't work.
     
  2. dl_studios

    dl_studios

    Joined:
    Oct 14, 2012
    Posts:
    76
    Hi Sient,

    Thanks for getting in touch about my other question. The doc links were helpful.

    I have a new question. I'm getting this error.

    Repeated data (a list, collection, etc) has inbuilt behaviour and cannot use a surrogate
    ProtoBuf.Meta.MetaType.BuildSerializer () (at c:/Dev/protobuf-net/protobuf-net/Meta/MetaType.cs:417)

    This is the code. Its just a test to see if I can get data to serialize.
    Code (CSharp):
    1.  
    2.         string playerPrefPath = PersistentInfo.GetPlayerPrefPath();
    3.         _FullPath = playerPrefPath + _TestFileName;
    4.  
    5.         if(!Directory.Exists(playerPrefPath))
    6.         {
    7.             Directory.CreateDirectory(playerPrefPath);
    8.  
    9.         }
    10.  
    11.         Debug.Log("Object state has been saved to " + _FullPath);
    12.  
    13.   int savedvalue = 1324014;
    14.  
    15.         // Get the serialized state of the object
    16.         string content = SerializationHelpers.SerializeToContent<int,ProtoBufNetSerializer>(savedvalue);
    17.  
    18.  
    19.         // Write it out to disk
    20.         File.WriteAllText( _FullPath , content);
    I'm not sure what is causing the issue. The serialization works fine in a new project, but when I actually try to use it with my current project it gives me that error.

    Thanks for taking a look at this.

    Update: I've been reimporting packages to see if there was some sort of conflict. Turns out something in many of Pathological's packages causing the error to throw. I haven't been able to figure out what exactly it is. It's a three in one package PoolManager, UnityConstraints, and TargetPro. I've deleted them out one by one and the errors always persist until the last package is deleted irregardless of which package I leave until last.

    Update2: After more experimenting I can say that it has something to do with BaseBehaviour. When I simply use ProtoBuf-api to save things work fine. The errors come whenever I use SerializationHelpers.SerializeToContent<T,ProtoBufNetSerializer>(value);

    Looking at BaseBehaviour in your package I'm surprised to find two BaseBehavoiurs in the Full Inspector Package. One is the normal BaseBehaviour the other is a generated BaseBehaviour<JsonNetSerializer>generated by Full Inspector as part of the serializer. I changed BaseBehaviour<JsonNetSerializer> to BaseBehaviour<ProtoBufNetSerializer> to see if by chance that made a difference but it didn't. I'd really like to use your api but I'm still scratching my head as to how to get the packages to play nice.
     
    Last edited: Aug 26, 2014
  3. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Sorry about that, but attribute property editors are not currently supported on methods (see this corresponding issue).

    For the moment, you can just use a "fake" field to do this, ie,

    Code (csharp):
    1.  
    2. public class Behavior : BaseBehavior {
    3.     [InspectorOrder(0), ShowInInspector, InspectorHidePrimary]
    4.     [InspectorComment("Warning message!", CommentType.Warning)
    5.     private int _inspectorProxy;
    6.  
    7.     [InspectorOrder(1)]
    8.     [InspectorButton]
    9.     public void Method() {}
    10. }
    11.  
    I'll take a look at this, but it looks like you also sent a PM. Let's carry on the conversation there.

    Thanks.
     
  4. psxcode

    psxcode

    Joined:
    Jan 26, 2014
    Posts:
    26
    Hi. Full Inspector is amazing.
    But one thing is really annoying.
    I have a lot of arrays of classes that holds arrays.(And here FI really helps me)
    And I like the feature that I can collapse(fold) those arrays.
    But when I press Play button in Editor - FI unfolds ALL arrays.
    Please fix this. FI should remember folding.
    Also it unfolds everything on recompile.
     
    Last edited: Aug 27, 2014
  5. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Please go into FullInspector2/fiSettings.cs and set EnableMetadataPersistence to true.

    This is currently off by default because it may slow down recompilation and entering play mode. Additionally, if you ever have a cyclic object graph that is not caught by FI (which is only the case for struct cyclic graphs), you're going to have to clear your metadata or delete the GameObject that had the cyclic graph (or just don't save the scene and reload it).
     
  6. psxcode

    psxcode

    Joined:
    Jan 26, 2014
    Posts:
    26
    Thank you very much. This is much better now. A little freeze on Run, but I dont need to fold everything back and search the line i was editing
     
  7. psxcode

    psxcode

    Joined:
    Jan 26, 2014
    Posts:
    26
    Why Limits Attribute located in FullInspector.Samples.Other.Limits namespace.
    It is used quite often. Why not place it into common FullInspector namespace.
     
    rakkarage likes this.
  8. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I'll look into promoting it to the core namespace (as a module, though), but it is intended as a sample for how to write an attribute property editor.
     
  9. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Could you make it so that property-setters only be called when the field is actually manipulated instead of each frame rendered? Running logs I see it being called at each update (even when just scrolling etc.). A setting would also be an option I guess, and if so maybe the possibility to only have it called when the newValue != oldValue.

    Would be great :)
     
  10. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Hey Maisey,

    What version of FI are you on? This should be the case for 2.4. Let me know if it isn't.

    Thanks
     
  11. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    I was just about to edit, since I still got the trial! :) But it looks promising so far! Great job.

    Another question... What are your views on others bundling this in their own plugin, which in turn is sold on the asset store? For a part of the profit of course! Maybe Unity has a nice way of handling that?

    Thanks!
     
    Last edited: Sep 4, 2014
  12. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Hey Maisey,

    If you're interesting in bundling FI, then it's best to get in contact with me via email and we can discuss something in private.

    Thanks
     
    Maisey likes this.
  13. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Of course, just wanted to check if it's a possibility! It's not certain yet though, but then I'll throw you a PM whenever we plan to do so!

    Thanks! :)
     
    Last edited: Sep 6, 2014
  14. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Coming in 2.5: Serialization Migrations!

    You will now easily be able to change what active serializer you use in your project. For example, if you've been using BinaryFormatter but want WP8 support, you can easily change all of your existing serialization data into Full Serializer's format using this new utility.

    serialization migration window.PNG
     
    mcmorry likes this.
  15. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    FI is getting more and more awesome with each update. Kudos.

    Full Serializer is really amazing work and truly a gift. It's taken away so much serialization pain.

    I understand that serializing Unity objects to disk is not supported. Since FI has become the Ultimate serialization solution for Unity, it would be really awesome if FI could provide some working example scenes of how to tackle some common use cases that involves the serialization of Unity Objects to disk.

    Cheers.
     
  16. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Thanks!

    I have very experimental code written out tacking this issue, but the biggest problem is how to handle the Unity lifecycle. I don't have a good way to inject serialization data into an object before Awake() is called (Facade has a similar problem when working with Component types). The typical solution is to just use FormatterSerivces, but Unity complains when you use it w.r.t. UnityObject types.

    If you just want to try serializing some UnityObject types, use a custom ISerializationOperator (to get rid of the NotSupportedExceptions) and then fsMetaType.Get(...).SetProperties(...) as appropriate when you need to customize how serialization of a certain UnityObject works (ie, Camera). You'll also have to figure out how to handle construction (try writing a custom fsConverter and utilize fsSerializer.Context to store the GameObject to add the Component to).

    Here's an example fsConverter (from my experimental code):

    Code (csharp):
    1.  
    2. using FullSerializer;
    3. using FullSerializer.Internal;
    4. using System;
    5. using UnityEngine;
    6.  
    7. namespace FullInspector.Serializers.FullSerializer {
    8.     public class ComponentConverter : fsConverter {
    9.         private fsReflectedConverter _reflected = new fsReflectedConverter();
    10.  
    11.         public override bool CanProcess(Type type) {
    12.             return typeof(Component).Resolve().IsAssignableFrom(type.Resolve());
    13.         }
    14.  
    15.         public override bool RequestCycleSupport(Type storageType) {
    16.             return false;
    17.         }
    18.  
    19.         public override bool RequestInheritanceSupport(Type storageType) {
    20.             return true;
    21.         }
    22.  
    23.         public override fsFailure TrySerialize(object instance, out fsData serialized, Type storageType) {
    24.             _reflected.Serializer = Serializer;
    25.             return _reflected.TrySerialize(instance, out serialized, storageType);
    26.         }
    27.  
    28.         public override fsFailure TryDeserialize(fsData data, ref object instance, Type storageType) {
    29.             _reflected.Serializer = Serializer;
    30.             return _reflected.TryDeserialize(data, ref instance, storageType);
    31.         }
    32.  
    33.         public override object CreateInstance(fsData data, Type storageType) {
    34.             // note you need to set the GameObject context value before starting deserialization
    35.             // with serializer.Context.Set(gameObjectReference);
    36.             return Serializer.Context.Get<GameObject>().AddComponent(storageType);
    37.         }
    38.     }
    39. }
    40.  
     
    Last edited: Sep 7, 2014
  17. MaxEden

    MaxEden

    Joined:
    Jun 22, 2013
    Posts:
    82
    Hi! Is Opt-in option ignored?

    Code (CSharp):
    1. [JsonObject(MemberSerialization.OptIn)]
    2.     class TestBehavior: BaseBehavior{
    3.        
    4.         [JsonProperty]
    5.         private int _field;
    6.  
    7.         public int Property
    8.         {
    9.             get { return _field; }
    10.             set
    11.             {
    12.                 if (_field != value)
    13.                 {
    14.                     _field = value;
    15.                 }
    16.             }
    17.         }
    18.     }


    Or am I doing something wrong?
     
  18. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    BaseBehavior serialization runs through FI-specific serialization logic. Serializers have the ability to register an alias for `[SerializeField]` (the Json.NET serializer registers `[JsonProperty]`), which is why you see `_field` being serialized.

    Because Json.NET is not being used to serialize `TestBehavior` (it was in FI1 and that caused a whole bunch of pain that FI2 avoids) annotations like `[JsonObject(MemberSerialization.OptIn)]` do not work.

    Please note that Json.NET is being used to serialize all non-UnityObject types (and a number of types that Unity serializes itself).

    Let me know if that clarifies things or if you have other questions. Thanks!
     
  19. MaxEden

    MaxEden

    Joined:
    Jun 22, 2013
    Posts:
    82
    Thanks for the answer!
    Is there a FI-specific way to enable Opt-In serialization?
    In my particular case I want to serialize just internal field, but not the property.

    Also is there way to use [JsonProperty("PropertyName")] to make aliases in case of refactoring?
     
  20. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Code (CSharp):
    1. [Obsolete("This setting is now ignored")]
    2. public static bool InspectorAutomaticallyShowPublicProperties = true;
    This is exactly what I need to do but then I see that this is obsolete..? Why? I can't have all my public properties in base-classes etc. shown in the inspector, and I don't want to manually edit already finished classes to [HideInInspector]... Could you please re-add this? Really can't see why a setting for it is a bad thing.

    Edit.
    Two issues:
    When I add a new script, FullInspector will call "Restore State" first of all, which in turn will reset all properties to their types default value (0 for int etc.). This will thus ignore any default values I've manually set on the backing field, eg:
    Code (CSharp):
    1. [SerializedField] private Vector3[] m_Corners = new Vector3[4]; // <---- This will be set to Vector3[0] instead...
    2.  
    3. public Vector3[] Corners{
    4.       get{ return m_Corners; }
    5. }
    6. public int Width{
    7.      get{ return rectTransform.deltaSize.x; } // <---- This will be ignored, even though width is 100 when created.
    8.      set{
    9.             Vector2 size = rectTransform.deltaSize.x;
    10.             size.x = value;
    11.             rectTransform.deltaSize = size;
    12.      }
    13. }
     
    Last edited: Sep 10, 2014
  21. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Currently there is no way to specify opt-in serialization. However, FI allows you the separate the serialized data from the inspected data, so you can make a field [NonSerialized, ShowInInspector] and it will display in the inspector without being serialized.

    Serialization rename support will be included in the next release (via Unity's [RenamedSerializedData] annotation), though it will only work on BaseBehavior/ScriptableObject derived types (you need to use the standard migration support in other serializers, ie, Full Serializer offers true versioning support).

    Rename the setting to

    Code (csharp):
    1.  
    2.         /// <summary>
    3.         /// Should public properties/fields automatically be shown in the inspector? If this is
    4.         /// true, then only properties annotated with [ShowInInspector] will be shown.
    5.         /// [HideInInspector] will never be necessary.
    6.         ///
    7.         /// *PLEASE NOTE* this does not impact how data is serialized! Public properties/fields
    8.         /// will *still* be serialized!
    9.         /// </summary>
    10.         public static bool InspectorRequireShowInInspector = true;
    11.  
    and go into FullInspector2/Core/Utility/InspectedMemberFilter.cs and change ShouldDisplayProperty (line 73) from

    Code (csharp):
    1.  
    2.         private static bool ShouldDisplayProperty(InspectedProperty property) {
    3.             var memberInfo = property.MemberInfo;
    4.  
    5.             if (memberInfo.IsDefined(typeof(ShowInInspectorAttribute), inherit: true)) {
    6.                 return true;
    7.             }
    8.  
    9.             if (memberInfo.IsDefined(typeof(HideInInspector), inherit: true)) {
    10.                 return false;
    11.             }
    12.  
    13.             return
    14.                 InspectedType.IsSerializedByFullInspector(property) ||
    15.                 InspectedType.IsSerializedByUnity(property);
    16.         }
    17.  
    to

    Code (csharp):
    1.  
    2.         private static bool ShouldDisplayProperty(InspectedProperty property) {
    3.             var memberInfo = property.MemberInfo;
    4.  
    5.             if (memberInfo.IsDefined(typeof(ShowInInspectorAttribute), inherit: true)) {
    6.                 return true;
    7.             }
    8.  
    9.             if (fiSettings.InspectorRequireShowInInspector) {
    10.                 return false;
    11.             }
    12.  
    13.             if (memberInfo.IsDefined(typeof(HideInInspector), inherit: true)) {
    14.                 return false;
    15.             }
    16.  
    17.             return
    18.                 InspectedType.IsSerializedByFullInspector(property) ||
    19.                 InspectedType.IsSerializedByUnity(property);
    20.         }
    21.  
    If you're adapting Full Inspector to an existing project, I would recommend using fiValue (in 2.5, send me an email if you'd like a build) instead, as it is more flexible and allows you to continue deriving from MonoBehaviour.

    Thanks!
     
  22. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Try initializing the Vector3 in a Reset() method. Unity is likely actually the one that is resetting m_Corners -- inline construction logic like that goes directly into the constructor, which Unity explicitly says to avoid doing construction work in.

    I'm confused by your second example though. Can you post a larger bit of code?
     
  23. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Actually, looking at the callstack it is getting reset from the "RestoreState"-method. Also it just started acting this way after implementing Full Inspector so the issue was not present before.

    The second example is just a property forwarding another property (from another component), which already has a value when my component is attached. The problem I see (guess from looking at the callstack) is that you do not serialize the component first time when created but instead call "ResetState", which will (as the name suggests) reset all fields/properties.

    But yes you are correct that for consistent behaviour it should be set in the reset-method also (since in C# you normally do it with field initializers so it's a good habit with both IMO).

    Edit. I think I'm confusing myself on this... Think I'm just getting used to the idea of serialising properties... Is there a way to expose a property WITHOUT serialising it? I just want the setter to be called when changing the value, not actually setting it to a default value etc. when created (as in this case it is already serialised somewhere else, in the RectTransform-component).
     
    Last edited: Sep 10, 2014
  24. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Okey I think I need a new post for this...

    One thing I see is the bundling of fields & properties, as if they should behave the same. Instead of having fields behave as normally (as done in default unity), you add settings that change the behaviour of BOTH fields of properties... You should definitely separate them, and have settings for them respectively (or only for properties).

    What I need is: A setting to make properties only be exposed if explicitly said so (ShowPropertyInInspector or equivalent) and a setting to tell if public properties should be serialised by default (in this case I want to set false, since otherwise it will break the behaviour of already created classes and harden the process to implement Full Inspector).

    Thanks of the quick responses!
     
  25. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I think one of the nice things about Full Inspector is that it unifies fields and properties -- conceptually they are very similar. A breaking change I may make in the future is to only automatically display/serialize auto-properties.

    I've tried hard to not have any settings that adjust any runtime behavior of Full Inspector -- fiSettings is something that can be changed locally on each computer depending on your preferences (in general, there are a few exceptions -- which are very likely to also get deprecated). One thing I really want is for serialization behavior to remain consistent. Unfortunately, this means that I have no plans to introduce a setting to disable automatic property serialization. I deprecated the public property display settings for a similar reason.

    However, what I can recommend is that you look at fiValue. It's included in 2.5 (just send me a PM or an email if you'd like a build). It allows you to use Full Inspector on MonoBehaviour derived types (with just a little bit of boilerplate code), so you will not have to add [NotSerialized] to your properties.
     
  26. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    I agree on this concept, however the issue is when you try to implement/ "un"-implement Full Inspector from long time developed projects, as FI "force"-changes the concept of how Unity does it (which as we know have no serialisation-support for properties). That's why I recommend at least having a setting/settings so that Full Inspector can behave exactly like Unity, if chosen, and from there you manually specify which parts you want to do what with (like manually marking which properties should be exposed &/or serialised). This would definitely ease the headache if you don't want to 100% rely on FI.

    About only automatically serialising auto-properties is something I think is essential (or again, having it optional) since the behaviour of an explicitly declared property is unknown, and as you've seen in my case (which is very usual) a property is not just always a simple getter/setter for a private backingfield but instead a forwarder for values from another component.

    I guess this is an attempt solve this, which I like, but I still hold on to the idea of having the possibility to transparently add FI to a project already in process (again, to avoid the tight coupling of FI to you project).

    Anyways, just my two cents! Great job on the plugin though! Count on Unity contacting you! ;)

    Edit.
    To give some perspective: I just hade to add [NotSerialized] to about 20 properties in total to remove a handful of random-bugs caused by setters being called all over the place (since one property changed its value depending on another property etc.). So I can't stress enough that you make the change to only automatically serialize auto-properties... :)

    Edit IMPORTANT.
    About the issue of resetting serialised fields (specific types, maybe only collections?) to the types default value instead of the default initialised value as set in code, I've localised the issue to Full Inspector. Look at the attached repro and you see how FI behave differently (& incorrectly) when resetting/creating components with serialised fields who have a specific default value.
    Also, it doesn't matter if I set it in Reset(), FI will be called after and wrongly assign the field. This stops me from proceeding with FI so please have a look at this ASAP, thanks!
     

    Attached Files:

    Last edited: Sep 11, 2014
  27. MaxEden

    MaxEden

    Joined:
    Jun 22, 2013
    Posts:
    82
    Um... I'm here just to confirm that I'm now going through all the Maisey's issues including the Reset() bug.
     
    Maisey likes this.
  28. jrhee

    jrhee

    Joined:
    Dec 5, 2013
    Posts:
    74
    Is there a way to ensure a Dictionary in a class that doesn't inherit from BaseBehavior gets serialized using FI? In the example below for example, the debug output for attribute count is always zero, even when I can entries for it in the inspector.

    Code (csharp):
    1.  
    2. [System.Serializable]
    3. public class CharacterData {
    4.     Dictionary<string, int> attributes;
    5. }
    6.  
    7. public class CharacterManager : BaseBehavior{
    8.     public CharacterData testData;
    9.     void Start() {
    10.         Debug.Log(testData.attributes.Count);
    11.     }
    12. }
    13.  
     
    Last edited: Sep 11, 2014
  29. jrhee

    jrhee

    Joined:
    Dec 5, 2013
    Posts:
    74
    Disregard above, there was an issue with my data setup. Working now!
     
  30. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Just another issue I found (or somehow inconsistency):

    If you have a custom, serializeable class with a public (serialized) property, FI will reinstantiate a copy of that object each time the property is changed. As seen in the attached repro, every time I drag the property "dragMeProp" it will reinstantiate a new instance of the custom class with the new value for that property. This differs from how Unity (and FI) behaves when a simple field is manipulated, as the reference will stay the same.

    Code (CSharp):
    1. [System.Serializable]
    2. public class CustomObject {
    3.     public CustomObject(){
    4.         Debug.Log("Instantiated");
    5.     }
    6.  
    7.     [SerializeField]
    8.     private int dragMe = 0; // <--- If this is changed in inspector, the reference to this "CustomObject" wherever it is declared will remain the same.
    9.  
    10.     public int dragMeProp{ // <---- If this is changed however, the whole "CustomObject" is reinstantiated and delegates will lose all listeners
    11.         get;
    12.         set;
    13.     }
    14. }
    The problem with this inconsistency is that say for delegates used while in editor (and not playing) will get reset to null and drop all the listeners... I can't keep resetting all the listeners each time, once on recompile is quite enough! :)

    Also, undo doesn't work while in play-mode for neither properties or fields (is intentional?). However the above issue doesn't occur while playing... Coincident?

    Edit.

    Okey, I've narrowed it down further for you:

    If I change the above class to the following, the effect will be reversed (changing the field will reinstantiate it, changing the property will not):

    Code (CSharp):
    1. [System.Serializable]
    2. public class CustomObject {
    3.     public CustomObject(){
    4.         Debug.Log("Instantiated");
    5.     }
    6.  
    7.     public int dragMe = 0; // <--- Now this will instead cause the object to reinstantiate
    8.  
    9.     [SerializeField]
    10.     private int dragMeProp{ // <---- And this will not...
    11.         get;
    12.         set;
    13.     }
    14. }
     

    Attached Files:

    Last edited: Sep 11, 2014
  31. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    For not 100% relying on FI, I strongly recommend using fiValue<T>.

    I've added auto-properties to the blocking issue list for 2.5. I appreciate the feedback!

    I have a quick-fix for the reset bug, but I haven't had a chance to do a full test suite. The fix is slightly tricky because it relates to prefabs, but iirc it should be fine.

    Go into FullInspector2\Core\Editor\IBehaviorEditor.cs and change line 111 from

    Code (csharp):
    1.  
    2. if (obj.SerializedStateKeys.Count == 0 && obj.SerializedStateValues.Count == 0) {
    3.  
    to

    Code (csharp):
    1.  
    2. if (hadPriorData && obj.SerializedStateKeys.Count == 0 && obj.SerializedStateValues.Count == 0) {
    3.  
    I'll be able to take a look at the other issue in a few hours.

    Edit:

    The fix doesn't fix all of the scenarios (it still breaks when you actually reset the object), but it should be good enough to get it working ATM.

    Edit 2:

    Another quick fix to get it fully working (afaik):

    Change the entire if to:
    Code (csharp):
    1.  
    2. if (hadPriorData &&
    3.     obj.SerializedStateKeys.Count == 0 && obj.SerializedStateValues.Count == 0) {
    4.  
    5.     // wipe existing data
    6.     obj.SaveState();
    7.     obj.SerializedStateValues.Clear();
    8.     for (int i = 0; i < obj.SerializedStateKeys.Count; ++i) {
    9.         obj.SerializedStateValues.Add(null);
    10.     }
    11.     obj.RestoreState();
    12.  
    13.     // run reset again to get the proper data
    14.     fiRuntimeReflectionUtility.InvokeMethod(target.GetType(), "Reset", target, null);
    15.     obj.SaveState();
    16.  
    17.     GUI.changed = true;
    18. }
    19.  
     
    Last edited: Sep 11, 2014
    Maisey likes this.
  32. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Thanks! However I need the "hadPriorData"-bool also (don't wanna guess) :) How will this solution work btw, will I still have to rely on "Reset()" or does it behave like Unity and use the statically initialized "default"-value?

    Also, any thoughts on the other issue with objects being re-instantiated when changed (in certain cases)?

    Thanks!
     
  33. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    This solution fixes the "default" value problem (the hadPriorData fixes that bit), and the second change fixes Reset not being properly applied when running on an object.

    hadPriorData signifies if the object modification detection subsystem already has data for the current object in the current editor session.

    I'll take a look at the second issue shortly.
     
  34. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I'm able to reproduce the instantiation issue pretty easily, but I'm not seeing the inconsistency between dragMe and dragMeProp.

    However, for the instantiation issue the fix is slightly more involved. If you'd like me to just send you a build let me know.

    First, move FullInspector2/Core/Editor/ObjectModificationDetector.cs into FullInspector2/Core/ObjectModificationDetector.cs and change the visibility of ObjectModificationDetector from internal to public.

    Second, go into FullInspector2/Core/fiEditorSerializationManager.cs and insert this statement after line 64:

    Code (csharp):
    1.  
    2. ObjectModificationDetector.Update(obj);
    3.  
    I can send a build with these changes if you would like.

    Funnily enough the issue here was the same prefab modification detection logic activating too aggressively as in the prior Reset/ctor bug.

    This is currently intentional to avoid a big perf hit, as undo support requires constant serialization of the inspected object (the inspector repaints constantly in play mode but not in edit mode). I'll try and take another pass though and see if I can get undo support w/o a perf penalty.
     
  35. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Great! Was kind of stuck with this issue as it caused me to either add lots of "haxx"-code or just wait for the fix so I really appreciate your effort!

    Yes I believe it would be great if you could send a whole build so I avoid screwing something up! ;)

    Thanks!
     
  36. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Sure. It looks like I'm unable to send you a PM on the forums (privacy settings) -- can you either email me or send me a PM?
     
  37. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Just a quick thing I noticed in 2.5: Undo/Redo will re-instantiate the object after a field/property has been changed (instead of keeping the same reference and just assign all the serialised fields/properties, like unity).
     
  38. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Hi sient, I have a weird problem. It seams that the deserialization is not executed on mobile. My code run in the editor without problems, but on android I get some null pointer exceptions of the ScriptableObject that should be already loaded because is referenced from another BaseBehavior component in the scene.
    So to be more precise I have a Game BaseBehavior that is marked as persistent (DontDestroyOnLoad).
    One child has another BaseBehavior that has a reference to a BaseScriptableObject.
    When from this starting bootstrap scene I load a new scene, only on mobile, the scriptable object is null.
    It was not happening before and I can't find a reason why it should happen now. Do you have any idea of what could be the problem?
    I also moved the access to this object out of the Awake to give time to FI to deserialize it, and also I tried to change the execution order of the script but nothing changed.
    Thanks
     
  39. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    I just tested that it happens also within the same scene
     
  40. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Unfortunately object recycling requires deserialization support into an existing object instance which is not generally supported by the different serialization frameworks.

    Hmm, that's strange. Would you mind sending me a build or similar so I can take a look?
     
  41. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    I sent you a private message
     
  42. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Okey, that's unfortunate. So I assume this will not change in the future, or maybe only be enabled for the serializers that do? And how will it behave if undo/redo is added to play mode?

    The reason I nag about this is because I want to keep as much of my editor-plugins transparent between "play mode" & "not play mode" whilst in the editor. As of now I'll have to take into account delegates loosing listeners etc. from time to time, which adds lots of boilerplate code.

    Anyways, thanks! :)
     
    Last edited: Sep 12, 2014
  43. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Thank you sient for your help and sorry for taking your time. Was totally my fault and your plugin is the best tools for Unity that a developer should always use.
     
  44. MaxEden

    MaxEden

    Joined:
    Jun 22, 2013
    Posts:
    82
    As far I know Json.net supports the populate behavior. I maybe wrong in some cases though.
     
  45. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    It does, the issue is BinaryFormatter.
     
  46. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    (Response to conversation with sient)

    I attached a repro, but after some testing I see lots of inconsistency from compile to compile (same code gives different result on recompile)... Is there some metadata cached that might be wrong in special cases?

    The code as it is now should display the drop-down even though [InspectorSkipInheritance] is present, and if not, try removing it, compile, add re-add it and compile (keeping the game object selected)... You should be able to find the case.
     

    Attached Files:

  47. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I'm having a really hard time reproducing this issue. I did a good number of recompiles and it never cropped up, and nothing of the sort that would affect the property editor selection is being cached.

    Are you able to produce this on an empty project with just FI and the test scene?
     
  48. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    The assets exported are the only assets in the whole project except FI.

    Sorry for being this vague, but I really can't give you more... :/ I've attached a print of how it is displayed now, with the exact code. I also attached my fiSettings (not sure if default).
     

    Attached Files:

  49. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    That looks like the correct view to me. The dropdown you see is not for the inheritance selector but is instead an inline object reference viewer. There is currently no way to disable that (though why would you want to?).

    Thanks
     
  50. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Oh wow, okay. :) Thinking about the name I'd see why, but I am not lying with that it sometimes disappeared...

    Well in my case I got a composed object keeping a reference to the "monobehaviour" it's part of, and then I don't want to show the drop down (which of course will only show the "cycle"-label), but also to avoid having users edit through that tiny drop down when components on other objects are shown. I want to show the standard "Object"-field where you press once and it highlights the gameObject with the component in question.

    Sorry for the confusion, I misunderstood your answer in the other conversation as if this was possible:

    "The dropdown is shown when the reference is null, but otherwise it is not shown."