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

(Free) uFAction - A complete set of serializable and inspectable delegates

Discussion in 'Assets and Asset Store' started by vexe, May 10, 2014.

  1. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    I decided to make uFAction free, because I won't be developing it anymore. If you're interested in delegates, a much better deal (also free) is VFW.

    ------


    uFAction has been released! Asset store link.


    Hi all,

    I'm an independent gameplay programmer who ended up falling in love with writing editor tools!
    Allow me to present my first tool, uFAction! - It's a Unity extension/package that gives you a full set of serializable/inspectable delegates (Actions Funcs) that could be easily integrated and made visible in the inspector for editing.

    Features and contents:
    • You can target any UnityEngine.Object with UnityDelegate (Actions and Funcs - all with generic versions, up to 3 generic args, want more? create a wrapper class for your data instead)
    • You can target any non UnityEngine.Object with SysObjDelegate (Actions and Funcs - with generic versions too)
    • You get a KickassDelegate that could accept any method with no return (void) regardless of the parameters' signature!
    • You can set your handlers' arguments (if any) from the editor by means of a direct value, or from a source!
    • Support for extension methods!
    • Customize all your way through. You can adjust BindingFlags, create new themes, and many more by means of a simple asset file!
    • Three unique editors: Readonly (For SysObjDelegates), Mini and Advanced (for UnityDelegates). Each with its own unique characteristics. Switch between available editors by a single click!
    • Extremely easy and simple to use! Just declare your delegate and annotate it with [ShowDelegate("Title")] - No need for any custom editors!
    • Support for Unity light skin!
    • A globally-accessed generic event system that you could use to globally (un)subscribe event handlers and fire game events!
    • -No more dealing with Rects! with the convenient and pleasant-to-use awesome GUIWrapper that makes it possible to use GUILayout-like methods in GUILayout-restricted areas (PropertyDrawer.OnGUI for example) - This is what I used to draw the delegate editors! It can draw Buttons, Labels, Blocks (Horizontal/Vertical), all kinds of fields, (IntField, ColorField, ObjectField, etc), Popups, Foldouts, Boxes, DragDropAreas, GetLastRect, ColorBlock, ChangedBlock, EnabledBlock and many more!
    • Price? a [old $10 KFC lunch meal] $5 potatoes sack :grin:

    Features to implement in coming updates:
    • The ability to select nested source properties.
    • Better serialization solution so that you don't have to subclass when creating generic delegates.
    • The ability to add assemblies from which to fetch extension methods.
    • Better separation between the editor/runtime stuff in the Settings ScriptableObject.
    • Any user-requested feature(s)
    Readme/Guide:
    • Here's a readme/guide pdf file - explains things in depth (how I serialized things, the classes hierarchy, usage, different types of delegates, differences between editors, the settings etc) (Reading it directly from the uploading site might not be pleasant, consider downloading it - Zoom in if the pics were small, the quality becomes better)

    Support:
    • If you have any questions, suggestions, features requests, etc feel free to post them in this thread.
    • If you ever encounter a bug, you could post it here providing a way of replicating it. If you needed an urgent fix and can't wait till the next update, I will look into it and fix it as fast as I can and send you a private message with the fix.
    • Alternatively, you could send me an email at askvexe@gmail.com
    • If I don't respond to you within 5 to 10 minutes, it could mean that: 1- I hit the sleep tank. 2- The lovely Unity forums thread notification is working perfectly. 3- My grandpa has taken the laptop to watch the news and enjoy a football match afterwards, or a 2-hours+ long women's volleyball match.


    Hope to hear your feedback! - Thanks.

    ------------------------------------

    uFAction 1.1 Change log:

    FIXES:
    - Fixed a bug when dragging a gameObject to a gameObject field. Sometimes you get a "Couldn't re-bind method xxx to target xxx".
    - Fixed a bug when trying to use the value assigned to an object field when you set your handlers' arguments.
    - Fixed a bug in GUIWrapper's ChangeBlock if you draw a control in the changed block.
    NEW:
    - Added a boolean flag to determine whether or not to keep the selection window active (focused) after making a selection (selecting a target, method or adding a new game object)
    - DEVBUS (Developer Extremely-Vriendly BetterUndo System): A much better undo system implemented via the command pattern for which you have full control on 'what' is it to be done, and 'how' it is to be undone! (Pic1, Pic2, Pic3. See TestEditor2 for the demo in the pics)
    - Now you have a full EditorGUIFramework with a BetterEditor, BetterPropertyDrawer, GUIWrapper and GLWrapper. With this framework, you could write GUI-independent drawers that well works in both custom editors and property drawers. (See the DrawMates in ShowEmAll)
    - With GLWrapper you could now draw your delegate from your custom editors so you're not just constrained to using ShowDelegate! (See TestEditor1 for the example in the pic)
    - Found a way to keep editor data out of runtime with BetterPrefs and IUniquelyIdentifiedObject. See.

    MODS:
    - SimpleSelectionMemorizer is now called SelectionMemorizer and it could memorize all your selections in a single editor session. It does this now by the aid of BetterUndo. Press Ctrl+Shift+- to go back, Ctrl+Shift+= to go forward.
    - Moved all the helpers/utils static classes to DLLs. The point is not to hide the code but to keep everything clean, compact, portable and easily plug-able. (There's really no practical meaning to hiding code in a DLL when it comes to .NET if you know what I mean...)
    - Much better undo support: You can now add/remove/set at will! There are some parts that don't support undo yet, mainly the args (setting an arg directly/from a source) - See this pic: green = supports undo. Red = doesn't.
    - Removed all the editor data (foldouts) from most the runtime classes with the help of BetterPrefs and IUniquelyIdentifiedObject. Now they're editor-only.
    - GUIControlOption is now called GUIOption. (There's now GUIOption and GLOption, both inheriting LayoutOption)

    ------------------------------------

    uFAction 1.2 Change log:

    NEW:
    1. Added an invocation performance scene to see some invocation benchmarks
    2. Huge boost in Editor performance and invoking delegates with editor arguments thanks to memoization and Fasterflect!
    3. Added new methods to EventManager: DynamicRaise, RaiseToAllExcept, RaiseToOnly
     
    Last edited: Dec 16, 2014
  2. hadiai

    hadiai

    Joined:
    May 10, 2014
    Posts:
    9
    This is impressive indeed! I've seen a lot of delegate packages on the asset store, but nothing like this! They were all lacking. The editors look nice, the class hierarchy looks simple and robust. At first I was wondering why the seperation SysObjDelegate vs UnityDelegate, but the readme made it clear. Ahh, Unity and its serialization system. Can't wait for this to be online, consider me your first customer :)
     
  3. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    hey @hadiai: thanks for your positive feedback! - You are right, Serialization is the reason why I had to go with two different approaches/delegate branches. I will keep an eye out for better serialization solutions as promised so that maybe we won't have that separation.
     
  4. Crazymb

    Crazymb

    Joined:
    Aug 29, 2013
    Posts:
    1
    This looks awesome! I've had issues with Unity and delegates serialization before and this seems like a better solution than others available in the store. Good work!
     
  5. Jamora

    Jamora

    Joined:
    Mar 5, 2013
    Posts:
    9
    How's the performance on that GUIWrapper compared to the built-in GUILayout?

    How about the run-time performance of these delegates versus normal delegates? Just wondering how using these will affect the run-time performance of my game...

    Looks like a very promising product.
     
  6. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @Jamora thanks for your input.

    As for your query, all the delegates (except KickassDelegate) use C# delegates as their back-end. Calling myUnityAction.Invoke(); will internally call a C# delegate (in this case it's an Action) - And of course, performance of C# delegates is excellent! Almost as fast as invoking a method directly.

    However, if you set your delegate's arguments selectively from the editor, I will have to use reflection to be able to invoke your delegate via the arguments you set because high chances are, they're gonna be different. (Cause normally, when you invoke a delegate with an argument, that same argument will be passed to all its subscribers - this is not the case here) And for that I use MethodInfo.Invoke - I don't use DynamicInvoke. I have mentioned all this in the readme file. I also provided a benchmark link. - (Invoking by MethodInfos pretty much sits at the middle of the chart "Reflected after binding").

    This is what is used by KickassDelegate, since it could accept any method with no return regardless of its parameters' signature. So if you're using KickassDelegate or a UnityDelegate (with custom args set from the editor) you might want to avoid invoking the delegate frequently in high-performance-sensitive areas, it all depends on your game, what's/how many things are being updated, etc. You certainly don't have to worry about single calls.

    Regarding GUIWrapper, it uses GUI as its back-end. I have not made any explicit benchmarks between it and GUILayout. But from my usage of it, it's pretty fast! - However, just remember to do a gui.HeightHasChanged(); whenever your GUI changes height so that I re-layout everything otherwise you'd experience a single frame of lag (the change of height usually happens when you fold/unfold a foldout)

    Hope that answers you, if you got more questions, please feel free to ask.

    Thanks.
     
    Last edited: May 11, 2014
  7. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,649
    Bookmarked...and deal...
     
    Last edited: May 11, 2014
  8. hadicoco

    hadicoco

    Joined:
    May 10, 2014
    Posts:
    13
    $10? I'd sell for at least a double price lol - KFC is $20 where I'm at anyway
     
  9. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    I'm sold. Gosh...one week to wait for the asset..
     
  10. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,649
    Same here for KFC. :D
     
  11. TechSupportIncoming1

    TechSupportIncoming1

    Joined:
    Mar 13, 2014
    Posts:
    4
    Did you handle anonymous methods? I don't know if it's possible... but it would be a nice addition.
    Btw great work man :cool:
     
  12. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Hey @TechSupport thanks for dropping by.

    As for your query, not sure what you mean by 'handle' - but I assume you mean does uFAction support the adding/removal of anonymous methods to delegates. The answer is, no. The reason is that, let's say you did something like:
    Code (csharp):
    1.  
    2. int x;
    3. myDel += () => x++;
    4.  
    One might ask, where is the target object in this case? - Well, it's actually generated by the compiler. It's a wrapper that most the times contains the name "DisplayClass" - (usually <>__DisplayClass or something but we don't care about the name really) - Inside this wrapper, you'll see your x variable defined! Since this class is compiler generated, none of my delegates are able to point to it because: 1- It's not a UnityEngine.Object so all my UnityDelegates are useless. 2- It is a System.Object so you might think that my SysObjDelegate could target it, but no. currently SysObjDelegates could target System.Object classes that have the [Serializable] tag on them which in this case they don't. Even if I used an annotation-free serializer, most annotation-free serializer will require you to let them know beforehand what types you're gonna be serializing, in this case you don't know the type cause it's compiler-generated.

    If all of that was not clear to you, see this video.

    I might find some kind of work-around, but again, it's sketchy business. Most the times you could just put your code in a legit method and call it instead.

    Hope this answers you.

    Thanks.
     
    Last edited: May 11, 2014
  13. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Finally! - uFAction has been accepted and is now on the store! :) - Asset store link.
     
    Last edited: May 17, 2014
  14. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Just wrote my review: https://www.assetstore.unity3d.com/en/#!/content/17817

    Can't stress enough out how great this tool actually is. Built in a comprehensible but also expandable way, saves so much time and vexe is such a nice contact. A pleasure to work with the asset!

    Looking forward to future updates! :)
     
  15. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @BTStone thanks so much for your kind words! Glad you're satisfied. First happy customer :D

    As for things to update/add, I'm actually thinking of making the method bindings available to each delegate on a per-instance basis. Of course, static one remains. But if you so choose you could go with the instance bindings instead. I will also include my GLWrapper that I'm working on so that you could now finally easily draw your delegate from an editor script that way you're not constrained to just [ShowDelegate]. Also, give the ability to specify your own assemblies to fetch extensions from, so not just the first-pass assembly.
     
    Last edited: May 19, 2014
  16. clunk47

    clunk47

    Joined:
    Apr 29, 2011
    Posts:
    22
    Congrats on an amazing job friend!
     
  17. hadiai

    hadiai

    Joined:
    May 10, 2014
    Posts:
    9
    How did you get to show extension methods? I have a class right now with a simple extension method however when I reflect it (see its methods) I don't get to see the extension method I wrote...
     
  18. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @hadiai: Good question! The first thing to understand is that extension methods will resolve to static methods. They are not an actual part of your object.

    So this:
    Code (csharp):
    1.  
    2. public static class TransformExtensions
    3. {
    4.    public static void MyExt(this Transform t)
    5.    {
    6.        // ....
    7.    }
    8. }
    9.  
    10. myTransform.MyExt();
    11.  
    Will turn into this:
    Code (csharp):
    1.  
    2. public static class TransformExtensions
    3. {
    4.    public static void MyExt(Transform t)
    5.    {
    6.        // ....
    7.    }
    8. }
    9.  
    10. TransformExtensions.MyExt(myTransform);
    11.  
    With that being said, how can we reflect and get the extension methods of a certain type?
    First, we need an assembly reference to look inside its types. Our TransformExtensions class is static which means it's implicitly sealed. It's also not nested nor generic (must check for these too) Also, the compiler generates a [ExtensionAttribute] on your extension method. We can use all of this information when reflecting.

    This should help get you started:
    Code (csharp):
    1.  
    2. public static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type wantedType, Type returnType, BindingFlags modifiers)
    3. {
    4.     return assembly.GetTypes()
    5.                    .Where(t => t.IsSealed  !t.IsNested  !t.IsGenericType)
    6.                    .SelectMany(t => t.GetMethods(BindingFlags.Static | modifiers))
    7.                    .Where(m => m.IsDefined(typeof(ExtensionAttribute)))
    8.                    .Where(m => m.ReturnType == returnType)
    9.                    .Where(m => m.GetParameters()[0].ParameterType == wantedType);
    10. }
    11.  
    Test (a C# console app):
    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Reflection;
    6. using System.Runtime.CompilerServices; // needed for ExtensionAttribute
    7.  
    8. namespace Test
    9. {
    10.     public static class TestExtensions
    11.     {
    12.         public static void MyStringExt(this string input) { }
    13.         public static void MyOtherStringExt(this string input) { }
    14.         // etc
    15.     }
    16.  
    17.     class Program
    18.     {
    19.         // you can put GetExtensionMethods(...) here...
    20.  
    21.         static void Main(string[] args)
    22.         {
    23.             foreach (var m in GetExtensionMethods(typeof(Program).Assembly, typeof(string), typeof(void), BindingFlags.Public))
    24.             {
    25.                 Console.WriteLine(m.Name);
    26.             }
    27.         }
    28.     }
    29. }
    30.  
    This outputs the names of the two string extension methods. However, this gives you 'exact' type-match. So, if you have an extension method for UnityEngine.Object say, and you wanted all the extension methods for Transform, this method wouldn't cut it, some extra inputs are needed. I wanted to keep it simple but if you still want to know I will happily share.

    Hope that helped, thanks.
     
    Last edited: May 19, 2014
  19. hadiai

    hadiai

    Joined:
    May 10, 2014
    Posts:
    9
    Thanks for your reply. You accessed the first parameter from GetParameters without checking to see if the length is greater than zero, shouldn't we check first?
     
  20. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @hadiai: There's no need for that, cause reaching the last where, all the methods at this stage have [ExtensionAttribute] on them so it's guaranteed that they'll have at least one argument/parameter (the 'this') :)
     
    Last edited: May 21, 2014
  21. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Hi all. I just uploaded uFAction 1.1 - Waiting approval. Check out the change log in the main post above :) - Apologies if any of you stumbled across either of the two fixed bugs. The first one is pretty much harmless, you get the error, and then it goes away. The second is not.
     
    Last edited: May 26, 2014
  22. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    1.1 is live! - That was relatively quick. Enjoy DEVBUS :)
     
  23. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Been a while, quite busy months. 1.2 is here with notable performance enhancements to delegate editors and when invoking delegates via editor arguments!

    How's everyone's experience been with uFAction? I'd love to hear from you...
     
  24. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Good job.You just saved me a week writing my own serializable delegates for Unity.Everything is nice and neat and straight forward.I didn't compiled yet a game for a specific platform to test the package, but i am sure there won't be any trouble.Nicely done!
     
  25. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @sysameca Thanks for your purchase! I hope you like it! and if there's something you didn't, don't hesitate to suggest an improvement
     
  26. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    I started working today with uFaction as i didn't needed it's functionality until now and the first think i want to suggest as improvement is somehow as an option to be able to select objects implementing an interface.Like for example when you open the search list from the + icon on KickAssDelegate to have a button or something "Select objects which implement interface" and then list all the interfaces available from the current project class libraries.Then one can easily select a game object implementing interface.This is good when you are dealing with lot's of GO's like a currently am.If it's not a big deal will be just a small nice feature for intermediate and advanced programmers who are using also interfaces..
     
  27. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @sysameca I'm currently adding interfaces support (serialization and exposure) to ShowEmAll. I'll see if I can port some of that to uFAction. Thanks for your suggestion. Definitely doable.
     
  28. pneill

    pneill

    Joined:
    Jan 21, 2007
    Posts:
    207
    Does this package work on iOS? As I recall there are some AOT compile issues with delegates in IOS.
     
  29. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @pneill Thanks for dropping by! I haven't really tested it on iOS because I don't have any so I can't guarantee. Not sure about compile issues with delegates. If there's ever a potential issue it would be with reflection. A lot of people claimed to have reflection working no problem on iOS with the exception of Reflection.Emit (anything related to runtime code generation in general) I asked one of my customers @BTStone he said he didn't have issues on iOS so far.

    If you like, I could send you a demo version and test it out yourself :)
     
  30. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
  31. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Definitely THE GUIWrapper needs an int slider. Maybe you can split it to IntSlider and FloatSlider.I have a problem also with Rotorz Reorderable List and the custom property drawer.. it adds like around 200-300 pixels vertical space.Do i need to do something special so it won't add that space?The code is basically uses just gui.Foldout() method.Look at the image.

    EDIT: Also for each inserted item it adds another 200-300 pixels which produces a total of 400-600pxs for a second item for instance.And it behaves like that also for a default list and array representation in the inspector
     

    Attached Files:

    Last edited: Sep 16, 2014
  32. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    There's a Slider method of course - See EditorGUIFramework/Wrappers/BaseWrapper/Controls/Sliders (uses EditorGUI.Slider)

    There's nothing special I do in all of my gui methods, they're just wrappers. GUIWrapper's Foldout is a wrapper for EditorGUI.Foldout, while GLWrapper's for EditorGUILayout.Foldout. I don't do any extra horizontal/vertical blocks things, just a foldout. The image you show looks like a block issue, it seems as if the foldout and the minus (-) sign is in a vertical block? I don't know what Rotorz do so I can't really tell what's going on.
     
  33. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    I reedited the post it's not Rotorz issue.It happens with the normal arrays and normal lists also.About the slider i was talking about an int slider the current slider accepts only floats :)
     
  34. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    So there's been some changes to the wrappers' API for the new ShowEmAll stuff. I would love to give you the most recent version but unfortunately it's not stable yet. I have a version of the older EGF (which you're using) and I will add the IntSlider and send you those added files. Notice how I didn't upload EGF on its own, because it's not a full framework yet, I only added what I needed (I didn't need an int slider, that's why it wasn't included)

    Can you hack up a small project with all the necessary ingredients to replicate the issue you're having so I can take a look? Thanks :)
     
  35. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Yes of course. I think that the gui.Foldout produces some weird behaviors.Now when i tried to replicate the thing on a fresh project it draws the variables on top of the other foldouts.Select the test object and try to open expand the first item.Then try the second.Then try the third you will see what i mean :) Then also there is a commented line inside the test script you can uncomment it to see the other thing that one might not expect.
     

    Attached Files:

  36. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    So I added you the slider. But for the issues with the drawer, again, it's a fix scheduled with the new API. There's not a small change I could do to the current API to address this. It's a layouting issue, rects positions are misplaced - you could notice that on the foldout where you have to click a bit further on the left - that's a sign that the layouting is not taking into consideration the indentation caused by the list. With the new API there 'should' be no more need for a GUIWrapper, everything can be done via GUILayout (which means you could still use GLWrapper... at least I'd personally do) so no layouting issues - I'm just worried about performance. I don't know if you opened the scene where I had two delegates on drawn via GLWrapper and another via GUIWrapper, the second seemed to perform better. Apologies for the inconvenience :)
     

    Attached Files:

  37. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @Guys, @sysameca I've released my Vexe Framework along with a new drawing API, better serialization and a simplified delegates system that fulfills my initial uFAction promises (having better serialization and not subclassing to create new delegate types) - I haven't yet migrated uFAction to take advantage of this new framework...
     
  38. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Halved down the price.
     
    Last edited: Nov 13, 2014
  39. YinXiaozhou

    YinXiaozhou

    Joined:
    Oct 19, 2013
    Posts:
    133
    I sent a mail to you but get no reply. So I post it here see if I have luck.

    I just bought your uFAction. And I get some issues when testing it. I want to know is these issues fixable?

    1. Cannot use uFAction delegate classes in nested classes. I get a error when try to use UnityAction in nested class: Serialization depth limit exceeded at 'Vexe.Runtime.Types::SerializedClass`1'. There may be an object composition cycle in one or more of your serialized classes.

    Below is my test script.

    usingUnityEngine;
    usingSystem.Collections;
    usinguFAction;

    publicclasstest : MonoBehaviour
    {
    publicActionPairkick;
    }

    [System.Serializable]
    publicclassActionPair
    {
    publicstringName;

    [ShowDelegate("Action")]
    publicUnityActionAction;
    }

    2. Cannot use uFAction delegate classes in arrays.

    3. Get null reference errors every time when I switch component for UnityAction in Inspector. Although it seems that the functionality is not effected. Below is the error stack.

    NullReferenceException: Object reference not set to an instance of an object
    uFAction.UnityDelegate`1[TDelegate].RebuildInvocationList () (at Assets/Vexe/uFAction/Core/Delegates/Bases/UnityDelegate.cs:158)
    uFAction.Editors.BaseEditor`2+<Draw>c__AnonStorey2A[EditorGUIFramework.GUIWrapper,EditorGUIFramework.GUIOption].<>m__6D () (at Assets/Vexe/uFAction/Core/Editor/Delegate Editors/BaseEditor.cs:186)
    EditorGUIFramework.Helpers.Blocks.ChangeBlock (System.Action check, System.Action onChange) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:34)
    EditorGUIFramework.GUIPopup.Draw () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIControls/GUIPopup.cs:16)
    EditorGUIFramework.GUIControl.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIControls/GUIControl.cs:44)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__54 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:107)
    EditorGUIFramework.Helpers.Blocks.LabelWidthBlock (Single width, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:40)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__53 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:106)
    EditorGUIFramework.Helpers.Blocks.ColorBlock (Color newColor, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:24)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__52 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:105)
    EditorGUIFramework.Helpers.Blocks.StateBlock (Boolean newState, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:16)
    EditorGUIFramework.GUIControlBlock.DrawControl (EditorGUIFramework.GUIControl c, Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:104)
    EditorGUIFramework.HorizontalGUIControlBlock.Draw () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/HorizontalGUIControlBlock.cs:84)
    EditorGUIFramework.GUIControl.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIControls/GUIControl.cs:44)
    EditorGUIFramework.GUIControlBlock.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:99)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__54 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:107)
    EditorGUIFramework.Helpers.Blocks.LabelWidthBlock (Single width, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:40)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__53 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:106)
    EditorGUIFramework.Helpers.Blocks.ColorBlock (Color newColor, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:24)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__52 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:105)
    EditorGUIFramework.Helpers.Blocks.StateBlock (Boolean newState, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:16)
    EditorGUIFramework.GUIControlBlock.DrawControl (EditorGUIFramework.GUIControl c, Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:104)
    EditorGUIFramework.VerticalGUIControlBlock.Draw () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/VerticalGUIControlBlock.cs:42)
    EditorGUIFramework.GUIControl.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIControls/GUIControl.cs:44)
    EditorGUIFramework.GUIControlBlock.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:99)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__54 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:107)
    EditorGUIFramework.Helpers.Blocks.LabelWidthBlock (Single width, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:40)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__53 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:106)
    EditorGUIFramework.Helpers.Blocks.ColorBlock (Color newColor, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:24)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__52 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:105)
    EditorGUIFramework.Helpers.Blocks.StateBlock (Boolean newState, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:16)
    EditorGUIFramework.GUIControlBlock.DrawControl (EditorGUIFramework.GUIControl c, Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:104)
    EditorGUIFramework.HorizontalGUIControlBlock.Draw () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/HorizontalGUIControlBlock.cs:84)
    EditorGUIFramework.GUIControl.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIControls/GUIControl.cs:44)
    EditorGUIFramework.GUIControlBlock.Draw (Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:99)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__54 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:107)
    EditorGUIFramework.Helpers.Blocks.LabelWidthBlock (Single width, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:40)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__53 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:106)
    EditorGUIFramework.Helpers.Blocks.ColorBlock (Color newColor, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:24)
    EditorGUIFramework.GUIControlBlock+<DrawControl>c__AnonStorey26.<>m__52 () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:105)
    EditorGUIFramework.Helpers.Blocks.StateBlock (Boolean newState, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/Other/Helpers.cs:16)
    EditorGUIFramework.GUIControlBlock.DrawControl (EditorGUIFramework.GUIControl c, Single x, Single y) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/GUIControlBlock.cs:104)
    EditorGUIFramework.VerticalGUIControlBlock.Draw () (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/Blocks/GUIControlBlocks/VerticalGUIControlBlock.cs:42)
    EditorGUIFramework.GUIWrapper.MainStackBlock (System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIWrapper.cs:145)
    EditorGUIFramework.GUIWrapper.Draw (Rect start, UnityEngine.GUIStyle style, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIWrapper.cs:84)
    EditorGUIFramework.GUIWrapper.Draw (Rect start, System.Action block) (at Assets/Vexe/Editor/EditorGUIFramework/Wrappers/GUIWrapper/GUIWrapper.cs:79)
    EditorGUIFramework.BetterPropertyDrawer`1[T].OnGUI (Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at Assets/Vexe/Editor/EditorGUIFramework/BetterPropertyDrawer.cs:107)
    UnityEditor.PropertyDrawer.OnGUISafe (Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label)
    UnityEditor.PropertyHandler.OnGUI (Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, Boolean includeChildren)
    UnityEditor.EditorGUI.PropertyFieldInternal (Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, Boolean includeChildren)
    UnityEditor.EditorGUI.PropertyField (Rect position, UnityEditor.SerializedProperty property, Boolean includeChildren)
    UnityEditor.EditorGUI.PropertyField (Rect position, UnityEditor.SerializedProperty property)
    UnityEditor.Editor.OptimizedInspectorGUIImplementation (Rect contentRect)
    UnityEditor.GenericInspector.OnOptimizedInspectorGUI (Rect contentRect)
    UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor editor, Int32 editorIndex, Boolean forceDirty, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect, Boolean eyeDropperDirty)
    UnityEditor.InspectorWindow.DrawEditors (UnityEditor.Editor[] editors)
    UnityEditor.InspectorWindow.OnGUI ()
    System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
    UnityEditor.PopupCallbackInfo:SetEnumValueDelegate(Object, String[], Int32)
     
  40. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @YinXiaozhou First thanks for dropping by. Second sorry for the delayed response.

    - Unity's serialization system is a pure PITA. I got totally different result from your first test case. Will see what that is about.
    - Because of the way Unity handles array drawing, the fact that it won't let you customize anything of that matter, and the way I'm doing my own custom layouting (because Unity's GUILayout is slow), it is currently difficult to achieve sequences of delegates.

    The only real way for me to fix all those issues, to have arrays of delegates, serializable nested delegates etc is for me to port my serialization and drawing systems from my VFW to be used in uFAction. I've been wanting to do that for a while but really couldn't find the time. In the meantime, if all you want is a basic delegate implementation you can check out the delegates in my VFW (link in my signature. its free): Pros: 1- support for delegates arrays/lists. 2- generic delegates serialization (so you don't need to subclass to create your delegates classes) 3- nested delegates serialization (so pretty much it covers all your concerns). Cons: 1- No extension methods support. 2- only one view style. 3- can't customize colors. 4- the delegate drawer has relatively simple functionalities than the drawers in uFAction. 5- No super-kickass delegate that you could use to hook methods with arbitrary signatures to. So I encourage you to try that out, while I port those systems to uFAction.

    Here's what you get in VFW



    Thanks.
     
    Last edited: Nov 13, 2014
  41. YinXiaozhou

    YinXiaozhou

    Joined:
    Oct 19, 2013
    Posts:
    133
    OK. I get the pain or Unity serialization. I'll try VFW. Thank you.
     
  42. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Guys, uFAction is now free, and I won't be developing it anymore. The effort is much more worth putting into VFW instead. I highly recommend anyone who tried ufaction to try VFW. offers so much more than delegates.
     
    Jessy likes this.
  43. Jlpeebles

    Jlpeebles

    Joined:
    Oct 21, 2012
    Posts:
    54
    Unity 5 apparently messed with the serialization on iOS. I see no issues on desktop, but on device it was trying to allocate over a gigabyte of data, and this was definitely from the Kickass Delegates. When I removed all delegates that had targets there were no allocation issues but I believe they were throwing null errors on device when being invoked. I have tried VFW but there appears to be serialization issues there too, not just on iOS, not sure if they are related to Unity 5. I reverted to before Unity 5 and things are going smoothly again, it's not imperative that I upgrade.
     
    Last edited: Mar 18, 2015