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

Question How to use events in Unity to force one script to call the method of another script?

Discussion in 'Scripting' started by Kujji, Mar 15, 2023.

  1. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    I read information and documentation about action, c# event and UnityEvent, as i understand you better not use UnityEvent because they are slower than c# event and action, but to use event or action you need to use public static to make one script subscribe to an event which is in another script, what is not safely.

    So the question is how to use action or event without static right?
     
  2. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    Events do not need to be static.
    They CAN be public, but are not required to (you can e.g. add your own "AddListener"/"RemoveListener"-Methods.
    One particular quirk of events is that they can only be invoked by the class that owns them (not even subclasses can invoke them).
     
  3. Homicide

    Homicide

    Joined:
    Oct 11, 2012
    Posts:
    657
    Hmm, either im way out to lunch, or this is incorrect.

    For eg: i have a static class GlobalEvents. These events can be invoked from anywhere, anytime.
     
  4. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    Should've used the term "Raise" instead of invoke, since that's what's used for events.

    https://learn.microsoft.com/en-us/d...to-raise-base-class-events-in-derived-classes

    Afaik events can only be raised by their containing class.
    This might be different for static events/classes?
     
    Homicide likes this.
  5. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    How can i subscribe listener from another sctipt to script where not static event created and invoked?
     
  6. Homicide

    Homicide

    Joined:
    Oct 11, 2012
    Posts:
    657
    Depends on the specific event type, but generally...

    otherScript.eventName.AddListener(OnEvent);
    --
    or
    --
    otherScript.eventName += OnEvent;

    Again, perhaps i am not interpreting correctly, but it should be that easy.
     
    Kujji likes this.
  7. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    Error - An object reference is required for the nonstatic field, method, or property 'member',
    can't apply to public ation or event
     
  8. Homicide

    Homicide

    Joined:
    Oct 11, 2012
    Posts:
    657
    object reference really shouldnt be an issue. You alone know what objects you have, where they are, so get your reference,
     
    Kujji likes this.
  9. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    Made by using Action, short version:
    in first script

    public event Action OnHitAction;

    and then invoked it

    in second script

    Player player = new();
    player.OnHitAction += Hit;
     
    Homicide likes this.
  10. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    This will only work if your Player is not a monobehaviour.
     
    Homicide likes this.
  11. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    For MonoBehaviour Player i made it like this:
    in second script

    private Player _player;
    _player = GetComponent<Player>();
    _player.OnHitAction += Hit;
     
    FrankvHoof likes this.
  12. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    960
    So given the nature of your question I'd say you are a relative beginner to this. And as such it worries me that no one has yet to let you know that you must also be sure to unassigned your event listeners when you no longer need them. Failure to do so can lead to memory leaks.

    One thing to note about UnityEvents is that they are just a wrapper class for standard C# events. But they include several additional features such as always ensure you can invoke them even when they have no listeners (which throws and exception), support for use in the inspector and serialization so that you can save listeners. And automatic cleanup on object destruction so that memory leaks are avoided. Don't worry about the performance implications at this point. They will not affect you in any way shape or form.
     
  13. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    Where should i unassigne event listener? I assigne it in awake and need to be listened for whole game time.
     
  14. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    Normally you'd do that in an OnDisable or OnDestroy.
    Edit: When unassigning you might need to check if the player != null
     
    Sluggy and Kujji like this.
  15. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    960
    Yes, as a general rule I follow that pattern. If I assign a listener in Start or Awake I unassign in OnDestroy. If I do it in OnEnable I undo it in OnDisable. There are of course always exceptions but this is the baseline you should always consider starting with for any kind of resource you are managing yourself.

    This sort of practice makes life easier when you start getting into dynamically creating and removing objects or enabling and disabling them when doing things like pooling.
     
    Kujji likes this.
  16. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    Thanks!