Troubles with Photon Friends - Unity, Facebook sdk

Options
Hello. I am developing a 2d multiplayer game. I am using facebook or my custom authentication. Everything is working with that. I have implemented my own friend system using playerprefs (adding, refreshing list ect..) however when I try to find friends, it always returns that they are not online, even if they are.

This is the flow for my game:

Menu > Login via facebook (set photon userid/token to the facebook information) > Load lobby level > Load friends from player prefs > FindFriends > Display information.

However when I display the information, it always says that they are offline. Am I missing something? Or do I need to do something specific because of the facebook integration? I have been stuck on this for sometime now so any help is appreciated.

After the friends are loaded from the playerpref string, this is called, and I have the friend list callback in another script that should print out some debug logs.

public void InitializeFriends()
{
if (_friendList != null)
{
string[] friends = _friendList.ToArray ();

PhotonNetwork.FindFriends (friends);
Debug.Log ("Tryna find friends");
}
}


void OnUpdatedFriendList()
{
Debug.Log ("OnUpdatedFriendList");
if (PhotonNetwork.Friends != null)
{
foreach (FriendInfo friend in PhotonNetwork.Friends)
{
Debug.Log ("Friend name: " + friend.Name + " Online: " + friend.IsOnline);
}
}
}

What im wondering is, why is it saying that the friends are offline even when they're online?
All of this is called once... Is FindFriends supposed to be called more then once? How can i properly setup/design this so it works efficiently.

Comments

  • Dev
    Dev
    edited May 2016
    Options
    This is my authentication code that is used on initial login - I figured this could be of use.

    void OnLoggedIn(AccessToken token)
    {

    // Set our session data on the photon server
    PhotonNetwork.AuthValues = new AuthenticationValues();
    PhotonNetwork.AuthValues.AuthType = CustomAuthenticationType.Facebook;
    PhotonNetwork.AuthValues.UserId = token.UserId;
    PhotonNetwork.AuthValues.Token = token.TokenString;
    PhotonNetwork.AuthValues.AddAuthParameter("username", token.UserId);
    PhotonNetwork.AuthValues.AddAuthParameter("token", token.TokenString);

    // Set the session data
    Session.SetSessionData (token);

    // Connect to photon server
    Connect.ConnectToServer ();

    }

    *The access token is simply the current access token returned from facebook if successfully authenticated.
  • Dev
    Options
    Any help
  • Dev
    Dev
    edited May 2016
    Options
    So I have updated my code so I will explain a bit of my process. I have a button (for test purposes) that just 'refreshes' the photon friend list. The UpdateFriendsOnServer function is called automatically as soon as the level is loaded and the friendmanager is initialized. I use a ui button which I use to call this method as well. I set the photonnetwork.playername before i connect as well which I read was also necessary. I am using custom auth via facebook so don't think that has anything to do with it. And Still no idea what is going on... Even when I refresh it says the friend isn't online so not sure what's happening.

    IEnumerator UpdateFriendsOnServer()
    {
    if (_friendList != null)
    {
    string[] friends = _friendList.ToArray ();

    PhotonNetwork.FindFriends (friends);

    yield return new WaitForSeconds(0.5f);

    RefreshFriendList();
    }

    }

    void RefreshFriendList()
    {
    _friendListInformationText.text = "";

    if (PhotonNetwork.Friends != null)
    {
    for (int i = 0; i < PhotonNetwork.Friends.Count; i++)
    {
    _friendListInformationText.text += PhotonNetwork.Friends[i].Name + " : " + PhotonNetwork.Friends[i].IsOnline + "\n";
    }
    }
    else
    {
    Debug.Log ("Frands are null");
    }
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited May 2016
    Options
    Hi @Dev,

    I apologize about the delay.

    I just want to make sure that your friends list contains Photon UserIDs used in Custom Authentication or Facebook IDs? If they are the same thing then you can skip my question.

    This is probably unrelated to your question but you can simplify client authentication code:
    PhotonNetwork.AuthValues = new AuthenticationValues();
    PhotonNetwork.AuthValues.AuthType = CustomAuthenticationType.Facebook;
    PhotonNetwork.AuthValues.AddAuthParameter("token", token.TokenString);
    Also I want to make sure Custom Authentication is setup properly, did you add AppID and Secret key/values of your facebook app to the Custom Authentication configuration in your Photon application in the dashboard? What URL do you use? Do you enable anonymous clients? Do you reject clients when authentication provider is unavailable?
  • Dev
    Dev
    edited May 2016
    Options
    Hey no worries - just appreciate that someone took the time to help! &

    1) How am i able to tell if it contains UserID's if the only information I can get is the friend name and offline state? But yes once i am authenticated via facebook, I use the corresponding callback to set all my session data (including facebook userid/token to photons)
    2) I added my appId/ secret key in the photon dashboard
    3) Not sure what you mean by url? Im using facebook sdk for login authentication so I don't actually need to connect to an external web service.
    4) Not allowing anonymous clients to connect, independently of configured providers.
    5) Reject all clients if not available.
  • Dev
    Options
    bump
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hey @Dev,

    I apologize about the delay.

    Please try this.
    
    void OnEnable(){
    	StartCoroutine("UpdateFriendsOnServer");
    }
    
    void OnDisable(){
    	StopCoroutine("UpdateFriendsOnServer");
    }
    
    
    IEnumerator UpdateFriendsOnServer()
    {
    	while (true) {
    		if (_friendList != null) 
    		{
    			string[] friends = _friendList.ToArray ();
    			PhotonNetwork.FindFriends (friends);
    		}
    		yield return new WaitForSeconds(friendsCheckPeriod);
    	}
    }
    
    override void OnUpdatedFriendList () {
    	Debug.Log ("OnUpdatedFriendList");
    	if (PhotonNetwork.Friends != null) 
    	{
    		foreach(FriendInfo friend in PhotonNetwork.Friends) 
    		{
    			Debug.Log ("Friend name: " + friend.Name + " Online: " + friend.IsOnline);
    		}
    	}
    }
  • Dev
    Options
    Hmm okay I will try.
  • Dev
    Dev
    edited May 2016
    Options
    Also i'm not able to override it - I get an error. Should it be? It gets called regardless of if i have that specifier there.
  • Dev
    Options
    So with your provided code it's still saying that they are offline. Any way you could provide assistance via teamviewer or any similar service?
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Sorry about the extra override.

    Please make sure the array of UserIDs passed to FindFriends matches the UserIDs of the connected Photon Players.

    Since you want to use facebook ID as UserID. You should set each client's UserID to facebook ID and use array of facebook IDs of facebook friends in FindFriends.

    Please also update Custom Authentication code to set UserID to facebook ID:
    PhotonNetwork.AuthValues = new AuthenticationValues();
    PhotonNetwork.AuthValues.AuthType = CustomAuthenticationType.Facebook;
    PhotonNetwork.AuthValues.UserId = token.UserId; // this is important
    PhotonNetwork.AuthValues.AddAuthParameter("token", token.TokenString);
    Please log UserIDs and make sure to pass array of facebook IDs. Do not confuse UserId with PlayerName/Nickname.

    UserIDs in Photon is now being separated from PlayerName/UserName/Nickname. UserId was introduced in PUN in v1.67.

    PhotonPlayer.userId != PhotonPlayer.name

    Read more about the importance of UserID in "Playing with friends".
  • Dev
    Dev
    edited May 2016
    Options
    Woot fixed it. Yeah the reason is because I was storing literal friend names and then putting them into FindFriends(). I think the documentation is misleading there. I think a reimplementation of the userid and photonplayername could be beneficial. It seems like theres a lot of ambiguity between the two which could confuse a lot of people.

    Oh one quick thing, im not sure how to do is correlate the 2. Basically the system i wrote you could type in a name (of the player you want to add) and it would display the name and that they were offline (findfriends saying offline because of photonname in findfriends and not userids), however I simply fixed it by typing in the user id of the player (me in this case). So what im asking is how can I correlate the 2 so if i type in a name it will automatically obtain or have a reference to the userid. Is it possible? I've seen some photon friend list assets out there so i imagine there must be some sort of work around.

    Anyways, appreciate you taking the time to help me.

    Thanks,
    Dev.
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    @Dev, please let us know which documentation you found confusing or misleading. Maybe it's just outdated.

    What you are asking is possible and there are different ways to do it and to optimize it.

    Ideally, you can use facebook names (short or long form, first/last or full name) as Photon Nicknames. Get facebook friends' facebook IDs and facebook names (which should match Photon UserIDs and Nicknames) and save them. Then when you look for a Nickname, you can get UserID.
  • Dev
    Options
    Could you please provide some sort of example as how to match both them.. Like you mentioned above PhotonNetwork.UserId != PhotonNetwork.playerName... So with that i'm fnding it hard to depict how I will be able to fnd players via their name. For example, if I click on add friend and type in the name of a user, how will it know that players userId (especially if they're offline)?
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited May 2016
    Options
    The idea is to use facebook SDK to do that. Since facebook ID = Photon UserID and facebook name = Photon Nickname. However, the search may be limited to the list of facebook friends. I'm not sure if it's possible, in general, to look up facebook ID using facebook SDK given the facebook name.

    You connect with facebook, get list of friends. List should contain facebook ID and facebook name.
    Having facebook name you can loop through the list compare facebook names and when you find a match get facebook ID.

    There is no guarantee that the facebook friend is playing your game. So he/she may appear offline and you can't tell.

    The other, more complex, solution is to use a web server to store list of users of your game.
  • Dev
    Options
    Ohhhh I see. Ok that explains it a bit more. Thanks. I think what is misleading is how the userId is used to communicate. A simple workaround I did (i imagine it's insecure) was simply storing a reference to the original facebook user id then setting the photon user id to the nickname or username.
  • Hey, some nice discussion above. I've the same problem of getting friends list. But i'm confused that how will i get the friend list from playerprefs. how do I declare/initialize the _friendList List? Does Photon gets the friendlist of player from facebook at runtime or you have to hard code it?
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @SaadSalman,

    Read my answer here.
  • hey, OnUpdtaedFriendsList is removed and OnFriendListUpdate is the new one I quess.... but this isn't working too...I dont know why its not being called

    here is my code:
    public override void OnEnable()
    {
    	StartCoroutine(UpdateFriendsOnServer());
    }
    
    public override void OnDisable()
    {
    	StopCoroutine(UpdateFriendsOnServer());
    }
    
    private IEnumerator UpdateFriendsOnServer()
    {
    	if (friendList != null)
    	{
    		foreach (var obj in friendList)
    		{
    			frnds.Append(obj.ToString());
    		}
    
    		PhotonNetwork.FindFriends(frnds);
    	}
    
    	yield return new WaitForSeconds(10);
    }
    	
    public override void OnFriendListUpdate(List<FriendInfo> frndsList)
    {
    	text.text = "heheh";
    	if (frndsList.Count > 0)
    	{
    		text.text = "updtaae";
    		foreach (FriendInfo info in frndsList)
    		{
    			if (info.IsOnline)
    			{
    				GameObject friendGO = Instantiate(friendPrefab);
    				friendGO.transform.SetParent(fbFriendConnected.transform.GetChild(2).GetChild(2));
    				friendGO.transform.localPosition = new Vector3(0, yValue1, 0);
    				friendGO.transform.localScale = Vector3.one;
    				friendGO.transform.GetChild(0).GetComponent<Text>().text = info.UserId;
    				yValue1 -= 120;
    			}
    			else
    			{
    				GameObject friendGO = Instantiate(friendPrefab);
    				friendGO.transform.SetParent(fbFriendConnected.transform.GetChild(2).GetChild(4));
    				friendGO.transform.localPosition = new Vector3(0, yValue2, 0);
    				friendGO.transform.localScale = Vector3.one;
    				friendGO.transform.GetChild(0).GetComponent<Text>().text = info.UserId;
    				yValue2 -= 120;
    			}
    		}
    	}
    }
    

    text.text is just used to check if OnFriendListUpdate is being called or not...
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited December 2020
    Options
    Hi @anmol07goyal,
    if you extend MonoBehaviourPunCallbacks make sure to call the base class methods if you override OnEnable() and OnDisable()
    source

    side notes:
    why do you need a coroutine for this? the official example on our documentation website is simpler.
    why do you have "friendsList" and "frnds"?