Understanding An Argument, Plugin

Hi there,
I am using a plugin to access the Facebook Graph API. I am struggling understanding some of the arguments I need to pass tho. I am hoping some of these good people can help me understand it.

Example…

public void fetchProfileImageForUserId(string userId, Action<Texture2D> completionHandler)

The above is called if I would like to get the user id picture, obviously. However, I do not know the string, for userId, nor do I understand what the Action completionHandler is.

Can anyone help me understand these?
Thanks

What class does fetchProfileImageForUserId exist in? I can’t find it in the Facebook Graph API for Unity references.

Me neither
Did you try following the tutorial? (which includes picture retrieval)
https://developers.facebook.com/docs/games/unity/unity-tutorial

It’s the prime 31 plugin. Facebook.instance…

My issue is sorting the arguments. I get how everything is related and works, but how do I know what userId is, and what is an Action ?

And yes, I actually was able to achieve this without Prime31, just via the Facebook API, however since Twotter has no similar API, I thought it would be best to just use Prime31 keeping Twiter and Facebook under the same umbrella so to speak.

Okay, found the “documentation” I think I was better off without it :stuck_out_tongue_winking_eye:

Alright, I can explain Action but you’re on your own for userId (I assume it must be the login name of the image you want to get?)

You can think of Action<> as a delegate. In other words, it is a variable which, instead of holding a value, holds some code. That code can then be executed at a later time by “invoking” the variable. In this context, the SDK is providing a way for you to get the image asynchronously. The SDK will probably spin up a separate thread to do the download and once completed, will “invoke” the code that you send along as an Action.

To understand Action<> I think you first need to learn about delegates.

Consider the following (familiar) function:

private void Update()
{
}

Let’s dissect what is called the “signature” of this method.
The first keyword “private” tells the compiler that other classes may not call this function - it is only accessible from within its containing class.
The second keyword “void” tells the compiler that this function does not return a value. That doesn’t mean it does nothing, it just means that if another function called this one, it shouldn’t expect anything coming back.
The third term “Update” is the functions name
The brackets indicate where the parameter list starts and ends - in this case, there are no parameters
In total, we say the “signature” of this method is no arguments and no return value.

I’m sure you’ve seen more interesting functions. Here’s a few samples top facilitate our continuing discussion:

public void Log(string message)
{ // ...
}

This function has a different signature: it accepts one string argument and has no return value

public int Add(int a, int b)

This function accepts two integers and returns an integer.

Delegates are pretty straight forward once you understand signatures. Let’s create a delegate for the Log function

delegate void StringOperation(string theString);

This creates a new type and you can declare a variable to have this type. When assigning into this variable, the compiler will make sure you are type safe. In otherwords, you can’t put something into a variable with type StringOperation unless that thing is the same type as StringOperation. For delegates, the type equality is based on signatures.

StringOperation myFunctionVariable = Log; // this is OK because Log() has the same signature as the StringOperation delegate
myFunctionVariable = Add; // this will cause a compile time error because Add(int, int) does not have the correct signature

To create a delegate which could contain Add, you could use the following:

delegate int BinaryOperation(int a, int b);
BinaryOperation myAdditionFunction = Add;

Now… onto Action<>

An Action<> is actually just a quick way of talking about a certain type of delegate. Action is a delegate with no return value and no parameters. Action is a delegate with no return value and one string parameter. Thus:

delegate void StringOperation(string theString);
StringOperation myLogFunction = Log;
// is equivalent to
Action<string> myLogFunction2 = Log;

Action<int, int> is a delegate with no return value and two integer parameters.
Action<> can be used to describe any delegate that does not have a return value. In order to describe delegates with a return value, such as one which could contain our Add function, we have Func<>.

Anyways… that’s a topic for another day… Let’s get back to the parameter requested by this SDK.

public void fetchProfileImageForUserId(string userId, Action<Texture2D> completionHandler)

The second parameter in this function is requesting a delegate which accepts one Texture2D parameter and has no return value. This method will be called after the image has completed downloading so that you can apply the texture to something in your game. You can think of this method as a “continuation” or “callback” and could do something like this:

void Start()
{
  fetchProfileImageForUserId("eisenpony", ApplyImage);
}

void ApplyImage(Texture2D theImage)
{
  // Apply the texture, contained in theImage, to your mesh
}

Thank you very much @eisenpony ,
So are you saying that the Action<>, is essentially a void? Meaning, I declare the action as …

void ApplyImage(Texture2D theImage){
}

And now, I can pass that void…action, as the argument for action in the fetchProfileImageForUserId()?

If so, if its that easy, that is brilliant! Thank you.

I think you’ve got it.

To be clear, it is a function that you are passing, which happens to have a void return type and a Texture2D argument.

1 Like

Right,
So in short, an Action<> is a function with a return type that can be passed as an argument?

Hmm… that’s not quite how I would put it.

Action is a type which represents a delegate to a function with no return type (void) and no arguments.

Action is a type which represents a delegate to a function with no return type (void) and one Texture2D argument.

In your case, you need a Action which could be any function that has no return type (void) and accepts a Texture2D argument. So, if you had a class:

class MyClass
{
  void ApplyImage(Texture2D theImage)
  {
    // apply the image to the mesh
  }
}

Then the method MyClass.ApplyImage could be put into a variable of type Action.

Thus, you can call your SDK’s function by simply giving it the name of this method

class MyClass : MonoBehaviour
{
  void Start()
  {
    fetchProfileImageForUserId("eisenpony", ApplyImage);
  }
  void ApplyImage(Texture2D theImage)
  {
    // apply the image to the mesh
  }
}
1 Like

Awesomeballs.
Good reading.

I appreciate your professors stylings.
Cheers!!

EDIT:
I may have just solved, will update when confirmed, but I declared a vairable and placed it as the argument passe. Duhhhh.

//orginal post.
Cheers.

Hi @eisenpony
Thanks again, for your help.
However, I have run into an issue with an action based argument I am using in a subscription.

//Static event Action as defined in plugin.
public static event Action<object> graphRequestCompletedEvent;
//I want to subscribe to the event, as so I have done...
FacebookManager.graphRequestCompletedEvent += fb_graphRequestCompleted;
///...and then set up a return void with an action<object> as an argument.
public void fb_graphRequestCompleted(System.Action<object> obj){
print("graph request completed");
}

…However, I am told the argument here System.Action does not match the original. However, as far as I can see, they are identical.

?? Any ideas?
And thanks

Action refers to a delegate which takes an Object as a parameter, so you subscribing method should have the following signature:

void fb_graphRequestCompleted(Object obj)

Hm.
I used…

publicSystem.Action<object> objectForCompletion;

And in the void (subscription)…

public void fb_graphRequestCompleted(object objectForCompletion){
print("graph request completed"); 
 }

This has no errors.

I’d need to see the rest of the script to be sure but I think

publicSystem.Action<object> objectForCompletion;

is redundant.

Also,

public void fb_graphRequestCompleted(object objectForCompletion){
print("graph request completed");
}

there’s no reason to name your parameter after the variable above. In fact - it could be misleading if your variable is a class variable. The parameter will now override the class variable when working in the method scope unless you explicitly refer to this.objectForCompletion.

Anyways, if it works without errors then that’s a good start!

Hm,
I don’t follow you.
How would you execute this?

Given:

//Static event Action as defined in plugin.
public static event Action<object> graphRequestCompletedEvent;

Create:

///...and then set up a return void with an object as an argument.
public void fb_graphRequestCompleted(object obj){
print("graph request completed");
}

And subscribe like:

//I want to subscribe to the event, as so I have done...
FacebookManager.graphRequestCompletedEvent += fb_graphRequestCompleted;

No need for:

public System.Action<object> objectForCompletion;

Ok will try.
I was thinking it, the argument needed to be an action of type object.

This will take a while. Not on cloud yet, so the builds to the device from Unity take sometime.

Thank you again!!!

Ps. just pre build.

As mentioned in our messages.
I am told that the arguments I am passing are null (nothing to do with the subscription process above)…

Please see…

System.Action<Texture2D> imageTexture;
public void btnPressed_fb_GetImageID(){ 
//public void fetchProfileImageForUserId( string userId, Action<Texture2D> completionHandler)
Facebook.instance.fetchProfileImageForUserId(meString, imageTexture);
 }

I had applied this method last build, but while error free, got no response/reaction/function performed in Facebook. The plugin creator is suggesting I am passing a null argument. I am curious as to if this will cause the issue again.

Also, I rearranged the code a bit after going back and looking at your help. I thought perhaps the argument imageTexture, needed to be a delegate void passImage(Texture2D image);
but still an error of incorrect type.

What is the way to insure that the Action portion of the argument is not null?

Okay, lets try to narrow things down a bit.
Let’s just talk about fetchProfileImageForUserId for a minute. Do you get a response form this?

Ok, I will leave you alone for a bit.

The plugin, as I forgot, has examples.

mainly, where I am declaring an Action to be an argument, completionHandler, the examples show, this is instead…

       //commoneventhandlerusedforallgraphrequeststhatlogsthedatatotheconsole
voidcompletionHandler( stringerror, objectresult )
 {
if( error != null )
Debug.LogError( error );
else
Prime31.Utils.logObject( result );
 }

So, as you see, I was way off. I am sorry for this, I am just trying to wrap my head around something that is still abstract to me.

Cheers