Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Interface instead of SendMessage

Discussion in 'Scripting' started by Ambrose998800, Jun 13, 2021.

  1. Ambrose998800

    Ambrose998800

    Joined:
    Jun 23, 2015
    Posts:
    59
    I just learned how to use interfaces instead of GameObject.SendMessage.
    Earlier I used the message system a lot (BroadcastMessage), mainly to control child-objects of items.

    Now I have objects with childs of childs of childs that need activation. GameObject.BroadcastMessage was easy to use for this, but how do I the same thing with interfaces?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    Only GetComponent<T>() works with interfaces unfortunately.

    BUT it is trivial to make an interface getter function for all interfaces in children:

    1. use GetComponentsInChildren<T>() (I usually use
    GetComponentsInChildren<MonoBehaviour>()
    )

    2. iterate all the returned Components and if they are an interface, add them to a list

    3. return the list (or convert .ToArray() if you prefer)

    EDIT: my info might be out of date; I didn't realize that what @VolodymyrBS suggests below could work.
     
    Last edited: Jun 13, 2021
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,533
    Yes GetComponentsInChildren does not have a generic constraint to Component anymore like all the GetComponent versions had in the past. So it does work with interfaces just fine. Also note that there is now a version that takes a List as argument to take the results. So if the capacity of the List is large enough, this would be a garbage free solution as well.
     
  4. VolodymyrBS

    VolodymyrBS

    Joined:
    May 15, 2019
    Posts:
    150
    It highly depends on how you code looks like, but basically replacement of BroadcastMessage by interface will look like this
    Code (CSharp):
    1. public interface ICoolInterface
    2. {
    3.     void UsefullMethod (int data);
    4. }
    5.  
    6. // in some method
    7. var components = GetComponentsInChildren<ICoolInterface>() ;
    8.  
    9. foreach (var component in components)
    10.     component.UsefullMethod(42);
    11.  
    12.  
    for better performance you could cache results of GetComponentsInChildren in some field;

    P.S. this is repost of previous answer because I delete it instead of edit :oops:
     
    Last edited: Jun 13, 2021
  5. Ambrose998800

    Ambrose998800

    Joined:
    Jun 23, 2015
    Posts:
    59
    Well, when I use it like this:

    Code (CSharp):
    1. IActivateItem[] Activations = gameObject.GetComponentsInChildren<IActivateItem>();
    2.  
    3.         foreach (IActivateItem Activation in Activations)
    4.         {
    5.             if (Activation != null)
    6.             {
    7.                 Activation.ActivateItem(Activate);
    8.             }
    9.         }
    I just get an editor crash: StackOverflowException: The requested operation caused a stack overflow.
     
    Last edited: Jun 13, 2021
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    Is this code inside of the ... .ActivateItem() method? :)

    Or are you calling it from OnEnable / OnDisable or something similarly circular?
     
    Bunny83 and Ambrose998800 like this.
  7. VolodymyrBS

    VolodymyrBS

    Joined:
    May 15, 2019
    Posts:
    150
    what do you do in ActivateItem method?
     
    Bunny83 likes this.
  8. Ambrose998800

    Ambrose998800

    Joined:
    Jun 23, 2015
    Posts:
    59
    Got it. My fault was to use this code above recursive in the activation function of the main item. Had to call it from an other method, then it works. Something learned. Thanks!
     
    Bunny83 likes this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    To understand recursion, you must first understand recursion.

    I do this a lot with properties inadvertently... i'll make a complex getter / initializer and then add some feature that interacts with it in a way that re-initializes it... and then it blows out the stack.

    Or I just forget to prepend underscore to the identifier and use itself recursively. :)