Classes as Message Arguments

.

Can I pass an instance of a class that I created as the argument in a SendMessage call?

I’ve tried to do it, but keep getting parsing errors that seem to be indicating that it isn’t something that’s going to happen.

Here’s a for instance. Say I have the following in a script on object “Sender”:

class CachedData {
	var pos : Vector2;
	var isGrabbed : boolean;
}

private var packedData : CachedData();

gameObject.SendMessage("Wakeup", packedData);

… I would think that the following in a script on object “Receiver” would be okay:

class IncomingData {
	var pos : Vector2;
	var isGrabbed : boolean;
}

private var myData : IncomingData();

function Wakeup (myData : incomingData) {
	x = myData.pos;
	y = myData.isGrabbed;
}

Thing is, the JS parser seems unhappy with the argument list on the Reciever object’s Wakeup function.

Am I barking up the wrong tree here? Coding it wrong? Or should I just pass an array in the SendMessage call?

TIA, all!

.

What is the error it’s giving you?

Something along the lines of “the function Wakeup does not recognize its argument”.

Sorry I can’t be specific right now, I’m away from my computer and wrote this post from memory.

Tell me though, is it possible at least to actually send a class as an argument?

Thanks for your reply!

I’m not sure, I’ve never done it, however it looks like SendMessage sends an Object.

That means that your receiving function needs to receive an object and then cast it into what it knows it is. It will not implicitly upward cast to an IncomingData object.

Kinda Like this:

function Wakeup (myData : object) {
   x = (IncomingData)myData.pos;
   y = (IncomingData)myData.isGrabbed;
}

quick written code, you may want to store the casted variable instead of casting multiple times, but hopefully you get the idea.

.

I’m back at my computer working with this, but I’m still not quite there.

I’m curious, should the word “object” be in the line that you scripted as exactly as shown (i.e. lowercase and all)?

function Wakeup (myData : object) { ...

Thanks, again!

.

Yes, if you look at the Scripting Reference:

You will see this:

function SendMessage (methodName : string, value : object = null, options : SendMessageOptions = SendMessageOptions.RequireReceiver) : void

the second parameter is value, and it is an object. object in mono is the base type of all Reference types(classes). You need to send and recieve in the same format, so if SendMessage sends an object whatever you called needs to recieve an object. Once you have it in the form of an object you can cast it to what you know it to be. But you cannot expect SendMessage to figure out on it’s own what you wanted to send and what you expect to be recieved.

If you are at your computer can you tell us what the error line is. It’s incredibly difficult to help remedy a problem when you don’t know what the problem is, but merely the situation that the problem can occur in.

I thought that maybe I needed to use “Object” instead, since the parser is saying that “object” is not a valid type when I use your code suggestion.

In answer to your question, the error message that I’m getting with my original code is as follows:

Thanks again for your help!

Here’s that full error message text:

Normally there is a second error with that one specifying that class a could not be cast into class b implicitly.

However, object is within the System namespace, so you may need to use using System; or import System; to include that namespace.

Does it matter that I am using Javascript?

Just curious.

I think in Javascript it’s import System;

But I’m not 100% sure, whatever format is normally used for including namespaces.

However the namespaces do work once imported, as it’s all in CLR in the end anyway.

import System;

is the format, place it at the top of your file. It will allow you to access the type object.

I did, but now I’m getting parsing errors on otherwise acceptable syntax.

Here’s an example:

That’s because Random is a class in both System and UnityEngine.

Your two options are:

  1. rename Random to UnityEngine.Random
  2. remove ‘import System;’ and rename object to System.object (this should work, but I’m not as sure)

I’ve tried using UnityEngine.Random.Range but things still aren’t working.

I’m curious, is it possible to pass Classes without having to invoke the System namespace?

Once you imported System, the code compiler does not know if you want to work with the “Random” class packaged with Unity (Unity - Scripting API: Random) or the “Random” class packaged with the .NET System DLLs (Random Class (System) | Microsoft Learn). Same name, different classes.

So simply, where ever you were using “Random” before, change it to “UnityEngine.Random” (thus telling the compiler exactly which one you want to use)

SendMessage uses System.Object (or alias: object)

You need to receive that type.
You could use something that isn’t SendMessage. SendMessage cannot automatically take an object of unknown type, and convert it into a type that it doesn’t know what it is.

I’m sorry I can’t really write an example right now, although if you google you should be able to find C# examples doing similar things (look up boxing and unboxing).

.

Thanks for your patience - I think I’m getting close now. :wink:

So, back in the Receiver script’s Wakeup function, I’m scripting as you suggested:

function Wakeup (myData : System.Object) {
   x = (IncomingData)myData.pos; 
   y = (IncomingData)myData.isGrabbed; 
}

… below but I’m getting parser errors indicating that the properties “pos” and “isGrabbed” are each “not a member of Object”.

.

.

Oops, I made a mistake in that last post.

When I use the code above, I don’t get the error I indicated. Actually, I get the following parser error for each of the lines that are trying to recast:

Should I code recasting differently since I am in JS? Using “as” maybe?

.

Ok, this is getting much closer.

Try:

function Wakeup (myData : System.Object) {
var data : IncomingData = (IncomingData)myData;
   x = data.pos;
   y = data.isGrabbed;
}

It does the casting earlier, but it should hopefully work. I’m unsure of casting syntax for javascript as I work in C#, but now that you’ve got the object all you need to do is tell the code that the generic Object that you’ve recieved is actually an IncomingData object. This should do that.

Edit: if ‘myData as IncomingData’ works you could try that as well instead of casting with ().

   x = (myData as IncomingData).pos; 
   y = (myData as IncomingData).isGrabbed;

–Eric