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

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

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

  1. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    I recently bought uFaction for inspecting delegates and my question is this: Does this asset has the functionality to select a game object, it's components, call methods with any given type of arguments ?If so then i am considering to buy it.
     
  2. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Request:
    Could you make it so that [InspectorButton] works on methods with parameters that all have default-values?
    Something like this (in ReflectedPropertyEditor.cs I guess):

    Code (CSharp):
    1. bool isAllDefault = true;
    2.             if (method.HasArguments){
    3.                 foreach(System.Reflection.ParameterInfo paramInfo in method.Method.GetParameters()){
    4.                     if((paramInfo.Attributes & System.Reflection.ParameterAttributes.HasDefault) == 0)
    5.                         isAllDefault = false;
    6.                 }
    7.  
    8.                 if(!isAllDefault)
    9.                     buttonName += " (Remove method parameters to enable this button)";
    10.             }
    And then you'll have to do some doodling with the Invoke-method. :)
     
  3. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Small bug:
    When adding items to a collection using the inspector, OnValidate will be invoked before the item has been instantiated (the item in the list is still null. Guess it's supposed to be instantiated before added to the collection...).
     
  4. jrhee

    jrhee

    Joined:
    Dec 5, 2013
    Posts:
    74
    Is multi-object editing supported? I'm have a custom editor that inherits from CommonBaseBehaviorEditor. Everything works great, except [CanEditMultipleObjects] no longer seems to work.
     
    rakkarage and Maisey like this.
  5. BigToe

    BigToe

    Joined:
    Nov 1, 2010
    Posts:
    208
    Quick question on using logic for customizing the inspector. Just bought this and am used to using CustomEditors, so still trying to get used to this method.

    I have two Vector3 fields. animateTo and animateFrom. I only want to show the animateFrom field in the inspector if the bool useFrom = true;

    public class myClass : BaseBehavior<FullSerializerSerializer>{
    public bool useFrom = true;
    public Vector3 animateTo;
    public Vector3 animateFrom;
    }

    Can I manage this logic/display with attributes? Or do I need to write a PropertyEditor for myClass?


    Thanks!
     
  6. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    Small bug(?):
    If a property has a private setter, it can still be edited in the inspector.

    Code (CSharp):
    1. [NotSerialized, ShowInInspector]
    2. public float Property{
    3.       get;
    4.       private set;
    5. }
     
  7. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Oops -- sorry everyone! I haven't been getting notifications about posts here. I'll be replying shortly.
     
    Maisey likes this.
  8. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    There is some basic delegate functionality but uFAction has a much more sophisticated implementation. With fiValue, you'll be able to continue using uFAction and FI together. Send me a PM if you'd like a preview build.
     
  9. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Sure. No need for changes in ReflectedPropertyEditor; instead, go into InspectedMethod and change Invoke to

    Code (csharp):
    1.  
    2. /// <summary>
    3. /// Invoke the method. This function will never fail.
    4. /// </summary>
    5. public void Invoke(object instance) {
    6.     try {
    7.         object[] args = null;
    8.  
    9.         // support default parameter methods
    10.         var methodParams = Method.GetParameters();
    11.         if (methodParams.Length != 0) {
    12.             args = new object[methodParams.Length];
    13.  
    14.             // NOTE: Based on documentation, it looks like the value you're actually
    15.             // supposed to use to get default arguments is Type.Missing, but
    16.             // there appears to be a bug in mono where that is not supported. Instead
    17.             // we will just fetch the default parameter values and send them.
    18.             for (int i = 0; i < args.Length; ++i) {
    19.                 args[i] = methodParams[i].DefaultValue;
    20.             }
    21.         }
    22.  
    23.         Method.Invoke(instance, args);
    24.     }
    25.     catch (Exception e) {
    26.         Debug.LogWarning("When invoking method " + Method + ", caught " +
    27.             "exception:\n" + e);
    28.     }
    29. }
    30.  
    and also change the constructor to

    Code (csharp):
    1.  
    2. public InspectedMethod(MethodInfo method) {
    3.     Method = method;
    4.  
    5.     // We can consider methods with all-default parameters as no parameter methods
    6.     foreach (var param in method.GetParameters()) {
    7.         if (param.IsOptional) continue;
    8.         HasArguments = true;
    9.         break;
    10.     }
    11.  
    12.     var attr = method.GetAttribute<InspectorNameAttribute>();
    13.     if (attr != null) {
    14.         DisplayName = attr.DisplayName;
    15.     }
    16.  
    17.     if (string.IsNullOrEmpty(DisplayName)) {
    18.         DisplayName = DisplayNameMapper.Map(method.Name);
    19.     }
    20. }
    21.  
    I'm happy to send you a custom build if you want instead.
     
    Maisey likes this.
  10. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Is this with the 2.5 build with the OnValidate fixes?
     
  11. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Sorry, not at the moment :(.
     
  12. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I've just implemented a solution for this. Send me a PM request and I'll send you the latest build. Here's how it works:

    Code (csharp):
    1.  
    2. public class myClass : BaseBehavior<FullSerializerSerializer>{
    3.     public bool useFrom = true;
    4.     private bool notUseFrom { get { return !useFrom; } }
    5.  
    6.     [InspectorDisplayIf("notUseFrom")]
    7.     public Vector3 animateTo;
    8.     [InspectorDisplayIf("useFrom")]
    9.     public Vector3 animateFrom;
    10. }
    11.  
    The solution is extremely flexible; for example, here is one of the scenarios it easily enables:

    Code (csharp):
    1.  
    2. using FullInspector;
    3. using System;
    4.  
    5. public class SpellDemo : BaseBehavior {
    6.     public enum SpellStyle {
    7.         Direct,
    8.         DOT,
    9.         AOE
    10.     }
    11.  
    12.     private bool _InspectorDisplayDirectDamage() { return Style == SpellStyle.Direct; }
    13.     private bool _InspectorDisplayDOT() { return Style == SpellStyle.DOT; }
    14.     private bool _InspectorDisplayAOE() { return Style == SpellStyle.AOE; }
    15.  
    16.     public SpellStyle Style;
    17.  
    18.     [InspectorDisplayIf("_InspectorDisplayDirectDamage")]
    19.     public float DirectDamage;
    20.  
    21.     [InspectorDisplayIf("_InspectorDisplayDOT")]
    22.     public float DotTime;
    23.     [InspectorDisplayIf("_InspectorDisplayDOT")]
    24.     public float DotStrength;
    25.  
    26.     [InspectorDisplayIf("_InspectorDisplayAOE")]
    27.     public float AoeRadius;
    28.     [InspectorDisplayIf("_InspectorDisplayAOE")]
    29.     public int AoeMaxTargets;
    30.     [InspectorDisplayIf("_InspectorDisplayAOE")]
    31.     public float AoeMaxDamage;
    32. }
    33.  
    34.  
     
    BigToe likes this.
  13. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    This is intentional. You may be interested in [InspectorDisabled], which will draw it with a disabled GUI so you cannot modify the value.
     
    Maisey likes this.
  14. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    This is with the latest version you sent me, so I guess so.

    Just shoot me a new build whenever you got time and I'll grab it. :)
     
  15. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    [BUG(?)]:
    Hi! I get some exceptions whenever I build the project, with "OnAfterDeserialize" being called on a component that is already destroyed (the classic Unity-exception). Full exception:

    Code (CSharp):
    1. MissingReferenceException: The object of type 'RectTransform' has been destroyed but you are still trying to access it.
    2. Your script should either check if it is null or you should not destroy the object.
    3. ACE.UI.UIRect.SyncRect () (at Assets/ACELib/UI/UIRect.cs:755)
    4. ACE.UI.UIRect.OnAfterDeserialize () (at Assets/ACELib/UI/UIRect.cs:869)
    5. FullInspector.Internal.BehaviorSerializationHelpers.RestoreState[FullSerializerSerializer] (ISerializedObject obj) (at Assets/FullInspector2/Core/BehaviorSerializationHelpers.cs:191)
    6. FullInspector.BaseBehavior`1[TSerializer].RestoreState () (at Assets/FullInspector2/Core/BaseBehavior.cs:59)
    7. FullInspector.Internal.fiEditorSerializationManager.RunDeserializations () (at Assets/FullInspector2/Core/fiEditorSerializationManager.cs:117)
    8. UnityEditor.EditorApplication.Internal_CallUpdateFunctions ()
     
  16. Diet-Chugg

    Diet-Chugg

    Joined:
    Jul 4, 2012
    Posts:
    51
    In my project I have a MonoBehaviourPlus class that I have all my Monobehaviour classes derive from. Would Full Inspector work on all of my sub-classes if I have my MonoBehaviourPlus class derive from your BaseBehaviour class? I'm way interested in getting this tool.
     
  17. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I'll take a look into this. Is this causing the build to fail (it shouldn't)? If so, you can just add a check for if (obj != null), as Unity does some strange object life-cycle things when running a build.
     
  18. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Yep, and with 2.5 you'll be able to just use fiValue<T> without deriving from BaseBehavior at all.
     
  19. Diet-Chugg

    Diet-Chugg

    Joined:
    Jul 4, 2012
    Posts:
    51
    On the Asset store there is a mention of "edit: the author sent me a beta of the next version - that quarter second delay when viewing a new fancy editor is gone. Just great work!" Is that supposed to be part of v2.5 as well?

    Note: I got the asset and am loving it but I have noticed the lag for the more fancy editors.
     
  20. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    No the build works fine, so no issue there. Just lot's of errors, before I added the check. :)

    Thanks!
     
  21. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Are you running on the trial? The trial points to 2.3 which is slow -- 2.4 is the current version on the asset store which is significantly faster. If you are on the trial, send me a PM and I'll send you an updated evaluation build.
     
  22. Diet-Chugg

    Diet-Chugg

    Joined:
    Jul 4, 2012
    Posts:
    51
    I'm on 2.4. However when poking around in your sample scenes the dictionaries (the part that's running slow for me) runs just fine. So it must be that it's taking more effort because I have my MonobehaviourPlus class that I inherit from for my custom.cs. I changed my MonobehaviourPlus class to inherit from BaseBehaviour. MonobehaviourPlus is about 1000 lines and uses the [HideInInspector] attribute about 120 times (A bunch of quick getters and setters for common components I use). I think my class is likely the culprit. I'm going to try removing some of the unneeded [HideInInspector] attributes and see if it helps.

    Edit: I now have 53 [HideInInspector] attributes in my MonobehaviourPlus script. Which does improve speed but it's still pretty slow. Looks like I need to find some ways to optimize my script.
     
    Last edited: Oct 3, 2014
  23. Alic

    Alic

    Joined:
    Aug 6, 2013
    Posts:
    137
    Hey! Really enjoying this so far. I tried it months ago, and the performance increases you've done are really great!

    I'm wondering about something that seems counterproductive in the terms of the List<MonoBehaviour> implementation. Currently if you make a list of components and add references to it, the name of the game object they are on is displayed for the list entry, but the name of the component type is not! (In the default Unity inspector List, you see GameObjectName(ComponentTypeName).) This makes adding a bunch of component references from the same game object all indistinguishable from each other, which is kind of annoying.

    One other little pet peeve is that the FullInspector list implementation doesn't allow for items to be dragged onto the list field in order to add the reference as a new item in the list. You have to click add item and then drag onto the null reference. But maybe this is intentional/hard to get around.

    Anyway, I feel like this is something I'll have to play with a long time to really see everything it can do, but I'm already planning parts of my design workflow around it -- great work you've done!
     
  24. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Is the slowness at runtime or just at instantiation time?
     
  25. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Thanks! I appreciate it.

    afaik, this is a bug with the Unity EditorGUI.ObjectField function. I've looked into it in the past and the only solution seemed to be reimplementing all of Unity's object selection code.

    This is more a Rotorz issues, but it would be nice if a drag and drop directly added. I'm not sure of a good way to implement it atm.

    Wonderful! Let me know what you think after you've got more experience with it :). I'm happy to take any suggestions for improvements.
     
    kaladrius-trip likes this.
  26. Alic

    Alic

    Joined:
    Aug 6, 2013
    Posts:
    137
    Hey sient, quick question: In the samples-other scene in full inspector 2.4, everything explicitly implements Json Serializer and there's a big message in the Hierarchy saying JSON.NET SERIALIZER REQUIRED. I just want to confirm that if I'm planning on using BaseScriptableObject to build a database and probably also use the [InspectorDatabaseEditor] attribute, that these are things I should explicitly use JSON serializer for. I guess I'm asking mainly because other places in the documentation seem to encourage using Full Serializer as the default, and I got the sense looking around that JSON serializer was left in mainly for compatibility with past versions. Thanks!
     
  27. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Yep, Full Serializer is recommended for default usage now, and Json.NET is left for compabilitly reasons. The samples-other scene just derives from BaseBehavior<JsonNetSerializer> -- there is no real reason for why it explicitly needs Json.NET; it can easily be swapped out for Full Serializer.
     
  28. Alic

    Alic

    Joined:
    Aug 6, 2013
    Posts:
    137
    Thanks a lot! :)

    Oooh, one more question: are there plans to allow reordering of dictionary items similar to lists?
     
    Last edited: Oct 12, 2014
  29. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Dictionaries cannot be reordered because the underlying collection is unordered / undefined.
     
  30. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    Hi! I just purchased this over the weekend. I haven't had the time to play with it yet. But so far I've seen that it can set interfaces in the inspector. BUT it can't drag monobehaviours that implements the interface to the inspector.

    Is this correct? If so, I would like to make this a feature request instead.
     
  31. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    This is indeed supported, but I've added an issue to improve to workflow here. Here is the current workflow (an instance is auto-added so that serialization works properly, otherwise there is no way to preserve the type information):

    interface demo.gif

    Container
    Code (csharp):
    1.  
    2. using FullInspector;
    3.  
    4. public interface IInterface { }
    5. public class SimpleImpl : IInterface { }
    6.  
    7. public class Container : BaseBehavior {
    8.     public IInterface Interface;
    9. }
    10.  
    Behavior:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class Behavior : MonoBehaviour, IInterface {
    5. }
    6.  
     
  32. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    Why is Behavior component being added when you set the concrete implementation of IInterface to Behaviour?

    It would be great if we could remove that (autoadding behaviour) from the workflow. :)
     
  33. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    It's so the interface will serialize properly. If there is no component added then the reference is effectively null which means that there is no type information.
     
  34. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
  35. Deleted User

    Deleted User

    Guest

    The method described there is for hiding entire transforms (in the hierarchy). I don't believe there's a way to hide monobehaviors in the inspector.

    In any case, sient's example is valid workflow until the point where you want to use *another* game object's behavior as the referenced item, then the behavior is left hanging.

    Sient, isn't a better way forward to use something like Facade, perhaps with an extension for the interface field? So in the Container, you would write, say, IBinding<IInterface>, which would be satisfied by a proxy class (Facade-like) that auto-instantiates a MonoBehavior of a specified type at runtime, or another proxy class that just references an IInterface of another object?
     
  36. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    I actually tried it and it worked. I can hide monobehaviours in the inspector.
     
  37. TeddyGeorgeoff

    TeddyGeorgeoff

    Joined:
    Oct 21, 2012
    Posts:
    9
    Works fine in play mode, but when trying to build I get this. I am using unity 4.6.

    ArgumentException: The Assembly UnityEditor is referenced by FullInspectorSerializerProtoBufNet. But the dll is not allowed to be included or could not be found.
    UnityEditor.AssemblyHelper.AddReferencedAssembliesRecurse (System.String assemblyPath, System.Collections.Generic.List`1 alreadyFoundAssemblies, System.String[] allAssemblyPaths, System.String[] foldersToSearch, System.Collections.Generic.Dictionary`2 cache, BuildTarget target) (at C:/BuildAgent/work/d63dfc6385190b60/Editor/Mono/AssemblyHelper.cs:137)
    UnityEditor.AssemblyHelper.AddReferencedAssembliesRecurse (System.String assemblyPath, System.Collections.Generic.List`1 alreadyFoundAssemblies, System.String[] allAssemblyPaths, System.String[] foldersToSearch, System.Collections.Generic.Dictionary`2 cache, BuildTarget target) (at C:/BuildAgent/work/d63dfc6385190b60/Editor/Mono/AssemblyHelper.cs:140)
    UnityEditor.AssemblyHelper.FindAssembliesReferencedBy (System.String[] paths, System.String[] foldersToSearch, BuildTarget target) (at C:/BuildAgent/work/d63dfc6385190b60/Editor/Mono/AssemblyHelper.cs:172)
    UnityEditor.HostView:OnGUI()
     
  38. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Yea, I was using hiding in another project but I would like to avoid that as it makes things sometimes difficult to understand if anything goes wrong. What I would like to do is investigate adding drag and drop to the interface, so the interface type is automatically selected after you drop the component onto the interface selected. I'll try and take a look at it this weekend.

    Clever, that would probably work out well. However, it requires that people wrap their references in another type which I would like to avoid.
     
  39. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I've intentionally disabled builds on the trial -- otherwise there is no reason to purchase :).
     
  40. PrefabEvolution

    PrefabEvolution

    Joined:
    Mar 27, 2014
    Posts:
    225
    So what about serialization/deserialization performance? Unity serialize objects without any reflection, its generates serialization/deserialization IL code that work lighting fast, and that why they don't supports generics, interface serialization and so on. This process(weaving) is running when you make a player build and don'y annoying you when you develop your project. But i think your serialization should be probably 5-10 times slowly than native Unity. Do you have any serialization performance tests results?
     
  41. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Serialization/deserialization performance will vary highly depending upon your selected serializer.

    protobuf-net also generates custom IL but manages to support generics and interfaces.

    I ran some tests in 4.3 which showed protobuf-net being *faster* than Unity's serializer, but since then Unity has significantly optimized their serialization engine -- I expect it to be faster than protobuf-net now. Full Serializer and Json.NET are going to be slower since they both go through reflection APIs (I can't speak for Json.NET, but Full Serializer does it for portability reasons).
     
  42. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
  43. PrefabEvolution

    PrefabEvolution

    Joined:
    Mar 27, 2014
    Posts:
    225
    Object properties in my plugin are collected through unity api. fullinspector can't expose properties through native unity api, so probably property override for objects that serialized through fullinspector serializer will not work proper. Also would like to cooperate with fullinspector plugin author and make this plugins full compatible.
     
  44. PrefabEvolution

    PrefabEvolution

    Joined:
    Mar 27, 2014
    Posts:
    225
    protobuf generates serialization code in runtime that is not allowed on IOS.
     
  45. cjke-7777

    cjke-7777

    Joined:
    Apr 28, 2013
    Posts:
    9
    What would be the best approach to creating a custom property editor for FullInspector to see? I have duplicated the MinMax example custom property editor. When placed within the same folder down in

    Code (csharp):
    1.  
    2. using System;
    3. using UnityEditor;
    4. using UnityEngine;
    5. using FullInspector;
    6.  
    7. namespace mynamespace
    8. {
    9.    [CustomPropertyEditor(typeof(Stat))]
    10.    public class StatEditor<TElement> : PropertyEditor<Stat>
    11.    {
    12.      public override Stat Edit(Rect region, GUIContent label, Stat element, fiGraphMetadata metadata) {
    13.        float min = element.Min;
    14.        float value = element.Value;
    15.        float minLimit = element.Min;
    16.        float maxLimit = element.Max;
    17.        string labelText = label.text + string.Format("{0}/{1}", value, maxLimit);
    18.        var updatedLabel = new GUIContent(labelText, label.image, label.tooltip);
    19.        EditorGUI.MinMaxSlider(updatedLabel, region, ref min, ref value, minLimit, maxLimit);
    20.        return new Stat((int)value, (int)minLimit, (int)maxLimit);
    21.      }
    22.  
    23.      public override float GetElementHeight(GUIContent label, Stat element, fiGraphMetadata metadata) {
    24.        return EditorStyles.largeLabel.CalcHeight(label, 100);
    25.      }
    26.    }
    27. }
    28.  
     
  46. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    I really hope your plugins get fully compatible!

    Have you tried this with your plugin yet? Are properties the only issue?
     
    Last edited: Oct 18, 2014
  47. PrefabEvolution

    PrefabEvolution

    Joined:
    Mar 27, 2014
    Posts:
    225
    i don't try it, but i think you can also try it with free version of the fullinspector.
     
  48. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    I tried it a little bit but so far I'm not running into problems. :)
     
  49. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    Full Inspector includes experimental code that integrates protobuf-net's AOT compilation into Unity's build environment, which completely removes the runtime code generation and enables iOS usage.
     
  50. sient

    sient

    Joined:
    Aug 9, 2013
    Posts:
    602
    I think some of your comment may have gotten truncated. The code looks good to me -- what are you trying to accomplish?