Search Unity

SendMessage is a trap

Discussion in 'Scripting' started by TurnBased, Sep 8, 2016.

Thread Status:
Not open for further replies.
  1. TurnBased

    TurnBased

    Joined:
    Mar 10, 2015
    Posts:
    4
    I've only been scripting in Unity for a couple months.

    I find myself heavily using SendMessage from object to object to trigger various pieces of functionality around the game. The result has been functional, but overly complicated and... how do I put this nicely... spaghetti.

    Does anyone have any good links to discussions or descriptions of philosophies that would help a newbie script-monkey keep on track and not create massive webs of cross communicating objects? I'm finding my habits are causing the need to constantly refactor.

    I get that the more experience I get the better my code will be, but I'm always looking for good advice!

    Thanks!
     
  2. bart_the_13th

    bart_the_13th

    Joined:
    Jan 16, 2012
    Posts:
    498
  3. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    generally avoid sendmessage, use references to call functions on specific objects (i.e. getcomponent etc.) and you might find looking up "events and actions" (or "unityevents and unityactions" they have made scene stored variants) is useful
     
    TurnBased likes this.
  4. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
  5. TurnBased

    TurnBased

    Joined:
    Mar 10, 2015
    Posts:
    4
    Thanks... these are the perfect kind of replies!
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    There is almost always a direct way to communicate between objects. Broadcasting and blind message sending can be misleading and wasteful, and as you have discovered, it can create a web of confusion and sends you to debug hell.

    For instance, if every object in the game needs to know when the game is paused, you can have a GameController that has OnPaused and OnUnpaused events, and every object that cares about pausing will subscribe to those on Awake.

    Some developers prefer broadcasted events, and they can be fine if used correctly. One good rule for broadcasting events is to never expect something to happen when you broadcast an event. Consider it a blind announcement that something happened, not a command or call to action.
     
  7. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    SendMessage had its uses when GetComponent didn't support interface type arguments as a generic way to say "do this thing if you have it".

    Now that you can get a component that implements an interface and get back typed intellisense there's not much reason to use it.
     
    DonLoquacious, Ryiah and Kiwasi like this.
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    SendMessage really should be pulled from the API. Between GetComponent on interfaces and ExecuteEvents, it really serves no purpose any more.
     
  9. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,813
    SendMessage may be required when a C# script needs to communicate with a JavaScript. I'm not sure if there's any other easier way of doing this other than using SendMessage.

    The docs gives a really bad example of using SendMessage
    http://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html
    and doesn't explain why you might need to use it.

    Also messages will not be sent to inactive objects, unlike calling the method directly where the function can still be called even if the gameobject or script is not active.
     
    Last edited: Sep 9, 2016
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    JavaScript should also be pulled from the API. ;)

    On a serious note I had forgotten about that one, its one of the few legitimate uses for SendMessage. The other possibility is to call private methods on components while avoiding reflection. But combining JS with C# and calling private methods are sketchy practices anyway.

    The example was written before you could call GetComponent on an interface. So at that point it was relevant.
     
    CodeSmile likes this.
  11. Lorenei

    Lorenei

    Joined:
    Aug 8, 2015
    Posts:
    8
    LeftyRighty and ArachnidAnimal like this.
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    What. Is. This?


    UnityScript supports interfaces, right? So if you've got a UnityScript script and a C# script in the same compile step, and need them to communicate, you can just put a interface one compile step earlier and communicate through that.

    Or you could stop using UnityScript like a sane person
     
  13. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Today I learned about the "print" function. o_O
     
  14. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,813
    But unfortunately, if you buy an asset from the asset store written years ago, you don't have a choice. The asset was created using UnityScript so you're stuck using UnityScript. This is the dilemma I run into with alot of the assets I buy.
     
    Alverik likes this.
  15. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    It can be useful if you want to pull method calls from a text file or allow the player to type commands into a debug console. But if you're using it by typing the method name directly into the code like in the examples, then there's almost always a better way to do it. Interfaces and events.
     
  16. digital-synapse

    digital-synapse

    Joined:
    Nov 18, 2017
    Posts:
    2
    Yeah as previously stated, dont use SendMessage. Use GetComponent<> with interfaces. You get type safety way more speed. Since you are calling typed methods through an interface you can also have listeners respond back with results. Take a look at my ComponentBase.cs which handles getting all the listeners and adds way more granular control to scoping for GetComponent. https://gist.github.com/digital-synapse/12bc70e494067b85564a2039d184b65c
     
  17. chriszul

    chriszul

    Joined:
    Feb 13, 2018
    Posts:
    33
    We also still need SendMessage for when you are building a webGL build. The unity webGL player is embedded in a webpage and the only way the containing page's javascript can communicate with the objects inside the unity runtime is through SendMessage. I think this is what @TTTTTa meant with his comment.

     
    Roman200333, digital_monk and Kiwasi like this.
  18. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    I think SendMessage is one of those things all Game Developers knew about when Unity was first made. It's in Unity since anyone thinking of switching from Torque or Unreal would expect to see it.

    This is when the strong coders hacked the C++ back-end to change how doors opened and jumping worked. While the game-play coders/level designers used a simple scripting language with LookAt and SendMessage. I think that's all UnityScript is, too -- something that looks more like what game coders were used to.
     
  19. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,512
    SendMessage is like using a Railgun when a .22 would work fine.
     
    CodeSmile and xen23 like this.
  20. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    Derp. It is what it is. Opting to pull a functional feature is utterly stupid.
    I'm pissy enough about features being pulled from products.
    “It's not needed.” is NOT an excuse to pull a feature from a product!!!
     
    Jingle-Fett likes this.
  21. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    So... I would use the railgun. You terrible point is not made.
     
  22. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    I think the argument isn't "It's not needed, so get rid of it", but rather "It's actively harmful to use and not needed, so get rid of it."
     
    xVergilx and Kiwasi like this.
  23. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    Uh, no it's not.
     
  24. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    Hey. Most of these responses 'could' be true(r) for BroadcastMessage, since it is inherently => broader.
    SendMessage targets a specific GameObject, and so it's nowhere nearly as notorious as this rabble make it out to be.
    It goes to the small handful of Components on a GameObject. If none of them have the function, no harm, no biggy.
    It has it's uses.
     
    halley likes this.
  25. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    With a username like "Luke Nukem", necroing an old post, just to actively disagree on a subjective opinion tossed out by a couple users...

    yeah, not surprised you'd use a railgun.
     
    xVergilx, Antypodish and SparrowGS like this.
  26. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Have fun with all of its weight(overhead)

    Just saying "no its not" is very childish, do you have reasons to back it up?
     
  27. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    Your response is ambiguous. Do mean "That isn't the argument" or "It isn't actively harmful"?
     
  28. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    The latter.
    I hope you don't find this response ambiguous.
     
  29. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    I don't, this one is clear. In that case, I suppose experience will be your teacher soon enough if you stick with development. Have a good one.
     
  30. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    it absolutely is, it always is.
    Thank you very much.
     
  31. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    I don't need to enjoy that, since I use the function well.
    If you get a lot of overhead from it, then you're doing it wrong, which doesn't surprise me.
    You are childish for thinking that's not possible.
    I back it up by 'doing' it. You should do the same instead of blindly cursing it like a novice.
     
  32. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Pot meet kettle, kettle meet pot.
     
  33. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    Railgun... Play Tiberian Sun for the best Railgun experience.
    You called my name, puny gnat. That is somehow an element for preferring to use a Railgun? Okay...

    I'm not a forum type. However, when I see incorrectness, sometimes I like to interject, depending on the severity.

    I'm not much into pot. I have a white kettle.
     
  34. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Yet you're a still a child.
     
  35. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    Yet, you're a gnat, no different to the rest of the online trolls.
    Indeed, I am naive to expect better from a developer forum.
     
  36. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    Hmmm...LaneFox's post, ending the thread a year ago, was nonsense, but it was such nonsense that didn't even need to be refuted. "using a railgun instead of a 22"? That implies SendMessage is more powerful, with corresponding overhead, which isn't really the case. Also, stop using gun metaphors.

    IMHO LukeNuke is correct (there's no reason to remove SendMesssage, since it's a standard "easy" command, and Unity is full of them); but is also a very rude person. Bragging about a secret superior way to use SendMessage... come-on. Just say that it works fine for you, and you have no need to desire to fix what isn't broken in your game-making style.
     
    LukeNukem44 likes this.
  37. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Here are my reasons why SendMessage should be removed:
    - Its slower then the alternatives
    - It relies on strings, which means it can't be checked at compile time
    - It encourages bad programming habits among beginners
    - It ignores access modifiers
    - Its clunky when it comes to handling parameters
    - It can't be followed through the compiler

    SendMessage advantages
    - It does late binding really easily
    - It can call private methods
    - It reduces the amount of interfaces required

    SendMessage is basically reflection light. Which means that you should only use it in places where you would be comfortable using reflection as your solution. If you know what you are doing, and are comfortable with the downsides and upsides, then go for it.
     
  38. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I'm not claiming to be a prophet or anything. But I have been right on this thread before about features being removed.

     
    LiterallyJeff and SparrowGS like this.
  39. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,512
    Any design dependency on SendMessage() will scale into a bad design. You can make more elegant solutions which improve usability, consistency and efficiency. Since it sends a message to every component, it has to iterate over every component. Designing anything around that is bad design and should be avoided - to illustrate, it's like consuming a lot of energy to fire a railgun at your target when a small rifle would just as effectively destroy it with significantly less energy. Since energy conservation is at the very fundamental core of good design I would assume the application was evident.

    It's unfortunate that the point of my illustration was so vigorously avoided, and instead devolved into a petty insult contest.
     
    okelenovo77 likes this.
  40. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,429
    You guys understand that SendMessage is identical to the mechanism that brings you OnCollisionEnter and Update, right?

    If I have a tank NPC object, and my generic gunner-AI component needs a target, and my generic turret-swivel component needs a target, and my generic cannon-firing component needs a target, I have choices. I can surely tightly couple the AI to the turret and cannon. I can surely write a separate interface script and maintain a list of ITargetting components which needs to get managed if the player can swap parts. Or I can send one message OnTargetAcquired and get on with my day. Because at the end of the day, developer time is money and 0.001ms is nowhere near as valuable.
     
  41. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,813
    I did a search for "SendMessage" and "BroadcastMessage" in my project and found a whole bunch of occurrences of it in the Unity Standard Assets. It's being used in many of Unity's particle system standard assets scripts, including Unity's ActivateTrigger class.
    It seems to be used as an alternative to interfaces.
    Nowdays that UnityScript is phased out, the right approach would be to use an interface I think.
    So if Unity was to obsolete this, they would need to update the Standard Assets to remove all occurrences which they themselves are using it.
     
    Lorrak likes this.
  42. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,512
    I would suggest profiling this.
     
  43. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Just because Unity made a bad design decision a decade ago doesn't mean we have to follow suit. I'll bet that if Unity were to write the engine from scratch today, they wouldn't use magic methods.
     
    DonLoquacious, xVergilx and ADNCG like this.
  44. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Oh, please teach me great master.

    There's overhead to using this, you can't argue about that - it's a fact, go profile that against a proper event system and see what's what (and not in a small demo that's designed to work around it).

    You are childish for putting words in my mouth, I asked what are your reasons for defending it, I never said anything is im/possible

    Oh and I suppose you (unlike everybody else in this forum) know my work? that's probably why you can tell "I'm doing it wrong", again - when did I "curse this like a novice"? all I did is say it has overhead, too much to be of any good in any big project.

    and how exactly are you 'doing' it?
    either you're holding some kind of secret about how this all works (in which case - please enlighten us) or you're taking a defensive position against something you use and don't wanna acknowledge is not the best.
    it has some uses for teaching begginers, but it has too many drawbacks as mentioned by @Kiwasi (the future teller, was thinking it the whole thread btw, lol) to be of any use in real life
     
  45. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    My last response here was from 2016. I'm really surprised that 3 years later people are still banging this drum, enough so to resurrect this post to flame about an old paradigm. If you want to use SendMessage, then just do it. There's no style cop at your house that will stop you (yet).

    I originally wrote a lot to express my thoughts about this topic, but then decided it wasn't worth my time to engage in this debate.

    @Kiwasi 's post above is a pretty good summary of the pros and cons.

    Here's something to think about:

    If you had to deliver a package to a couple of houses in a neighborhood. Would you go door to door delivering to everyone, or would you look up their addresses and deliver directly to them?

    Which way seems like less work?
    Which way seems more intuitive?
    What do you do if you need to receive payment for each successful delivery?
    Which way would be easier to figure out what happened if you never received any payments?
    What if you absolutely cannot deliver to houses with dogs out front?
    How many houses have dogs?
    What if you wanted to re-deliver to the same houses every day?
     
    Last edited: Jun 18, 2019
  46. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
  47. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    I like Owen-Reynolds, even though I'm "rude".
    He seems to know more.

    I just got done dealing with learning Gmail removed the Mark As Read option from the More menu.
    I found out that there is a little icon on the bar that does that function anyway, however, there's nothing pleasing about having the option removed. This made me feel like checking this thread.

    I'm not much of a forum user, so I give no thought about the apparent "age of the post" etiquette. It demeans you.
    Removing SendMessage doesn't give way to an equivalent option, and if it did, I'd still get annoyed about having to do it a different way.

    There's no reason at all to remove it.

    A valid reason, which no one here can mention, would be it does bad things. But it doesn't. So far, you're saying it has high overhead... Read Owen-Reynolds comment again, or this: It's nowhere near as bad as you like to make it out to be.
    I have already said, to the OP, that it's not as broad as BroadcastMessage, as it only target the scripts on a SPECIFIED GameObject. Read that again. Read it some more. And more. Keep going. You've almost got it. Now 20 more times, as it needs to sink into those extremely thick skulls. I'm not rude. That's just a thick thought. REREAD IT! I won't repeat this again!!!

    You just fail to see a very clear concept: Don't remove options!
    Plain and simple. If you like being wrong, keep talking your crap!
     
    halley likes this.
  48. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    SendMessage and BroadcastMessage are both evil and slow.

    Its bad for your application architecture. Its bad for scalability reasons. Its bad for performance.

    If you're using something like SendMessage, you're doing it wrong. Period.
    There's no "right" usage for it. Being lazy is not the use case in programming world.

    If you need an actual event to be passed, use events, or reactive.
    Heck, even static event is way better decision than this abomination that should've been removed ages ago.

    No, its not.

    Default Unity's messages have way less overhead than SendMessage.
    And they do have on overhead of being called.

    I'd suggest using custom dispatcher instead of these messages whenever you can. (for the Updates)
    But its sometimes too convienient to not be used.

    OnCollisionEnter is bad for different reason. Its called too often.
    Sometimes not even you want it to be called. And sometimes it simply doesn't get called at all.

    Resulting in an extra checks that drain mobile battery due to CPU work and extra overhead that could've been completely avoided if better solution to be applied.
     
    Last edited: Jun 18, 2019
    DonLoquacious and SparrowGS like this.
  49. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    17
    I like the good points you make after insulting SendMessage.
    However, if you think that about SendMessage, then you're doing it wrong.
    Hint: One right way to use it is: Not in frame update.

    (not creating events) is not equal to (being lazy)
    However, that is a lazy argument by you, which I am getting used to here.
     
  50. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Never suggested anyone something like that and never done that. That's like Extra Evil ^ Billion.

    It is equal to being lazy.

    I've been integrating one SDK lately, so its super relatable.
    They've used SendMessage as an backward event pass from the native plugin side to the managed.

    So I've lost a bunch of time just because of game object being named differently than that plugin expects.
    Which caused SendMessage to fail miserably.

    If those SDK developers introduced one single event, let it be default C# default one, I would've saved a lot of time, brain power and nerves. I get that they may not be as good Unity developers as Android / IOS ones but here's that.
    Bear in mind, that is a payed SDK with backend support.

    Those people aren't amatures, they're either extremely lazy or extremely lazy.

    And as you can see, SendMessage is prone to human error.
    GameObject renamed - you're F***ed. Method refactored by someone - you're F***ed.

    All of these can be avoided by declaring a couple of lines of code from the managed side, and adding native -> managed bridge.

    But who needs that, when there's SendMessage?
     
    SparrowGS likes this.
Thread Status:
Not open for further replies.