You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何整合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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:52:45