Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Is there a way to make an UnityEvent have a return value?

Discussion in 'Scripting' started by VXPuddiM, Jan 20, 2018.

  1. VXPuddiM

    VXPuddiM

    Joined:
    Jan 23, 2017
    Posts:
    10
    I want to be able to choose a condition in the inspector, just like a delegate (i'm not using delegates because they don't show up in the inspector).
    Something like this would be perfect:
    Code (CSharp):
    1. public UnityEvent someEvent; // Event is choosen in inspector
    2.  
    3. public void Start()
    4. {
    5.     int someVariable = someEvent.Invoke(); // Doesn't needs to be an int especifically
    6. }
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    5,660
    That's not really how events work.

    Consider if you attached multiple listeners to said UnityEvent... which one's result would you be returning?

    I guess you could say the last one attached (which is how delegates work in C#). But nope, that's not how UnityEvent works, they just forego that oddity all together.

    Events as a design are really just a way for one object to say "I did something". So other objects can react to that thing it had done. The alerting object isn't really supposed to change its behaviour based on who happened to listen to it. It creates a really weird dependency with a loose link between them.

    If you need that sort of dependency. Instead just have a direct reference to that listener. Just have a field of the type of the listener, and attach it directly. Then call the method of importance on it.
     
    AndersMalmgren, karl_jones and Ryiah like this.
  3. Lysander

    Lysander

    Joined:
    Feb 24, 2013
    Posts:
    1,497
    Yep, in general, though I'm reminded that I do have a specific class in my General assembly that functions as a priority queue version of an event, and the listeners can consume the event and keep the remainder of the queue from being called afterward. That's not returning a value to the event invoker, but to the event handler itself though (and not returning anything so much as just changing a value in the eventargs).

    If you need a value sent back to the invoker, you should pass in a callback delegate as a parameter to the invoke method. This enables all listeners to "return a value" to wherever the invoker specifies, but it doesn't demand it the way a return type does.
     
    Last edited: Jan 20, 2018
    lordofduct likes this.
  4. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    626
    if you need to implement conditions, you can define an interface ICondition and classes implemented ICondition like below:
    Code (CSharp):
    1. public interface ICondition{
    2.    bool CheckCondition();
    3. }
    4. public class CCondition:Monobehaviour,ICondition{
    5.    [SerializeField]
    6.    float disTH;
    7.   [SerializeField]
    8.    public bool CheckCondition(){
    9.         float dis;
    10.         //Compute the distance between the gameobject and the target
    11.         return dis<disTH;
    12.    }
    13. }
    Therefore you can call GetComponent<ICondition>().CheckCondition()
    you can define an array of conditions with operators as well
    Also you can write your own custom editor
     
  5. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    68
    For future googlers

    I created an asset similar to UnityEvent but has return values. Usage is exactly the same as UnityEvent, and performance is similar as well. Comes with a default "Condition" that returns a bool. No interfaces or inheritance required.
    34294989-46de127e-e70b-11e7-84f0-99bc4525a8f5.png

    Check out the github repo: https://github.com/Siccity/SerializableCallback
     
    Samacvuk and andymads like this.
  6. Samacvuk

    Samacvuk

    Joined:
    Jan 8, 2017
    Posts:
    25
    Man this is AMAZING, this should be part of unity.
     
    Siccity likes this.
  7. Drago1

    Drago1

    Joined:
    Jul 29, 2015
    Posts:
    2
    Great decision, but I have problems after building my pc app. When I used yor asset, it didn't launch and I found it was because of more than one instances of serialized class or classes, who's parent is SerializableCallback<>, for example:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Example : MonoBehaviour
    4. {
    5.     [System.Serializable]
    6.     public class IntReturnIntEvent : SerializableCallback<int, int> { }
    7.  
    8.     public IntReturnIntEvent getPower;
    9.     public IntReturnIntEvent getVelocity;
    10. }
    By the way, in Editor ewerything works great. Have any idea, how to fix it?
     
  8. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    68
    Hmm, I've never had a problem with it on mobile platforms, but I'm getting issues on pc build too. Not sure what's causing it though. I'll have a look at it sometime soon.
     
  9. Drago1

    Drago1

    Joined:
    Jul 29, 2015
    Posts:
    2
    Is there any result in problem solving?:)
     
  10. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    68
    No, sorry, i forgot all about it. And now i just tried and can't reproduce it. Can you send your Unity version and possibly the error/line you're getting?
     
  11. SlapworthFH

    SlapworthFH

    Joined:
    Jun 16, 2017
    Posts:
    3
    This looks awesome, and is similar to something I've started searching for in Unity. I wonder if you have any thoughts about it?

    I've started wondering if there was a way to have an inspector UI that lets you choose specific VARIABLES on a target property. For example, say I wanted to build a bit of UI that was designed to display an arbitrary float variable, and intended to be cloned in multiple locations on a canvas to show different floats with identical presentation.

    The dream is that I could take one of those UI components, and via an Inspector interface point it towards a float variable on some other component on some other object. That would let the UI be reusable without having to write custom script to reference specific source floats to drive it.

    The SerializableCallback is the closest thing I've found, but works with methods. The dream version of this would use a similar interface to define a reference to variables.

    Does anything like that exist already in Unity? Is there a conceivable path to having such a thing? This seems like it mighe be a breadcrumb on that path: https://forum.unity.com/threads/access-variable-by-string-name.42487/

    Thanks - SlapworthFH
     
  12. cicchi

    cicchi

    Joined:
    Jan 12, 2017
    Posts:
    1
    Hi Siccity,
    thanks four your work.
    I downloaded SerializableCallback code from the link you provided and I followed the instructions to create a serializable condition. Like this:

    Code (CSharp):
    1. [Serializable]
    2. public class SerializableCondition : SerializableCallback<bool> { }
    It works perfectly in Unity, but if I make a build and install it on an Android phone, the game crashes when it tries to load the prefab that contains a SerializableCondition member.

    It's pretty easy to reproduce the issue.
    1) Create a game object
    2) Create a MonoBehavior script having the previous SerializableCondition as a field
    3) Assign a boolean function to the SerializableCondition in the Inspector
    4) Make that game object a prefab
    5) Create an instance of that prefab when loading your Main Scene...and Boom. Game crashes.

    So if everyone is interested, be aware that at the moment it does not work on a mobile device.