Search Unity

Wierd Unity Javascript Function Error

Discussion in 'Scripting' started by marty, Feb 6, 2006.

  1. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    I'm getting a wierd error when I call a function I wrote in Unity Javascript.

    The function header looks like this:


    function LevelDone (levelScore, levelOutcome) {
    ...
    }

    And the function call looks like this:

    objectwithfunction.SendMessage("LevelDone", levelScore, 1);


    The problem is, when I execute the functon call, I get the following error message:

    System.MissingMethodException: The best match for method SendMessage has some invalid parameter.



    I was hoping someone could clue me in to what might be wrong with my call, or maybe ellucidate that error message. I'm wondeirng, is SendMessage even the best way to call a function in another object?
     
  2. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    The best way to call a function, if you know the receiver, is to actually call the function.

    ie.

    Code (csharp):
    1.  
    2. var componentWithFunction : SomeClass;
    3. function Update ()
    4. {
    5.    componentWithFunction.LevelDone(1, 2);
    6. }
    7.  
    or if you have a reference to the game object. Just get the component in that game object and call the function. If you know the receiver.
    Code (csharp):
    1.  
    2. var someGameObject : GameObject;
    3. function Update ()
    4. {
    5.    var someComponent = someGameObject.GetComponent(SomeClass);
    6.    someComponent.LevelDone(1, 2);
    7. }
    8.  

    Only if you don't know the receiver you should use SendMessage.
    SendMessage looks in all scripts attached to the game object and calls the function if it exists. SendMessage can only take one parameter.

    Code (csharp):
    1.  
    2. var someGameObject : GameObject;
    3. function Update ()
    4. {
    5.    someGameObject.SendMessage("LevelDone", 1);  
    6. }
    7.  
     
  3. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    Thanks, Joe.

    I'm curious though, in the Scriptng Tutorial that you and DaveyJJ developed, you use FindObject-ish calls to communicate with classes and objects in your game, such as these:

    FindObjectOfType (text_time).guiText.text = levelTime.ToString("#,##0.0");
    var controller = FindObjectOfType(game_controller);


    Why did you do this, instead of using static, or more direct, references to the objects you wanted to reach?
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    You can do both.

    If you know that there will ever only be one instance of that particular class in your scene then it makes sense to use FindObjectOfType. This way you don't need to connect the variable in the inspector at all.


    If you directly connect a variable in the inspector, you will know exactly what it connects to, even if you attached the connected to script to several game objects. But you have to manually connect the variable in the inspector.
     
  5. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    Is all of this any different with script instances that are persistent across scenes (i.e. have been DontDestroyOnLoad-ed)?

    I ask because I have created a game controller script (based on the excellent DaveyJJ-Joe Unity Scripting tutorial) but my game controller does not seem to be receiving function calls from other scripts.

    I have initialized references to the script instances that I want to make calls to like this:

    var controller = FindObjectOfType(game_controller);
    var scorer = FindObjectOfType(score);
    var timer = FindObjectOfType(timer);

    While I can make functons calls to the 'score' and 'timer' objects instanced in the current scene, the 'game_controller' instance (created in a previous scene but told not to unload on new scenes) does not appear to "hear" function calls made using the 'controller' variable (i.e. controller.DoFunction).

    Any idea what might be wrong?
     
  6. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Are you sure the game_controller is actually there?
    Can you see it in the hierarchy view?
    Is the game object active?

    FindObjectOfType works regardless of objects marked DontDestroyOnLoad or not.
     
  7. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    Here's what I did:

    In the first scene of my project, I have an empty game object called 'controller' that I have attached an instance of the game_controller script to.

    As new scenes are loaded, the 'controller' object continues to appear in the hierarchy, with the instance of my game controller script attached.

    I'm not sure how I can tell whether or not the script instance is still active, but do know that I have not (knowingly) done anyhing to deactivate it.
     
  8. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    So when do you call
    var controller = FindObjectOfType(game_controller);?

    Can you post the full script?

    Also you might want to try if GameObject.Find works?
     
  9. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    I'm calling the function in the game_controller script from another script in the scene. That calling script is attached to an object in the scene which is attached to a mesh that is manipulated by the human player. Below is an abbrevated listing of the calling script:


    function Update () {

    // tell controller the level is complete and pass the score
    controller.LevelDone(scorer.AddToScore(0), 1);

    }
     
  10. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    The script seems fine. Probably an error in your setup.

    Maybe you should explicitly warn when any of the instances is not found:
    eg.

    if (scorer == null)
    Debug.Log("Scorer couldn't be found");
    if (controller == null)
    Debug.Log("Controller couldn't be found");
     
  11. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    Yeah, I tried that - you and DaveyJJ hinted at such an approach in your Scripting Tutorial.

    Unfortunately, no help - it looks like the instance is being found.
     
  12. IamBob

    IamBob

    Joined:
    Feb 4, 2006
    Posts:
    80
    Have you tried creating and calling a new function in the game_controller script?..

    function Test() { print("gotcha"); }

    just a thought to flesh out more details.
     
  13. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    Actually, that's the problem, no calls to functions in the controller work.

    Other script instances see the controller script instance, they can make calls to it - and all without any errors being reported, even if I require receivers for the calls. THe only problem is that the functions don't appear to be executing.

    It's downright wierd! ;-)
     
  14. IamBob

    IamBob

    Joined:
    Feb 4, 2006
    Posts:
    80
    Being a newb, I don't know that it makes any real difference but, maybe...

    If it's really called game_controller, have you tried renaming it to GameController instead?

    Just another random thought.
     
  15. marty

    marty

    Joined:
    Apr 27, 2005
    Posts:
    1,170
    Turns out the problem was that I had my target function set up as a coroutine, and thus could only accept one argument, instead of the two that I was passing.

    Thanks to everyone who posted help on this!

    And thanks in particualr to Joe, who as always, saved the day.