Search code examples
c#facebookunity-game-engineunity-web-player

Load CanvasFacebook.dll without Unity Integration (or other bridge options)


I am working on Unity3d game that I wish to publish on Facebook.

Information about setup:

As you know, Facebook Canvas provide option to use Unity Integration. Description of this options is:

"Yes" to use the Facebook Unity SDK

But I want to have custom canvas page that is shown before unity player is loaded. So that's why I need to stop using Unity Integration of Facebook Canvas. So currently I have a server that serves my application. Everything works fine except the unity plugin.

First problem I faced is the lack of CanvasFacebook.dll and AuthToken.unityhash files. I solved this by downloading them from this link (dll) and this one (unityhash). And placed them in appropriate paths (rsrc/unity/lib/sdk_6.1/CanvasFacebook.dll and rsrc/unity/key/sdk_6.1/AuthToken.unityhash) on my server. So now FB.cs loads this dll without problems.

But now I another problem. In FB.cs there is a code:

var fb = typeof(FBComponentFactory)
         .GetMethod("GetComponent")
         .MakeGenericMethod(facebookClass)
         .Invoke(null, new object[] { IfNotExist.AddNew }) as IFacebook;

This code works when I use Unity Integration in Facebook Canvas. But when I disable Unity Integration and run application inside of facebook - mentioned code executes and fails (without any errors or messages). How do I know that it fails? Well, it doesn't go further. Simple check - add Debug.Log("Got/Added CanvasFacebook component"); right after var fb = ... ; and see that Log method is not called. BTW, I have a log handler that calls something like Application.ExternalCall("console.log", message), but with some pretty stuff.

Ok, so I tried to check, why this code is not working with custom canvas. Why I think that dll is loaded and should work? Because right after

var assembly = Security.LoadAndVerifyAssembly(www.bytes, authTokenWww.text); ... var facebookClass = assembly.GetType(facebookNamespace + className);

facebookClass is not null and equals to CanvasFacebook. More over, I found that

var methodInfo = typeof(FBComponentFactory)
                 .GetMethod("GetComponent")
                 .MakeGenericMethod(facebookClass);

Also works. It's just the problem with invoking this method. When I try to

var fb = methodInfo.Invoke(null, new object[] { IfNotExist.ReturnNull }) as IFacebook;

Call works, but fb is null. So I checked FBComponentFactory class using ILSpy on IFacebook.dll from sdk. And here is class definition:

using System;
using UnityEngine;
namespace Facebook
{
    public class FBComponentFactory
    {
        public const string gameObjectName = "UnityFacebookSDKPlugin";
        private static GameObject facebookGameObject;
        private static GameObject FacebookGameObject
        {
            get
            {
                if (FBComponentFactory.facebookGameObject == null)
                {
                    FBComponentFactory.facebookGameObject = new GameObject("UnityFacebookSDKPlugin");
                }
                return FBComponentFactory.facebookGameObject;
            }
        }
        public static T GetComponent<T>(IfNotExist ifNotExist = IfNotExist.AddNew) where T : MonoBehaviour
        {
            GameObject gameObject = FBComponentFactory.FacebookGameObject;
            T t = gameObject.GetComponent<T>();
            if (t == null && ifNotExist == IfNotExist.AddNew)
            {
                t = gameObject.AddComponent<T>();
            }
            return t;
        }
        public static T AddComponent<T>() where T : MonoBehaviour
        {
            return FBComponentFactory.FacebookGameObject.AddComponent<T>();
        }
    }
}

So now I think that the problem is with adding component. But it doesn't throw any errors (well, I couldn't catch any using try catch). So I tried to AddComponent from FB.cs explicitly (I know that this is ugly hack, but I am just trying to understand the root of problem):

var type = typeof(FBComponentFactory);
Debug.LogError("I got type: " + type);
var fieldInfo = type.GetField("facebookGameObject", BindingFlags.NonPublic | BindingFlags.Static);
Debug.LogError("I got fieldInfo: " + fieldInfo);
var go = fieldInfo.GetValue(null) as GameObject;

if (go == null) {
    Debug.LogError("go is null, so creating new one");
    fieldInfo.SetValue(null, new GameObject("UnityFacebookSDKPlugin"));
    go = fieldInfo.GetValue(null) as GameObject;
}

Debug.LogError("I got go with name: " + (go == null ? "null" : go.name));
var component = go.AddComponent(facebookClass);
Debug.LogError("got component of type: " + component.GetType());
var fb = component is IFacebook;

I use log errors, because they will call console.error and it's a bit easier to see in browser logs.

So when I build game with this changes and run inside of facebook canvas, I see next output:

[Error] 7.24    I got type: Facebook.FBComponentFactory
[Error] 7.24    I got fieldInfo: UnityEngine.GameObject facebookGameObject
[Error] 7.24    I got go with name: UnityFacebookSDKPlugin

But the code Debug.LogError("got component of type: " + component.GetType()); is not executed. No errors, no exceptions. Executer (or how does it called) simply moves out from this method and goes on. I can play my game, but facebook plugin is not working.

And again. Previous code doesn't throw any exceptions (at least, I couldn't catch them using try catch).

Also, when I check Player.log file, I see:

7.24    I got type: Facebook.FBComponentFactory
7.24    I got fieldInfo: UnityEngine.GameObject facebookGameObject
7.24    I got go: UnityFacebookSDKPlugin
7.24    got component of type: Facebook.CanvasFacebook

So it shows that everything is fine. But actually, plugin is not loaded. When I try to use FB.Login I see:

180.49  Facebook: tried to login but we're not init'd yet.

Question(s)

Sorry for such long post. But here are my questions:

  • Does anyone know what the hell is happening here?
  • Is it possible that CanvasFacebook dll is corrupted?
  • I couldn't find any information about such behaviour of AddComponent. Have anyone experienced something similar?

And main question:

Is it possible to use Facebook Unity SDK and custom canvas? I know that I can just create my own bridge between JS SDK and Unity SDK, but I don't like the idea, when I know that someone already created it and the only problem - creating CanvasFacebook component.

Thanks in advance.


Solution

  • The question is rather old. But since version 7.0.0 of facebook plugin described flow is possible.

    For more information checkout official documentation.