Search Unity

[RELEASED] IUnified - C# Interfaces for Unity!

Discussion in 'Assets and Asset Store' started by Roland1234, Oct 25, 2013.

  1. Hacky

    Hacky

    Joined:
    Mar 22, 2013
    Posts:
    28
    Hi Roland,

    sry for uploading your files. I'm very sorry.
    And thank you very much for help. May be you stressed this fact in your read me or give an example scene with your asset.

    Best regards,
    David
     
  2. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    No worries, I managed to get a moderator's help to remove the upload in good time - I think hardly anybody noticed and there wasn't much damage done. An example scene sounds like a good idea, I'll have to think of something interesting for that so it might take a while.

    Let me know if you continue having trouble with the missing characters, I may have a potential work-around/solution for that but since I can't replicate the issue I'm a bit hesitant to include it in an official release and would need your help to verify that it does actually address the problem. Send me an e-mail (in the readme) if you're interested.

    Good coding to you!
     
  3. Game-Whiz

    Game-Whiz

    Joined:
    Nov 10, 2011
    Posts:
    122
    Just bought your plugin. Whenever I click "Select from list" Unity crashes with an out of memory error. This is happening in 4.5.2. Any idea on what's going on?
     
  4. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    I may have an idea, yes - it's possible this may be occurring if you have enough large assets included in the project that could make Unity crash should they all be loaded into memory at once. Could you verify if this is happening in a new empty project?
     
  5. Game-Whiz

    Game-Whiz

    Joined:
    Nov 10, 2011
    Posts:
    122
    That's probably it. It doesn't crash on an empty project.
     
  6. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Thanks for checking that, it gives me a lead to try for a solution. I have a possible fix that I would like to be able to test in your case, could I impose on you to send me an e-mail to try it out?
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Bought it because I'm always interested...

    Just to be clear, you don't save interfaces; you only wrap a generic type around the only polymorphic serializable type; UnityEngine.Object. I was hoping you found a way around that polymorphic issue, oh well.

    Would have been nice if you could expose the property that uses the interface to the Inspector.
     
  8. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Correct - all IUnified does is bridge the gap to allow code design that depends on interfaces for abstraction (at the cost of introducing a generic type for each interface), but it still depends on Unity's limitations regarding what can be serialized and what can't. The implementation still needs to be a UnityEngine.Object, most likely an existing instance of a MonoBehaviour or ScriptableObject. Anything can be assigned to the container during runtime, regardless of it's type, but that's runtime only.

    You probably know that there are alot of caveats when working with Unity's serialization system, and adding references via interfaces just complicates the issue since it can be implemented by just about anything (including structs, which Unity doesn't really support if I remember). I thought it was a good compromise to depend on Unity's serialization system and simply allow for their referencing via interfaces to allow for more managed abstractions in code.

    I've toyed with the idea of handling the serialization/deserialization myself, but that's a really broad topic and goes fairly deep. May I ask, in more detail, what sort of functionality would you find useful that you were maybe expecting to see? I may be able to figure out a good compromise to make the asset about 20% cooler.

    Brohoof,
    Roland
     
  9. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    393
    Hi,

    Have found this tool very useful so thanks for the great work. One thing I'm having a problem with is drawing my Interface in a custom editor.

    I have a class 'Row' that holds a list of my interface class:

    Code (CSharp):
    1.  
    2.  
    3. public class Row : MonoBehaviour {
    4.  
    5. [SerializeField]
    6.     public List<Field> fields;
    7.  
    8.  
    The fields class is where I have my Validator Interface

    Code (CSharp):
    1.  
    2. [System.Serializable]
    3. public class Field
    4. {
    5.       // Validator
    6.     [SerializeField]
    7.     public AssetViewer_IValidateProperty myValidator
    8.     {
    9.         get { return validator.Result; }
    10.         set { validator.Result = value; }
    11.     }
    12.  
    13.     [SerializeField]
    14.     private AssetViewer_IValidatePropertyContainer validator;
    15. }
    16.  
    Now I want to draw a custom inspector, which allows me to make many fields each with a different validator. If I make the 'fields' variable NOT a list I can call:

    Code (CSharp):
    1. serializedObject.Update();
    2.                 EditorGUILayout.PropertyField(serializedObject.FindProperty("fields"), true);
    3.                 serializedObject.ApplyModifiedProperties();
    No problem! However, as soon as I make 'fields' a list I'm completely shot. Any ideas on this one?

    Thanks!
     
  10. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Hello silentslack!
    Sorry I'm just replying now, I haven't had any support issues in quite some time. As far as I can tell everything should be working properly, the only thing that looks vaguely suspicious is your decorating your Field.myValidator property with the [SerializeField] attribute - not that it should be doing any harm, as far as I know it's just superfluous.
    I'll have to try and replicate the issue as soon as I have a chance, in the meantime: does the field show up as a list in the default inspector (i.e. not defining your own custom inspector)?
     
  11. silentslack

    silentslack

    Joined:
    Apr 5, 2013
    Posts:
    393
    Hey man, no problem :)

    Removing the custom editor doesn't solve things. If the field is a single variable your custom property drawer shows up, as soon as it's a list it goes.

    I've kinda hacked together a workaround by making the 'Field' class a Monobehaviour, not ideal but by adding it as a component I get the property drawers in the inspector and can still populate the 'fields' list.

    If you do find a solution it would be grand but I have something working so all is good. Thanks for the great plugin, slowly getting my head around interfaces!
     
  12. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    I've tried recreating your scenario and everything I see indicates that it should be working properly. Would it be possible for you to e-mail me a project showcasing the weirdness (my address is in the .pdf readme)? It'd really help me out - I'd hate to leave a potential bug lying around and having to make an object a MonoBehaviour when you shouldn't have to is a bit of a pain, eh?

    Oh and thanks for the compliments, that's always in demand : D - if you are still getting the hang of language features like interfaces don't hesitate to ask, I like going over that type of thing with others. Interfaces themselves are pretty simple, but can be powerful abstractions.
     
  13. sohojoe

    sohojoe

    Joined:
    Feb 13, 2015
    Posts:
    21
    Hey man, sounds great - but does it play nice with Unity5; I get the following when I click the download button:

    Possible incompatibility with Unity 5
    This package was published using Unity 4 and contains asset types which may not upgrade cleanly to Unity 5:
    • Scripts
    While Unity will generally attempt to upgrade assets to work, problems may still occur.For more information about upgrading projects to Unity 5, please refer to the Unity 5.0 Upgrade Guide.
    For more information about the compatibility of this specific package, please contact the publisher directly.
     
  14. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Hello sohojoe,
    Yes, the latest version (1.3.4) should work just fine in Unity 5. If you do discover an issue then please let me know, but everything should be completely functional.
     
  15. ESG-Steven

    ESG-Steven

    Joined:
    Mar 18, 2015
    Posts:
    38
    Hey Roland,

    Love the idea of the asset. Does it work with classes instead of interfaces? I have multiple situations where I require default functionality and variables which remove the ability to use an interface without awkward structure, so I use an abstract class instead.

    EDIT:
    To elaborate, I keep getting "No assets implement or derive from MovementController" every time I open the custom editor thing you have. I tried it with an interface but I still get the text. Not sure what I did wrong.

    Code (CSharp):
    1. public interface MovementController
    2. {
    3.     void initialize(Action<Coord> onComplete);
    4.  
    5.     void start();
    6.  
    7.     void end();
    8. }
    9.  
    10. [Serializable]
    11. public class MovementControllerContainer : IUnifiedContainer<MovementController> { }
    12.  
    13. //NEW FILE:
    14.  
    15. public class DerivedClass : MovementController
    16. {
    17.     //Some Implementation
    18. }
    In my object I just have:
    [SerializeField]
    protected MovementControllerContainer _movementController;

    Thanks,
    Steven
     
    Last edited: Jul 22, 2015
  16. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Hello Steven!
    The idea of the asset is that it will basically serialize any reference that Unity normally would, except it allows for access to that reference as the type specified by the container. What this means is that it will not, by itself, instantiate objects or expose their properties but simply hold a reference to it like any other Unity component.

    The message you are seeing indicates that there are no instances of Unity components of the type specified in your container either in the scene (as MonoBehaviours) or in the project assets (prefabs, etc). Try adding an object and attaching a component that implements your interface and it should show up in the selection list. Make a prefab out of it and it should show up in the "Project Assets" tab of that list as well.

    Finally, it should indeed work with containers that specify a class type instead of an interface if you follow the same rules as you would with interfaces i.e. you have instances that are of a type that Unity can serialize. So the container will be able to hold a reference to an abstract class that derives from MonoBehaviour, but at that point you are dealing with a type that Unity can serialize and expose natively (Unity does handle abstract classes as expected) and are honestly better off not using the asset in that case. In my opinion. Unless you've found some interesting use for my container that I hadn't considered.

    Let me know if you still can't get things working or have any other questions.
    Good coding!
     
  17. ntszar

    ntszar

    Joined:
    Aug 9, 2015
    Posts:
    1
    Hmm, Is there something that I am missing? Altogether it seems pretty simple (And Great!) But no Matter what I cannot achieve the functionality to drag and drop Implementation onto the Inspector.
    my code:

    Code (CSharp):
    1.  
    2. public interface DetectionMethod
    3. {
    4.     bool Detects(GameObject detectedObject);
    5. }
    6.  
    7. [Serializable]
    8. public class SightDetection : DetectionMethod
    9. {
    10.     public bool Detects(GameObject detectedObject)
    11.     {
    12.         return true;
    13.     }
    14. }
    15.  
    16. [Serializable]
    17. public class DetectionMethodContainer : IUnifiedContainer<DetectionMethod>
    18. {
    19. }
    20.  
    21. public class DetectionMethodComponent : MonoBehaviour
    22. {
    23.     [SerializeField] public List<DetectionMethodContainer> DetectionMethods = new List<DetectionMethodContainer>();
    24.  
    25.     public void Start()
    26.     {
    27.         var s = new DetectionMethodContainer();
    28.         s.Result = new SightDetection();
    29.         DetectionMethods.Add(s);
    30.     }
    31. }
    32.  
    33.  
    Using the code below I attached the Detection Method Component Script to my Object.
    Thanks to my Start function in the DetectionMethodComponent after running 'Play' in Unity, I get 1 entry in the list "SightDetection". so It works I guess.

    However when i try to add elements using the Unity UI nothing happens (the element row is grayed out).

    Also when using your GUI functionality to try to add the item from the list i am getting:
    'No assets found that implement or derive from DetectionMethod'

    Any hint as to what I am doing wrong?


    Update:
    It seems that it start to working after SightDetection inherits from MonoBehavior... And Put an instance of SightDetection somewhere in the code, It probably shwos that I am beginner with Unity now but =). Is there a way not to instantiate the object in the Scene at all and just Drag and drop from the Script directory?
     

    Attached Files:

    Last edited: Aug 13, 2015
  18. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Due to the way Unity serializes objects, there is no straightforward way to get the functionality you want. You'd have to integrate some custom serialization into Unity to do that, which is what I've seen some other assets do. I haven't really tried any of them so I can't recommend a particular one.

    While IUnified allows you to reference things via an interface, you still have to follow the basic rules of Unity's serialization system. Although Unity can serialize objects decorated by the [Serializable] attribute: be careful. They are handled differently. They will be rooted in their parent component and deserialized as unique instances, even if you set them to the same object. They will function as expected while in the editor until you go through a serialization/deserialization phase and then bam you'll lose the common reference without error until things start acting wonky depending on what you're doing with your code (still bites me from time to time).

    But I digress.Your implementation needs to be of a type that Unity can already serialize references of: anything inheriting from UnityEngine.Object should work, which will most commonly be MonoBehaviours and ScriptableObjects. You won't be able to hold references to other objects, even [Serializable] ones, just as you wouldn't be able to do if you had a field of an abstract type that didn't inherit from UnityEngine.Object - Unity wouldn't know what to instantiate for it. Once your game is actually running though, you can set the container's Result property to anything implementing the interface, since you won't be dealing with serialization/deserialization issues any more.

    I realize this can be confusing to people, especially if you're new to Unity because it has its own way of doing things that isn't always what you'd expect. Let me know if you have any questions and I'll try to clarify things better. If I know the answer, of course.

    Good coding, and thanks for the support!
     
  19. Pixsaoul

    Pixsaoul

    Joined:
    Feb 10, 2014
    Posts:
    14
    Hey I just bought your asset and it seems to do perfectly what I want, I think I'll create a specific item template in visual that create the interface with the container to make it even easier ;)

    I know it's been a long time since the last message here, but have is there any performance impact on your implementation ? if so, is it only in the editor ? at runtime ?

    Thanks for the amazing job, I can start to reuse interface again and avoid breaking every solid principle in my project.
     
    Roland1234 likes this.
  20. Pixsaoul

    Pixsaoul

    Joined:
    Feb 10, 2014
    Posts:
    14
    Hello, I've had an issue with the drag n drop of my instances into IUnified field for a while (2019.1.1 unity version).
    The last IUnified field of any component could not be droped on. Adding a dummy field last makes the previous one works.
    I'm testing the 2020.1.0a15 and now the drop is working again but There is a log error in the IUnifiedGUIHelper:

    NullReferenceException: Object reference not set to an instance of an object
    Assets.IUnified.Editor.IUnifiedGUIHelper.BuildBoxTexture (UnityEngine.Color bgColor, UnityEngine.Color borderColor) (at Assets/ThirdParty/IUnified/Editor/IUnifiedGUIHelper.cs:84)
    Assets.IUnified.Editor.IUnifiedGUIHelper.Initialize () (at Assets/ThirdParty/IUnified/Editor/IUnifiedGUIHelper.cs:353)

    If anyone runs into this issue on 2019 version, try to upgrade ;) (maybe in 2020). I haven't done any further investigation to fix the error that pops out.
     
    Roland1234 likes this.
  21. lhy_ps2

    lhy_ps2

    Joined:
    Feb 6, 2014
    Posts:
    6
    var boxTexture = GUI.skin.box.normal.scaledBackgrounds[0];
     
    Roland1234 likes this.
  22. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    I apologize for not answering sooner, as you point out it has been a long time since the last message. I've submitted an update to the store that will fix the null reference issue, but it is still in review (or you can apply @lhy_ps2's fix above on IUnifiedGUIHelper.cs:84).

    I'm still working on a fix for some drag and drop issues I've noticed started happening, but I believe the specific one you had mentioned will have been addressed in the update I've submitted. I wish I could say so more definitively but I wasn't able to reproduce what you describe. Send me an email and I can send you a copy of the updated version, if you'd rather not wait until it passes review.

    As far as your earlier question regarding performance: The performance impact in runtime should be negligible, all of the heavy lifting is done in editor code and I've not noticed a perceivable impact in the editor either.

    Apologies again for the late reply.
     
  23. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Version 1.3.10 is in the asset store and should fix all UI issues from Unity 2018.2 and on. And thanks to all who have taken the time to report issues they've discovered - it's been a long time now and I've been busy, busy, but still determined to maintain the package as much as I can. Cheers!
     
  24. Pritchard

    Pritchard

    Joined:
    Aug 30, 2013
    Posts:
    5
    Hi, bought the package today - great stuff!
    I was wondering, would it be possible for structs to be supported? I'm aware that there are quite a few limitations imposed on this addon by the fact that it has to work with Unity's serialization system, but even a few ideas on how it might be done could enable me to make the changes myself.
    The specific use case I bought IUnified for was to create UI elements based on some simple data structures - ie, a Button struct that contains a label and UnityEvent that's automatically set up on the actual button object by code.

    I have it working with IUnified, which is great! Unfortunately, because it only supports MonoBehaviour or ScriptableObject, the data for the buttons has to exist in the scene, since the UnityEvents need to be able to reference other gameobjects in the scene. (And ScriptableObjects can't do that in any circumstances)

    Before I was using IUnified, I had a list of Button structs which could all be set up inside the list itself, which is my ideal implementation. Of course, then I couldn't support other types of list content, so it was quite limited.

    Either way, IUnified is still great! Thank you for providing support for all these years.
     
  25. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Hello Pritchard, thanks for the support!

    I'd have to look into your use case in more detail when I have the time, but my instinct is that support for structs would either be impossible or spotty and difficult to maintain.

    I don't have any great ideas off the top of my head, unfortunately, I think I had concluded that a general solution just wasn't tenable: Unity is an odd duck when it comes to serialization, and its support for custom serialization isn't very good (at least from what I remember).

    If I do figure something out I'll be sure to update this thread.
    Cheers!
     
  26. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,941
    Hi @Roland1234
    I just bought your plugin for Unity 2020.2

    Can you please tell me how can i do GetComponentsOfType<Interface> to avoid manual drag and drop?

    PS: Its an Editor Script to save time

    Please advise
     
  27. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    Hello @jGate99, apologies for the delay - I rarely get support requests these days.
    If you are whom I think you are then I responded to your email, but for everybody else's reference: I would suggest using UnityEngine.Component as the the type parameter for GetComponents*<T> methods and then using the OfType<T> Linq extension method to filter down the results to the interface type you are interested in, so something like:

    Object.FindObjectsOfType<Component>().OfType<IMyInterface>()

    or, from a MonoBehaviour:
    GetComponentsInChildren<Component>().OfType<IMyInterface>()

    etc.

    Cheers!
     
    ph3rin likes this.
  28. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,941
    Thanks, Sent a reply to that email.
     
  29. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    205
    Is IUnifiedContainer an interface or an abstract class?

    Also, it looks like the Asset Store is down?