如何整合PlayFab与Photon好友信息?基于PUN 2的技术问询
整合PlayFab与Photon PUN 2好友系统:实现在线状态与房间查看
要解决PlayFab好友列表和Photon在线状态/房间信息的整合问题,核心是建立PlayFab ID与Photon User ID的映射关系,然后通过Photon的API获取好友的实时状态。下面是一步步的实现方案:
1. 先完成身份映射:存储Photon ID到PlayFab
每个玩家登录Photon后,需要把自己的Photon User ID保存到PlayFab的自定义玩家数据中。这样当你获取PlayFab好友列表时,才能找到每个好友对应的Photon身份。
添加这段代码,在玩家成功连接Photon后调用:
private void SavePhotonIdToPlayFab() { if (!PhotonNetwork.IsConnected) return; var updateRequest = new PlayFab.ClientModels.UpdateUserDataRequest { Data = new Dictionary<string, string> { { "PhotonUserId", PhotonNetwork.LocalPlayer.UserId } } }; PlayFabClientAPI.UpdateUserData(updateRequest, (result) => Debug.Log("Photon ID已同步到PlayFab"), (error) => Debug.LogError($"同步失败:{error.GenerateErrorReport()}")); }
2. 重构PlayFab好友列表获取逻辑:关联Photon ID
原来的DisplayPlayfabFriends只处理了PlayFab的好友信息,现在需要扩展它,为每个PlayFab好友获取对应的Photon ID,再通过Photon查询在线状态。
修改后的代码:
private List<PlayFab.ClientModels.FriendInfo> myfriends; private List<Photon.Realtime.FriendInfo> _photonFriendCache = new List<Photon.Realtime.FriendInfo>(); private Dictionary<string, string> _playFabToPhotonIdMap = new Dictionary<string, string>(); // 缓存映射关系 private void DisplayPlayfabFriends(List<PlayFab.ClientModels.FriendInfo> friendCache) { // 清空现有UI避免重复 foreach (Transform child in container) Destroy(child.gameObject); myfriends = friendCache; _photonFriendCache.Clear(); _playFabToPhotonIdMap.Clear(); // 订阅Photon好友列表更新事件(仅订阅一次) if (!PhotonNetwork.NetworkingClient.EventReceived.Contains(OnPhotonFriendListUpdated)) { PhotonNetwork.NetworkingClient.EventReceived += OnPhotonFriendListUpdated; } // 收集所有好友的Photon ID,批量查询状态 List<string> photonFriendIds = new List<string>(); foreach (var playFabFriend in friendCache) { FetchFriendPhotonId(playFabFriend, photonFriendIds); } } private void FetchFriendPhotonId(PlayFab.ClientModels.FriendInfo playFabFriend, List<string> photonIdsList) { var dataRequest = new PlayFab.ClientModels.GetUserDataRequest { PlayFabId = playFabFriend.FriendPlayFabId, Keys = new List<string> { "PhotonUserId" } }; PlayFabClientAPI.GetUserData(dataRequest, (result) => { if (result.Data.TryGetValue("PhotonUserId", out var photonIdData)) { string photonUserId = photonIdData.Value; _playFabToPhotonIdMap.Add(playFabFriend.FriendPlayFabId, photonUserId); photonIdsList.Add(photonUserId); // 先检查缓存中是否已有该好友的状态 var cachedStatus = _photonFriendCache.FirstOrDefault(f => f.UserId == photonUserId); if (cachedStatus != null) { CreateIntegratedFriendUI(playFabFriend, cachedStatus); } } else { // 好友未绑定Photon ID,显示为离线 CreateIntegratedFriendUI(playFabFriend, null); } // 当所有Photon ID收集完成后,批量查询状态 if (photonIdsList.Count == myfriends.Count) { if (photonIdsList.Any()) { PhotonNetwork.FindFriends(photonIdsList.ToArray()); } } }, (error) => Debug.LogError($"获取好友Photon ID失败:{error.GenerateErrorReport()}")); }
3. 处理Photon好友状态回调,更新UI
当Photon返回好友在线状态时,我们更新缓存并刷新UI:
private void OnPhotonFriendListUpdated(Photon.EventData eventData) { if (eventData.Code != EventCode.FriendListUpdate) return; _photonFriendCache = PhotonNetwork.Friends.ToList(); // 重新渲染所有好友UI,更新状态 foreach (var playFabFriend in myfriends) { _playFabToPhotonIdMap.TryGetValue(playFabFriend.FriendPlayFabId, out string photonId); var photonFriend = _photonFriendCache.FirstOrDefault(f => f.UserId == photonId); CreateIntegratedFriendUI(playFabFriend, photonFriend); } }
4. 整合UI显示:结合PlayFab昵称与Photon状态
创建一个统一的UI初始化方法,把PlayFab的好友昵称和Photon的在线状态、房间信息结合起来:
private void CreateIntegratedFriendUI(PlayFab.ClientModels.FriendInfo playFabFriend, Photon.Realtime.FriendInfo photonFriend) { UIFriend listing = Instantiate(uiPrefab, container); if (listing == null) return; // 显示PlayFab的自定义昵称(比Photon的UserId更友好) listing.friendNameText.text = playFabFriend.TitleDisplayName; // 设置在线状态颜色 bool isOnline = photonFriend != null && photonFriend.IsOnline; listing.onlineImage.color = isOnline ? onlineColor : offlineColor; // 显示房间信息或在线状态 if (isOnline) { listing.roomNameText.text = string.IsNullOrEmpty(photonFriend.Room) ? "在线(未进入房间)" : $"在房间:{photonFriend.Room}"; } else { listing.roomNameText.text = "离线"; } // 存储好友信息,方便后续操作(比如邀请好友) listing.playFabInfo = playFabFriend; listing.photonInfo = photonFriend; }
同时,更新你的UIFriend脚本,添加对应的字段:
public class UIFriend : MonoBehaviour { public Text friendNameText; public Text roomNameText; public Image onlineImage; public Color onlineColor; public Color offlineColor; // 新增字段存储整合后的好友信息 public PlayFab.ClientModels.FriendInfo playFabInfo; public Photon.Realtime.FriendInfo photonInfo; }
关键注意事项
- 确保玩家登录顺序:玩家需要先登录PlayFab,再登录Photon,然后调用
SavePhotonIdToPlayFab完成映射。 - 缓存优化:用
_playFabToPhotonIdMap缓存PlayFab与Photon的ID映射,避免重复调用PlayFab API。 - 状态刷新:可以添加一个定时刷新按钮,重新调用
DisplayPlayfabFriends来更新好友在线状态。 - 异常处理:处理好友未绑定Photon ID的情况(比如好友从未登录过Photon),此时显示为离线即可。
内容的提问来源于stack exchange,提问作者guy shalev
相关产品推荐
相关产品推荐

