Search Unity

SendMessage problems

Discussion in 'Scripting' started by wayne1512, Nov 21, 2017.

  1. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    Script1:
    public GameObject TileInfoSource; //this links to the script which has the recieving end of the message.
    TileInfoSource.SendMessage ("UpdateTile", "tiles", 1); //message

    On the other script:
    void UpdateTile (string layer,int id) {
    .......................
    }



    on the massage It shows me the compiler errors:
    1. The best overloaded method match for `UnityEngine.GameObject.SendMessage(string, object, UnityEngine.SendMessageOptions)' has some invalid arguments
    2. Argument `#3' cannot convert `int' expression to type `UnityEngine.SendMessageOptions'

    pls help
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    It's pretty clear what it says. The third parameter should be a SendMessageOptions type, not an int. However, SendMessage is horrible and shouldn't be used.

    You should be using GetComponent instead and make the method public.
     
    wayne1512 likes this.
  3. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    @Brathnann but the reciever has "void UpdateTile (string layer,int id)" so It's asking for the
    • MessageName = UpdateTile
    • String Layer
    • and int id
    so 3 arguments string,string,int
     
  4. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    also Isn't the get component only used to get access to components like rigid-body,mesh....
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    SendMessage takes up to three values. It's not calling the method the same way as if you call it directly.
    https://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html

    The reason sendmessage is bad is it will run it on all Monobehaviors, so it's not a good one to use.

    No, GetComponent is used for all components. Even personal scripts.

    GetComponent<OtherScript>().UpdateTile("somestring", 1); works as long as UpdateTile is public. Though depending on how often you call that script, you might just want a reference to the script instead of calling get component every time.
     
    wayne1512 likes this.
  6. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    Thanks for your help... I'll do this later cause I gtg now.
    So the getComponent can be used like that with all functions?

    And If SendMessage is sent to all Monobehaviors than why does it need something before it like in my case TileInfoSource.SendMessage???

    And will the getComponent send it to ALL the objects who have this script or just 1?

    And last question: The other script(the one recieving the message) has to send a message back to the sender with things like textures(sprites),ints... Do I just add a GameObject on the UpdateTile and write "this" on the sending?
     
  7. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Yes, GetComponent works for all your scripts and all the components that Unity already has setup.

    SendMessage sends to all Monobehaviors on a target. So if you had 3 scripts on the gameobject, sendmessage hits each one, even though you only mean to send it to one of them most likely.

    GetComponent gets a reference to the instance on a particular gameobject. So you still want to target a gameobject
    otherGameobject.GetComponent for example. If you don't target a gameobject, it checks the same object as the calling script.

    I'm not really sure what you mean with the add a gameobject and write this on the sending. If your method has a return value, it can be returned to the calling script just like normal. If you need more, you can also pass in a method to get a callback on.
     
    wayne1512 likes this.
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    If you need more than 1 returned value, perhaps if you describe your situation, we could offer an idea for how to setup your function (and/or what to return) :)
     
  9. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    @Brathnann you said "you might just want a reference to the script instead of calling get component every time." If I did that what would the varieble type be.. since its not GameObject???
     
  10. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    @Brathnann Also what would I do if I wanted to send a message to only 1 tile.
     
  11. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    @methos5k nvm... i'll just otherGameobject.GetComponent like Brathnann told me... tnx anyway
     
  12. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Well, let's use an example of two scripts

    Code (CSharp):
    1. public class TileManager : MonoBehaviour
    2. {
    3.    public List<Tile> tiles;
    4.  
    5.    void Start()
    6.    {
    7.        tiles[2].DoSomething(1);
    8.    }
    9. }
    10.  
    Code (CSharp):
    1.  
    2. public class Tile : Monobehaviour
    3. {
    4.    public void DoSomething(int aNum)
    5.    {
    6.  
    7.    }
    8. }
    So in this example we have a Tile component and a TileManager component. The TileManager maintains a list of Tile (your variable type). You can then call the script from the list.

    To clarify a bit, if you have several gameobjects in your scene with the Tile script on them, each one has an instance of that class on them. You're just setting up the reference to that instance. If you have a list of GameObjects you can just do GetComponent on whatever gameobject you want to access it on, but it's perfectly fine to do the list of Tile. In this case, I'm just assuming a drag and drop of your Tile Objects into the list on the TileManager, but you can add them to the list other ways as well through scripting.
     
  13. wayne1512

    wayne1512

    Joined:
    Oct 23, 2017
    Posts:
    84
    What I want is to do so when the tile is clicked:

    It sends a message with the layer(tiles,furniture,plumbing,electrical) and id of the block(ex: dirt=1,stone=2 on layer tiles)to the script with all the sprites.
    The sprite script sends back some variebles including 3 sprites and 1 bool (and possibly more) back to the tile that requested.


    so example the tile would send that it needs furniture no.3 then the sprite script sends it 3 sprites that make up the texture of furniture no.3 (may need to add more variebles in future)