Facebook.init() function still causing null exception - c#

Background:
I am trying to integrate facebook for a unity-android project and I can't seem to make it working, I have looked on the fb page and allot of other place but can't seem to find a what I am doing wrong.
Problem:
When trying FB.Login i get the reference exception: Facebook object is not loaded. Did you call FB.init?
Code for InitializeFB.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Facebook.MiniJSON;
using System;
public class ConncetToFaceBook : MonoBehaviour {
// Connect to facebook
void Awake () {
// Required
DontDestroyOnLoad(gameObject);
// Initialize FB SDK
enabled = false;
FB.Init(onInitComplete, OnHideUnity);
//Display id
Debug.Log (FB.UserId);
//Login to facebook
FB.Login("email,publish_actions", LoginCallback);
}
/* Helper Methods */
private void onInitComplete ()
{
enabled = true; // "enabled" is a property inherited from MonoBehaviour
if (FB.IsLoggedIn)
{
//Some Code
}
}
private void OnHideUnity(bool isGameShown)
{
//some code
}
void LoginCallback(FBResult result)
{
if (FB.IsLoggedIn)
{
OnLoggedIn();
}
}
void OnLoggedIn()
{
Debug.Log("Logged in. ID: " + FB.UserId);
}
}
Code for FB.cs.init()
public static void Init(
InitDelegate onInitComplete,
string appId = "{My app ID}", //I did put my own here. Plus I use " instead of ' because ' give me a error.
bool cookie = true,
bool logging = true,
bool status = true,
bool xfbml = true,
bool frictionlessRequests = true,
HideUnityDelegate onHideUnity = null,
string authResponse = null)

FB.Init() is asynchronous method - it doesn't make the program wait until it is finished. And your FB.Login() is called too soon, you need to call it after FB.Init() is ready - inside the onInitComplete() method.
My setup:
void FBConnect(){
if(!FB.IsInitialized){
Debug.Log("Initializing FB");
FB.Init(FBInitCallback, null,null);
} else {
Debug.Log("No need for FB init");
FBInitCallback();
}
}
private void FBInitCallback(){
Debug.Log("FB init OK");
if(!FB.IsLoggedIn){
FB.Login("email,user_friends", FBLoginCallback);
} else {
//GetHisFBDataNow();
Debug.Log("Everything is known about this guy");
}
}
private void FBLoginCallback(FBResult result){
if (result.Error != null){
Debug.Log("FB Error Response:\n" + result.Error);
} else if (!FB.IsLoggedIn) {
Debug.Log("FB Login cancelled by Player");
} else {
//GetHisFBDataNow();
Debug.Log("Now also everything is known about this guy");
}
}

Hey idk if that will help but can you try and put fb.log in init complete?

Related

Unity - Advertisment called multiple times

I'm having this problem using Unity's Advertisment. Specifically after watching the video and clicking the X button to close the video, I should give the prize to the player (go to the next level). The problem is that the OnUnityAdsDidFinish function calls if (showResult == ShowResult.Finished) multiple times. What am I doing wrong? how do I call the FindObjectOfType () .LoadNextLevel () function once; ? Thank you in advance
public class UnityAdsInterstitial : MonoBehaviour, IUnityAdsListener
{
private string gameID = "******";
//nome scelto nella DashBoard di Unity
private string interstitialID = "interstitial";
private string myPlacementId = "rewardedVideo";
public int randomHighValue = 30;
private bool TestMode = true;
private bool adsClosed = false;
public Button _button;
private void Awake()
{
_button = GetComponent<Button>();
}
void Start()
{
Debug.Log("Ads start");
_button = GameObject.Find("StartAds").GetComponent<Button>();
_button.interactable = Advertisement.IsReady(myPlacementId);
if (_button) _button.onClick.AddListener(ShowRewardedVideo);
Advertisement.Initialize(gameID, TestMode);
Advertisement.AddListener(this);
if (adsClosed)
{
adsClosed = false;
}
}
public void ShowInterstitial()
{
if (Advertisement.IsReady(interstitialID) )
{
Advertisement.Show(interstitialID);
}
}
public void ShowRewardedVideo()
{
if (Advertisement.IsReady(myPlacementId))
{
Debug.Log("Rewarded video is Ready");
Advertisement.Show(myPlacementId);
}
else
{
Debug.Log("Rewarded video is not ready at the moment! Please try again later!");
}
}
public void HideBanner()
{
Advertisement.Banner.Hide();
}
public void OnUnityAdsReady(string placementdID)
{
if (placementdID == interstitialID)
{
Debug.Log("InterstitialIsReady");
}
if (placementdID == myPlacementId)
{
Debug.Log("RewardedIsReady");
_button.interactable = true;
}
}
public void OnUnityAdsDidFinish(string placementdID, ShowResult showResult)
{
if (showResult == ShowResult.Finished)
{
// Reward the user for watching the ad to completion.
if (!adsClosed)
{
adsClosed = true;
FindObjectOfType<LevelLoader>().LoadNextLevel();
}
}
else if (showResult == ShowResult.Skipped)
{
// Do not reward the user for skipping the ad.
}
else if (showResult == ShowResult.Failed)
{
Debug.LogWarning("The ad did not finish due to an error.");
}
}
public void OnUnityAdsDidError(string message)
{
Debug.Log("OnUnityAdsDidError");
}
public void OnUnityAdsDidStart(string message)
{
Debug.Log("OnUnityAdsDidStart");
}
I would start my investigation by checking the placement id (in case there are more placements)
Checking that the callback is for the proper placement id
if (showResult == ShowResult.Finished && placementId == myPlacementId)
{
// Reward the user for watching the ad to completion.
if (!adsClosed)
{
adsClosed = true;
FindObjectOfType<LevelLoader>().LoadNextLevel();
}
}
The second would be that I only have one active instance of UnityAdsInterstitial. You can check this in debug mode by the reference of the object. If more than one instance starts from somewhere else in your code, then you should just limit to one.

Ads are working In Editor but not In Android

I am trying to use ads In my game . They are properly working in Unity but not in Android. Because of I am using unity 2018.4.25f1 personal so it's supporting older version of unity monetization asset. Maybe it's a problem but here is my code of Rewarded Video CSharp file
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;
[RequireComponent(typeof(Button))]
public class RewardedVideo : MonoBehaviour, IUnityAdsListener
{
#if UNITY_IOS
private string gameId = "3853032";
#elif UNITY_ANDROID
private string gameId = "3853033";
#endif
[SerializeField]Button myButton;
[SerializeField]GameObject errorMessage;
public string myPlacementId = "rewardedVideo";
void Start()
{
// Map the ShowRewardedVideo function to the button’s click listener:
if (myButton)
myButton.onClick.AddListener(ShowRewardedVideo);
// Initialize the Ads listener and service:
Advertisement.AddListener(this);
Advertisement.Initialize(gameId, true);
}
public void okError()
{
errorMessage.SetActive(false);
}
// Implement a function for showing a rewarded video ad:
public void ShowRewardedVideo()
{
if(Advertisement.IsReady() == true)
Advertisement.Show(myPlacementId);
else
errorMessage.SetActive(true);
}
// Implement IUnityAdsListener interface methods:
public void OnUnityAdsReady(string placementId)
{
// If the ready Placement is rewarded, activate the button:
if (placementId == myPlacementId)
{
// myButton.interactable = true;
}
}
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
// Define conditional logic for each ad completion status:
if (showResult == ShowResult.Finished)
{
int levels = PlayerPrefs.GetInt("unlockedLevel", 1);
if(levels != 5)
{
PlayerPrefs.SetInt("unlockedLevel", levels+1);
}
}
else if (showResult == ShowResult.Skipped)
{
// Do not reward the user for skipping the ad.
}
else if (showResult == ShowResult.Failed)
{
Debug.LogError("The ad did not finish due to an error");
}
}
public void OnUnityAdsDidError(string message)
{
// Log the error.
}
public void OnUnityAdsDidStart(string placementId)
{
// Optional actions to take when the end-users triggers an ad.
}
}
Downloaded asset from Assets store not from package manager. I saw Unity help, unity forum, stackoverflow but nothing solved my problem
Have you any suggestion?

How to access method from one GameObject to another on google OnAdclosed on Unity?

I have a GameScreenManger that will show or hide a panel based on the game status. I have a AdManager gameObject that holds a script that handles ads. I am able to show the ad, but on onAdclosed if i tried to make a reference of GameScreenManager that holds a script in Admanager Script and call a function when onAdclosed event listeners function, the call is triggering, but the actions are not working. Could some one help me in this?
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private string appId = "";
private InterstitialAd InterstitialAd;
private string InterstitialAdId = "interstitial_Ad_Id";
private RewardedAd RewardedVideoAd;
private string RewardedVideoAdId = "rewarded_video_ad_Id ";
public GameObject RewardPanel;
public GameScreenManager gameManager;
public bool isRewardedVideo;
private bool RewardedVideoLoaded = false;
public void Awake()
{
if(instance == null)
{
instance = this;
} else
{
Destroy(this);
}
MobileAds.Initialize(initStatus => { });
}
private void Start()
{
RequestInterstitial();
RewardedVideoAd = new RewardedAd(RewardedVideoAdId);
RequestRewardedVideo();
// Called when an ad request has successfully loaded.
this.RewardedVideoAd.OnAdLoaded += HandleRewardedAdLoaded;
// Called when an ad request failed to load.
this.RewardedVideoAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;
// Called when an ad is shown.
this.RewardedVideoAd.OnAdOpening += HandleRewardedAdOpening;
// Called when an ad request failed to show.
this.RewardedVideoAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
// Called when the user should be rewarded for interacting with the ad.
this.RewardedVideoAd.OnUserEarnedReward += HandleUserEarnedReward;
// Called when the ad is closed.
this.RewardedVideoAd.OnAdClosed += HandleRewardedAdClosed;
}
private void Update()
{
if (RewardedVideoLoaded == false)
{
RequestRewardedVideo();
}
}
private void RequestInterstitial()
{
string adUnitId = InterstitialAdId;
// Initialize an InterstitialAd.
this.InterstitialAd = new InterstitialAd(adUnitId);
// Create an empty ad request.
AdRequest request = new AdRequest.Builder().Build();
// Load the interstitial with the request.
this.InterstitialAd.LoadAd(request);
}
public void ShowInterstitial()
{
if (this.InterstitialAd.IsLoaded())
{
this.InterstitialAd.Show();
}
}
public void RequestRewardedVideo()
{
// Create an empty ad request.
AdRequest request = new AdRequest.Builder().Build();
// Load the interstitial with the request.
this.RewardedVideoAd.LoadAd(request);
if (this.RewardedVideoAd.IsLoaded())
{
isRewardedVideo = true;
RewardedVideoLoaded = true;
} else
{
isRewardedVideo = false;
RewardedVideoLoaded = false;
}
}
public void ShowRewardedVideo()
{
if (this.RewardedVideoAd.IsLoaded())
{
this.RewardedVideoAd.Show();
}
}
public void HandleRewardedAdLoaded(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardedAdLoaded event received");
}
public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args)
{
MonoBehaviour.print(
"HandleRewardedAdFailedToLoad event received with message: "
+ args.Message);
}
public void HandleRewardedAdOpening(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardedAdOpening event received");
}
public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
{
MonoBehaviour.print(
"HandleRewardedAdFailedToShow event received with message: "
+ args.Message);
}
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardedAdClosed event received");
Debug.Log("{lo} OnClosed called sender = " + sender);
RequestRewardedVideo();
gameManager.CheckForLives(); //This is not working.
this.RewardPanel.SetActive(true);
}
public void HandleUserEarnedReward(object sender, Reward args)
{
Debug.Log("{lo} Earned a Reward HandleUserEarnedReward called!");
string type = args.Type;
double amount = args.Amount;
this.RewardPanel.SetActive(true);
}
}
GameScreen Script
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameScreenManager : MonoBehaviour
{
public GameObject PauseScreen;
public GameObject OutOfLifeScreen;
public GameObject PauseButton;
public GameObject Scoretext;
public GameObject Livesbutton;
public Text MusicText;
public void LoadPause()
{
PauseScreen.SetActive(true);
bool audioPlaying = FindObjectOfType<AudioManager>().audioPlaying;
MusicText.text = audioPlaying ? "MUSIC ON" : "MUSIC OFF";
Time.timeScale = 0f;
}
public void ShowResume()
{
PauseScreen.SetActive(false);
Time.timeScale = 1f;
}
public void ShowMainMenu()
{
Time.timeScale = 1f;
SceneManager.LoadScene("Menu");
}
public void ShowOutOfLives()
{
OutOfLifeScreen.SetActive(true);
PauseButton.SetActive(false);
Time.timeScale = 0f;
}
public void CloseOutOfLives()
{
Debug.Log(" {lo} Entered CloseOutOfLives");
OutOfLifeScreen.SetActive(false);
PauseButton.SetActive(true);
Time.timeScale = 1f;
}
public void TogggleSound()
{
FindObjectOfType<AudioManager>().ToggleMute();
bool audioPlaying = FindObjectOfType<AudioManager>().audioPlaying;
MusicText.text = audioPlaying ? "MUSIC ON" : "MUSIC OFF";
PlayerPrefs.SetInt("audioNeeded", audioPlaying ? 1 : 0);
}
public void Quit()
{
Application.Quit();
}
}
Because the callbacks are coming from a non-main thread, and unity is a single threaded environment, so some unity APIs are inaccessible from non-main threads, for example you can't use GameObject.SetActive or many more component functions except from the main thread, so what you need to do is dispatch the callback to the main thread first, then all statements in your function will execute.
Here's how.
1) A simple dispatcher that executes methods on unity's main thread.
create an empty game object in your scene, and attach this to it.
using System;
using System.Collections.Generic;
/// <summary>
/// Helps dispatch task results to the main thread to be able to operate on unity's API like SetActive, enabled etc...
/// </summary>
public class MainThreadDispatcher : MonoBehaviour
{
Queue<Action> jobs = new Queue<Action>();
static MainThreadDispatcher Instance = null;
private void Awake()
{
Instance = this;
}
private void Update()
{
while (jobs.Count > 0)
{
var next = jobs.Dequeue();
if(next != null)
{
next.Invoke();
}
}
}
/// <summary>
/// Dispatches a function to be executed on unity's main thread to be able to use unity's API.
/// </summary>
/// <param name="newJob"></param>
public static void Dispatch(Action newJob)
{
if (newJob == null)
return;
Instance.jobs.Enqueue(newJob);
}
}
2) Edit your on ad closed callback to dispatch to the main thread.
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
// simply give unity control back.
// you can pick and choose to execute what on main thread,
// but I'm just gonna dispatch the whole block.
MainThreadDispatcher.Dispatch(() =>
{
MonoBehaviour.print("HandleRewardedAdClosed event received");
Debug.Log("{lo} OnClosed called sender = " + sender);
RequestRewardedVideo();
gameManager.CheckForLives();
this.RewardPanel.SetActive(true);
});
}
It seems like you don't have a reference to your object in the second script:
Ad Script
public GameScreenManager gsmanagerRef; //drag and drop on the editor or find it on initialization
then you should be able to call
gsmanagerRef.ShowResume(); //or any other function
Hope this helps!

Unity Facebook login not works on Facebook App in the Android device

So i implemented Facebook SDK in my project, here the problem is FBlogin not works when i have facebook app in my android device. Please my and my team stuck in this stuff. For more details please replay to this post.
Here is the Code of my Facebook. It is working great when i uninstall facebook app in my device.
With facebook app in my android device : When open my game, facebook window is appear like do you want to continue insted of Login ask, when i click continue its not fetching my details like "Name and Profile Pic"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Facebook.Unity;
using Facebook.MiniJSON;
using UnityEngine.UI;
using System.IO;
using System;
public class Login : MonoBehaviour
{
public string fbname;
public string get_data;
public InputField login_name;
public Image profilePic;
public Text fbNameText,FriendsText;//BABJI
public GameObject loginPanel,mainPanel;
public bool loggedIn;
void Awake ()
{
if (!FB.IsInitialized)
{
FB.Init(() =>
{
if (FB.IsInitialized)
FB.ActivateApp();
else
Debug.LogError("Couldn't initialize");
},
isGameShown =>
{
if (!isGameShown)
Time.timeScale = 0;
else
Time.timeScale = 1;
});
}
else
FB.ActivateApp();
}
void Start()
{
if (GameSaver.instance.isFBLogin) {
loginPanel.SetActive (false);
login_name.gameObject.SetActive (true);
mainPanel.SetActive (true);
// StartCoroutine (DelayLogIn ());
} else {
loginPanel.SetActive (true);
}
}
// IEnumerator DelayLogIn()
// {
// yield return new WaitForSeconds (0.1f);
//
// }
private void InitCallback ()
{
if (FB.IsInitialized) {
// Signal an app activation App Event
FB.ActivateApp();
// Continue with Facebook SDK
// ...
} else {
Debug.Log("Failed to Initialize the Facebook SDK");
}
}
private void OnHideUnity (bool isGameShown)
{
if (!isGameShown) {
// Pause the game - we will need to hide
Time.timeScale = 0;
} else {
// Resume the game - we're getting focus again
Time.timeScale = 1;
}
}
public void LoginCalled()
{
if (!FB.IsLoggedIn)
{
var perms = new List<string> (){ "public_profile", "email" };
FB.LogInWithReadPermissions (perms, AuthCallback);
}
else
{
//
}
// you are already logged in, do something
FB.API("me?fields=name", HttpMethod.GET, GetFacebookData);
FB.API("me/picture?type=square&height=128&width=128", HttpMethod.GET, GetProfilePicture);
login_name.gameObject.SetActive (true);
mainPanel.SetActive (true);
loginPanel.SetActive (false);
GameSaver.instance.isFBLogin=true;
GameSaver.instance.SaveGameData ();
}
private void AuthCallback (ILoginResult result)
{
if (FB.IsLoggedIn)
{
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
// Print current access token's User ID
Debug.Log(aToken.UserId);
// Print current access token's granted permissions
foreach (string perm in aToken.Permissions)
{
Debug.Log(perm);
}
FB.API("me?fields=name", Facebook.Unity.HttpMethod.GET, GetFacebookData);
//FB.API("/me/picture?redirect=false", HttpMethod.GET, GetProfilePicture);
//BABJI
FB.API("me/picture?type=square&height=128&width=128", HttpMethod.GET, GetProfilePicture);
login_name.gameObject.SetActive (true);
mainPanel.SetActive (true);
loginPanel.SetActive (false);
GameSaver.instance.isFBLogin=true;
GameSaver.instance.SaveGameData ();
//BABJI
loggedIn = FB.IsLoggedIn;
}
else
{
Debug.Log("User cancelled login");
}
}
void GetFacebookData(IResult result)
{
fbname = result.ResultDictionary["name"].ToString ();
login_name.text = fbname ;
login_name.gameObject.SetActive (true);
fbNameText.text = fbname;
Debug.Log("fbName: " + fbname);
}
private void GetProfilePicture(IGraphResult result)
{
if (result.Error == null && result.Texture != null)
{
profilePic.sprite = Sprite.Create (result.Texture, new Rect (0, 0, 128, 128), new Vector2 ());
}
}
}
depending on what we have discussed above
try this code :
public void Awake()
{
// Init Facebook SDK
if (!FB.IsInitialized)
{
// Initialize the Facebook SDK Configuration
FB.Init(InitCallback, OnHideUnity);
}
else
{
// Already initialized, signal an app activation App Event
FB.ActivateApp();
}
}
private void InitCallback() {
if (FB.IsInitialized)
{
// Signal an app activation App Event
FB.ActivateApp();
}
else
{
Debug.Log("Failed to Initialize the Facebook SDK");
}
}
private void AuthCallback(ILoginResult result)
{
if (FB.IsLoggedIn)
{
// Here is the region where u r loggged in from facebook acccount
// Just put your Logic Here
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
}
else
{
Debug.Log("Facebook User cancelled login");
}
}
and here is what you need to call when u press a button,
public void LoginWithFaceBook()
{
var perms = new List<string>() { "public_profile", "email" };
FB.LogInWithReadPermissions(perms, AuthCallback);
}
also use this when u logout from your application
public void FacebookLogout()
{
if (FB.IsLoggedIn)
{
FB.LogOut();
}
}

NullReferenceException on Public Method Unity3D

void Update () {
if (isSaveNeeded){
AutoSaveData();
isSaveNeeded = false;
}
string status;
if (Social.localUser.authenticated) {
status = "Authenticated ";
if (isLoaded == false){
LoadAutoSave();
isLoaded = true;
}
}
else {
status = "Not Authenticated";
}
statusToPass = status + " " + mMsg;
}
public void OnSignIn() {
if (Social.localUser.authenticated) {
PlayGamesPlatform.Instance.SignOut();
}
else {
PlayGamesPlatform.Instance.Authenticate(mAuthCallback, false);
}
}
public void LoadData() {
((PlayGamesPlatform)Social.Active).SavedGame.ShowSelectSavedGameUI("Select Saved Game to Load",
10,
false,
true,
SaveGameSelectedForRead);
}
public void SaveData() {
((PlayGamesPlatform)Social.Active).SavedGame.ShowSelectSavedGameUI("Save Game Progress",
10,
true,
false,
SaveGameSelectedForWrite);
}
public void AutoSaveData() {
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithAutomaticConflictResolution(autoSaveFileName,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime,
SavedGameOpenedForWrite);
}
public void LoadAutoSave() {
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithAutomaticConflictResolution(autoSaveFileName,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime,
SavedGameOpenedForRead);
}
I am trying to call a public method in the same script called AutoSaveData()
and it is giving me Null reference exception.
I have also added DontDestroyOnLoad to this script so that the game object persists between scenes.
I have been looking into it for some hours now and couldn't figure out the cause for it. It might be a simple mistake on my part but as I am new to coding, probably I am not able to figure it out.
Thanks
I fixed it by adding condition to my AutoSaveData() function.
Now it is like
if(Social.localuser.authenticated){ AutoSaveData(){
} }
Thanks

Categories