Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Problem with facebook SDK, "there are 2 event systems in scene" after initializing facebook FB.Init

Discussion in 'General Discussion' started by rpuls, Sep 12, 2022.

  1. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Hello, I am having a issue that I don't know how to deal with, when using the Facebook SDK 14.1.0.

    When I call FB.Init() which initialized the SDK package, It moves my EventSystem to "Don't destroy on load". When I then load any other scene, there is now two EventSystem objects, one that used to control the canvas events on the scene, and now also the one moved to "Don't destroy on load" - and unity starts spamming the warning:
    There are 2 event systems in the scene. Please ensure there is always exactly one event system in the scene

    The same happens when I go back to the main scene, because it is now loaded with the EventSystem that was there originally, plus the one from Don't destroy on load....

    1. I can't remove the original one from the main scene, otherwise the user can't click any buttons to begin with, and I don't always want to initialize the Facebook SDK, this is an additional optional thing in my game.

    2. I could remove all other event systems from all other scene, but this would be a massive pain, since I can no longer run 1 scene at a time when developing... Not ideal - and this still doesn't solve the issue that there will again be 2 event systems in the main scene each time that one is loaded.

    There has got to be some scripting trick that checks if there is an EventSystem in don't destroy on load, and if so, then destroy the other event system - when a scene is loaded? Or what would be the right way to handle this?

    Thanks!
     
  2. xjjon

    xjjon

    Joined:
    Apr 15, 2016
    Posts:
    605
    I don't think FB.Init should create any event system unless one doesn't exist in your scene, maybe you have a singleton script on your EventSystem game object that is targeting the entire gameObject and not just the component? Or your original scene didn't have an event system?

    Here's what FB.Init created for me:
    upload_2022-9-12_16-47-23.png

    You can check the code to see - maybe your version is different
    But here's the fb init code

    Code (CSharp):
    1.           switch (Constants.CurrentPlatform)
    2.           {
    3.             case FacebookUnityPlatform.Android:
    4.               FB.OnDLLLoadedDelegate = (FB.OnDLLLoaded) (() => ((AndroidFacebook) FB.facebook).Init(appId, onHideUnity, onInitComplete));
    5.               ComponentFactory.GetComponent<AndroidFacebookLoader>(ComponentFactory.IfNotExist.AddNew);
    6.               ComponentFactory.GetComponent<CodelessCrawler>(ComponentFactory.IfNotExist.AddNew);
    7.               ComponentFactory.GetComponent<CodelessUIInteractEvent>(ComponentFactory.IfNotExist.AddNew);
    8.               break;
    9.             case FacebookUnityPlatform.IOS:
    10.               FB.OnDLLLoadedDelegate = (FB.OnDLLLoaded) (() => ((IOSFacebook) FB.facebook).Init(appId, frictionlessRequests, FacebookSettings.IosURLSuffix, onHideUnity, onInitComplete));
    11.               ComponentFactory.GetComponent<IOSFacebookLoader>(ComponentFactory.IfNotExist.AddNew);
    12.               ComponentFactory.GetComponent<CodelessCrawler>(ComponentFactory.IfNotExist.AddNew);
    13.               ComponentFactory.GetComponent<CodelessUIInteractEvent>(ComponentFactory.IfNotExist.AddNew);
    14.               break;
    Which will check your scene during Awake() for CodelessUIInteractEvent:

    Code (CSharp):
    1. if ((UnityEngine.Object) UnityEngine.Object.FindObjectOfType<EventSystem>() == (UnityEngine.Object) null)
    2.       {
    3.         GameObject gameObject = new GameObject("EventSystem");
    4.         gameObject.AddComponent<EventSystem>();
    5.         gameObject.AddComponent<StandaloneInputModule>();
    6.         UnityEngine.Object.DontDestroyOnLoad((UnityEngine.Object) gameObject);
    7.       }
     
  3. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Hi, thanks for sharing your code example ! :)

    Mine is indeed quite different, I am only calling FB.Init() - or, I have cut away everything else because I was trying to locate what call makes the EventSystem "not destroy on load", and I have concluded that it is the FB.Init(). There might be much variation depending on what SDK version is used, but the documentation doesn't mention anything about this as far as I can tell.

    I have checked my EventSystem object, there is no scripts or anything custom attached to it. It's the one that came automatically when I created a canvas.

    This is what my hierarchy looks like prior to starting the player:


    I have create a bare minimum script, that only contains a function that will initialize Facebook and nothing else, and attached that function to a button OnClick event:



    When I play the scene, the EventSystem object stays where it is (pic 1), right until the moment I click the button that calls the CallInit() function. Then the EventSystem object is moved out of the main scene hierarchy, and appears instead under the "don't destroy on load" section (outside the scene scope?)


    So, I don't think that the Facebook SDK is creating a new EventSystem, it's more like it is making the one that exist global, which I don't know why - or how to deal with, since I have even systems on other scenes as well.

    So ether, there should be a way to tell FB to not make it "don't destroy on load", but I can't find any information on that.
    Or, there should be a way for me to do it manually (with scripting moving it back into the scene hierarchy?) - I'm not sure how I target the EventSystem GameObject, and what to call to get it "back in scene" - and I'm not sure if the is advised?
    Or, some like....: OnSceneLoad check for duplicate EventSystem and delete one - this sounds to me like the least favourable approach - creating unwanted object and deleting them.
    Or, something completely different that I can't think of.
     
  4. xjjon

    xjjon

    Joined:
    Apr 15, 2016
    Posts:
    605
    The code snippets I shared was from the FB SDK - just followed into FB.Init() to see what it was doing.

    You should be able to navigate to the FB SDK code and see what it's doing to when you press the button.

    I don't believe the FB SDK has changed much in regards to the unity code. `CodelessUIInteractEvent.cs` is where. In the Awake() method of CodelessUIInteractEvent (which is created by FB.Init()) it will look for a game object of type EventSystem - if it can't find one then it will create one and set it to DontDestroyOnLoad. Try to verify if your version of the SDK does the same

    Anyways I think another thing you could try is just creating an empty scene with a simple component that just calls FB.Init() in Awake(). Or try their sample scene, then you can isolate why your scene results in 2 EventSystem
     
    rpuls likes this.
  5. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Good tip thanks! - Could you point me to the path/directory where you found facebook SDK code? (the file you are referring to) - when I search "CodelessUIInteractEvent.cs" in the assets, I don't find anything.
     
  6. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Alright, I did as suggested. Created a brand new scene, only added a canvas and a button, then made the button trigger FB.Init() - and I must say I was kind of suspicious that it would not reproduce, and that it would indeed be because I am having some dark magic in my main scene that I have forgot about, but no. It reproduced exactly as in the main scene.

    To demonstrate I decided to do a screen recording. Sometimes visuals add valuable input to the brain storming, and I have become very determined to understand what's going on - and solve it.
    Here is the video clip:


    I forgot to capture the console, but I believe the output could be valuable... After the button is clicked, and FB.Init() is called, the following logs were printed in the console:

    1 Warning:
    This example uses Unity Engine OLD input system. If you are using new Input System and you want to use this example, please set your input configuration to BOTH.
    UnityEngine.Debug:LogWarning (object)
    Facebook.Unity.CodelessUIInteractEvent:Awake ()
    UnityEngine.GameObject:AddComponent<Facebook.Unity.CodelessUIInteractEvent> ()
    Facebook.Unity.ComponentFactory:GetComponent<Facebook.Unity.CodelessUIInteractEvent> (Facebook.Unity.ComponentFactory/IfNotExist)
    Facebook.Unity.FB:Init (string,string,bool,bool,bool,bool,bool,string,string,Facebook.Unity.HideUnityDelegate,Facebook.Unity.InitDelegate)
    Facebook.Unity.FB:Init (Facebook.Unity.InitDelegate,Facebook.Unity.HideUnityDelegate,string)
    FacebookTest:CallInit () (at Assets/Scripts/FacebookTest.cs:8)
    UnityEngine.EventSystems.EventSystem:Update () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:501)
    2 Warning:
    You are using the facebook SDK in the Unity Editor. Behavior may not be the same as when used on iOS, Android, or Web.
    UnityEngine.Debug:LogWarning (object)
    Facebook.Unity.FacebookLogger/DebugLogger:Warn (string)
    Facebook.Unity.FacebookLogger:Warn (string)
    Facebook.Unity.Editor.EditorFacebook:Init (Facebook.Unity.InitDelegate)
    Facebook.Unity.FB/<>c__DisplayClass36_0:<Init>b__1 ()
    Facebook.Unity.FB/CompiledFacebookLoader:Start ()
    3 Info:
    Using Facebook Unity SDK v14.1.0 with FBUnityEditorSDK/14.1.0
    UnityEngine.Debug:Log (object)
    Facebook.Unity.FacebookLogger/DebugLogger:Info (string)
    Facebook.Unity.FacebookLogger:Info (string)
    Facebook.Unity.FB:LogVersion ()
    Facebook.Unity.FB/CompiledFacebookLoader:Start ()

     
  7. xjjon

    xjjon

    Joined:
    Apr 15, 2016
    Posts:
    605
    You can view the source by 'ctrl' + click the method name in your IDE.

    So if you ctrl + click the Init() part of FB.Init() it should bring you to it.

    If that doesn't work, you can also view the source on their github. I see you are on v14 so I took a look at their changes and looks like they updated it here to make the EventSystem always DoNotDestroy

    Looks like they made a change to fix conflicts with the new/old input system.

    https://github.com/facebook/facebook-sdk-for-unity/commit/6ebf7f3d43a34580e8ef7fc13dfcbc568cb2054e

    There is an open issue still though for the EventSystem:https://github.com/facebook/facebook-sdk-for-unity/issues/442
    Don't have enough time to investigate whether it's still broken or not

    You are only using the old input system right? If so I would just use an older version of the FB SDK
    https://github.com/facebook/facebook-sdk-for-unity/releases
    13.2. shouldn't have the updated code for EventSystem
     
    rpuls likes this.
  8. james580

    james580

    Joined:
    Aug 9, 2017
    Posts:
    19
    I'm having the same issue due to updating my Facebook SDK to v14.1.0 (was previously on v11.0). I wrote a script that will auto search when a new scene is loaded and destroy any EventSystem's that aren't under DontDestroyOnLoad. Hopefully this helps you too if you hadn't found a fix yet.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.EventSystems;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class SingleEventSystem : MonoBehaviour {
    7.         private static SingleEventSystem instance;
    8.      
    9.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    10.         private static void Init() {
    11.             instance = new GameObject().AddComponent<SingleEventSystem>();
    12.             instance.hideFlags = HideFlags.HideAndDontSave;
    13.             DontDestroyOnLoad(instance.gameObject);
    14.         }
    15.  
    16.         private void OnEnable() {
    17.             SceneManager.sceneLoaded += HandleSceneLoaded;
    18.         }
    19.  
    20.         private void OnDisable() {
    21.             SceneManager.sceneLoaded -= HandleSceneLoaded;
    22.         }
    23.  
    24.         private static void HandleSceneLoaded(Scene arg0, LoadSceneMode arg1) {
    25.             var eventSystems = FindObjectsOfType<EventSystem>();
    26.             if (eventSystems.Length == 1)
    27.                 return;
    28.  
    29.             foreach (var eventSystem in eventSystems) {
    30.                 if (!IsDontDestroyOnLoadActivated(eventSystem))
    31.                     Destroy(eventSystem.gameObject);
    32.             }
    33.         }
    34.  
    35.         private static bool IsDontDestroyOnLoadActivated(Component eventSystem) {
    36.             return eventSystem.gameObject.scene.name == "DontDestroyOnLoad";
    37.         }
    38.     }
     
    rpuls likes this.
  9. james580

    james580

    Joined:
    Aug 9, 2017
    Posts:
    19
    rpuls likes this.
  10. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Thank you so much! This is very helpful - highly appreciated
     
    james580 likes this.
  11. MajidKhosravi

    MajidKhosravi

    Joined:
    Jun 21, 2013
    Posts:
    39
    Another approach is to add the following inside the OnInitComplete delegate:

    Code (CSharp):
    1. FB.Init(delegate
    2. {
    3.     var eventSystems = FindObjectsOfType<EventSystem>();
    4.     foreach (var eventSystem in eventSystems)
    5.     {
    6.         var tmp = new GameObject();
    7.         eventSystem.gameObject.transform.parent = tmp.transform;
    8.      }
    9. } , delegate(bool shown) { });
     
    Last edited: Sep 30, 2022
    james580 and rpuls like this.
  12. joshuaFS

    joshuaFS

    Joined:
    Jul 23, 2018
    Posts:
    25
    FWIW, I submitted this as a bug to Facebook, as I couldn't find it submitted there yet and it is still not fixed. When they tried to fix the new vs old input system, they broke this. Always a good idea to submit using their official Bug reporting system when possible. See the bug report here: https://developers.facebook.com/support/bugs/780949209829493/
     
    DungDajHjep and james580 like this.
  13. MajidKhosravi

    MajidKhosravi

    Joined:
    Jun 21, 2013
    Posts:
    39
  14. joshuaFS

    joshuaFS

    Joined:
    Jul 23, 2018
    Posts:
    25
  15. joshuaFS

    joshuaFS

    Joined:
    Jul 23, 2018
    Posts:
    25
    james580 likes this.
  16. HakanYukselGD

    HakanYukselGD

    Joined:
    Sep 4, 2018
    Posts:
    4
    Try closing Unity and opening again like the good old days.
    After Adding Facebook SDK, I got this warning, I checked the code, everything was ok. After 15-20 minutes I needed to close the unity and reopen. And the warning is gone.
    Somehow FindObjectOfType<EventSystem>(); couldn't find the old EventSystem object.