- Home /
My SendMessage is problematic [SOLVED]
Hi all,
I have a script attached to my enemy object (at the moment it's nothing but a cube, so no parent/child issues), which, among other things, calls this function when it dies:
var levelController : Scoreboard; // was var levelController : GameObject; var scoreWorth = 5;
function YouBeDead() { levelController.AddScore(scoreWorth); // was levelController.SendMessage("AddScore", scoreWorth); Instantiate(explosion, transform.position, Random.rotation); Destroy(gameObject); }
(levelController is a GameObject var, and scoreWorth is an int var) My issue is with the levelController line. It sends a message to my Level Controller script, telling it to add x amount of points onto my player's score:
var totalScore : int;
function AddScore(scoreWorth : int) { totalScore += scoreWorth; print (totalScore); }
function OnGUI () { GUI.Label (Rect (0,0,100,50), "Score: " + totalScore); }
The strange part is, it calls the function fine, but it doesn't send the value of scoreWorth. As a test, I put the line print(totalScore);
in the AddScore function, and every time I kill an enemy it does print, but it prints 0, so obviously the value isn't travelling with the message.
As always, it's probably something exceedingly simple, but I'm just not seeing it, and am starting to get cranky with it :P
Thanks for your help!
Kristof
(p.s. it's "Javascript", not "Java" - they are very different things! - ftfy)
Whoops! I should've known that, guess I just wasn't thinking :P
Answer by duck · Dec 02, 2010 at 07:41 AM
Have you defined "scoreWorth" as a var in your levelController script? if so, this class-wide definition may be conflicting with the "local" definition that you are trying to set up in the function's parameters. The correct way to do this is to not have a var declared with the same name as your function parameter names.
However, since you already have a variable as a reference to your levelController gameobject, you could go one step further and make that a reference to the script on that gameobject by changing the variable's type to the name of the script. Eg, instead of:
var levelController : GameObject;
You could have:
var levelController : LevelController;
(Assuming your script is named with an initial captial, which is the convention in Unity dev)
This means your variable is now set to receive an object whose type is "LevelController" - the type that you created when you made a script with that exact name.
Once you have this set up, if you drag your levelController gameobject into that slot, the reference will now be to the script instance on that object, rather than the object itself. This means you no longer have to use "SendMessage" to transmit messages, and can instead call the function directly, for example, instead of:
levelController.SendMessage ("AddScore", scoreWorth);
You can have:
levelController.AddScore(scoreWorth);
The benefits of working in this way are many, but to name a few:
- It's shorter and more readable
- It executes faster, and so is more optmial at runtime
- Certain common types of errors are checked at compile-time (typos or incorrect params)
Hope this helps!
---- EDIT ----
Apparently it didn't so here's another thing to try:
If your enemies are being dynamically instanced, then having a reference to the LevelController prefab sounds wrong - they ought to have a reference to the instance of that prefab in the scene.
I understand the problem is that you can't drag in these references because when in edit mode, the enemies don't exist in the scene in order to be able to drag references into them.
There are two ways that spring to mind to solve this:
Have the script that instantiates the enemies "tell" the new instances about the LevelController reference. Or...
Have the enemy instances "find" the LevelController reference in their own start functions.
To implement number 1, you would have a reference to the LevelController object in your "EnemySpawner" script (or whatever it's called - the important thing is that this presumably is on a gameobject somewhere in your scene).
In this script, it creates a new enemy instance, and then immediately after, in the same function, it passes the LevelController reference it has to the enemy, like so:
var levelController : LevelController;
// "Enemy" is the name of the script on your enemy prefab var enemyPrefab : Enemy;
function SpawnEnemy() { var newEnemy = Instantiate(enemyPrefab, newPos, newRot);
// now the levelController var on the new enemy is assigned the
// same reference that this script currently holds:
newEnemy.levelController = levelController;
}
Alternatively (number 2) - this is one of the situations where using one of the many "Find" functions is a good idea. You could find the levelController by the name of the gameobject, by its tag, or by the type of script attached.
Seeing as you know there is only one of this kind of object in your scene (or there should be, right?) you can make your enemys find this object using a single line of code in their Start function:
// this var is "private" because it doesn't need assigning externally private var levelController : LevelController;
function Start() { levelController = GameObject.FindObjectOfType(LevelController); }
Although I prefer your method vastly, it still has the same problem. Perhaps this has something to do with it, although i don't really think so: The enemies are instantiated from prefabs, and the prefabs have the script (it's called Scoreboard; the Game Object is called LevelController) referenced. However, since an object only in the scene can't be referenced in a prefab, I had to make LevelController a prefab and reference that.
I initially thought that was the problem, but I don't think it explains why it calls the function properly, and just doesn't send the value along... Does it?
Excellent! Finally got it to work, using the second method; thanks so much, I was at my wits end!
Your answer
Follow this Question
Related Questions
What is the best way to call a function from another script 1 Answer
How to call a function from another script without referencing it? 1 Answer
How to reference another script and call a function in C# ? 2 Answers
Calling a function from a different script on the same object 1 Answer
Sendmessage - return value 1 Answer