【问题标题】:Unity+PlayFab c# sequential executionunity+PlayFab c# 顺序执行
【发布时间】:2020-04-13 19:16:08
【问题描述】:

请告知 C# 语法,我正在对 PlayFab 进行 Rest API 调用以获取玩家配置文件,然后将玩家显示名称分配给本地公共变量,但在执行过程中我发现它们不是连续的函数序列一点也不。我不明白为什么,就像在 python 或 java 中一样,所有函数都是顺序的,它们将在另一个函数完成后执行。

按照逻辑,它应该使用 OnLoginWithGoogleAccountPlayFab 执行启动函数,该函数将调用 GetPlayerProfile 获取玩家名称并分配到公共​​字符串 PlayerDisplayName ,然后调用 ChangeSceneOnNewPlayer 它将检查名称是否为空。

但它以这种方式执行enter image description here

public PlayerDisplayName;
void Start(){
        OnLoginWithGoogleAccountPlayFab();
}
public void OnLoginWithGoogleAccountPlayFab() {
        PlayFabClientAPI.LoginWithGoogleAccount(new LoginWithGoogleAccountRequest()
        {
            TitleId = PlayFabSettings.TitleId,
            ServerAuthCode = AuthCode,
            CreateAccount = true
        }, (result) =>
        {
            PlayFabId = result.PlayFabId;
            SessionTicket = result.SessionTicket;
            Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- --------------------- GET PROFILE 1");
            GetPlayerProfile();
            Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- ---------------------NAME 1 ");
            ChangeSceneOnNewPlayer();
        }, OnPlayFabError);
    }

public void GetPlayerProfile() {
        PlayFabClientAPI.GetPlayerProfile(new GetPlayerProfileRequest()
        {
            PlayFabId = PlayFabId,
            ProfileConstraints = new PlayerProfileViewConstraints()
            {
                ShowDisplayName = true,
            }
        }, (result) =>
        {
            Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- ---------------------PROFILE 2");
            Debug.Log("The player's DisplayName profile data is: " + result.PlayerProfile.DisplayName);
            PlayerDisplayName = result.PlayerProfile.DisplayName;
            Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- ---------------------PROFILE 3");
        }, OnPlayFabError);
    }

public void ChangeSceneOnNewPlayer() {
        Debug.Log("Player Info");
        Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- ---------------------NAME 2 ");
        if (PlayerDisplayName == null) {
            Debug.Log("Player Info is NULL " + PlayerDisplayName);
            Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- ---------------------NAME 3 ");
            SceneManager.LoadSceneAsync("New_Player", LoadSceneMode.Single);
        } else {
            Debug.Log("Player Info NOT null " + PlayerDisplayName);
            Debug.LogWarning("waaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrr- ---------------------NAME 3 ");
            SceneManager.LoadSceneAsync("City", LoadSceneMode.Single);
        }
    }

【问题讨论】:

  • 请移除 Java 标签。这个问题与Java无关。

标签: java c# unity3d c#-4.0


【解决方案1】:

您的方法正在按顺序执行,但您返回的结果是异步返回的。这会在您的代码中引入竞争条件,这也是您在收到玩家资料之前看到正在执行 ChangeSceneOnNewPlayer 方法的原因。

让我们分解以下几行中发生的事情(为了清楚起见,删除了调试):

// Both these lines execute synchronously.
PlayFabId = result.PlayFabId;
SessionTicket = result.SessionTicket;

// Here you're invoking a synchronous method, but inside the method
// an asynchronous call is made to PlayFab, and the result will not be immediately
// returned.
GetPlayerProfile();

// Then you immediately call this method, but you haven't waited for the result from 
// PlayFab before you make this call.
ChangeSceneOnNewPlayer();

你想要的是更像这样的东西:

public PlayerDisplayName;

void Start()
{
    OnLoginWithGoogleAccountPlayFab();
}

public void OnLoginWithGoogleAccountPlayFab()
{
    PlayFabClientAPI.LoginWithGoogleAccount(new LoginWithGoogleAccountRequest()
    {
        TitleId = PlayFabSettings.TitleId,
        ServerAuthCode = AuthCode,
        CreateAccount = true
    }, (result) =>
    {
        PlayFabId = result.PlayFabId;
        SessionTicket = result.SessionTicket;

        // Get the profile, and specify a callback for when the result is returned
        // from PlayFab.
        GetPlayerProfile(OnGetPlayerProfile);
    }, OnPlayFabError);
}

public void GetPlayerProfile(Action<PlayerDisplayName> onGetPlayerDisplayName)
{
    PlayFabClientAPI.GetPlayerProfile(new GetPlayerProfileRequest()
    {
        PlayFabId = PlayFabId,
        ProfileConstraints = new PlayerProfileViewConstraints()
        {
            ShowDisplayName = true,
        }
    }, onGetPlayerDisplayName, OnPlayFabError);
}

// This method is used as a callback to your GetPlayerProfile function and is used
// to process the information.
public void OnGetPlayerProfile(PlayerDisplayName playerDisplayName)
{
    PlayerDisplayName = playerDisplayName;
    if (PlayerDisplayName == null)
    {
        SceneManager.LoadSceneAsync("New_Player", LoadSceneMode.Single);
    }
    else
    {
        SceneManager.LoadSceneAsync("City", LoadSceneMode.Single);
    }
}

这是使用任何 RESTful API 调用时的标准模式。

【讨论】:

  • 嗨 Aaron 什么,如果我想重用 GetPlayerProfile 函数?
  • @vinilka8 没有什么能阻止你重用它。 GetPlayerProfile 方法本质上是异步的,因此您只需要在其余代码中考虑到这一点。可以缓存值,因此您可以保存 PlayerDisplayName 并稍后访问它。但是,如果这样做,您可能会遇到问题。想象一下,您缓存了 PlayerDisplayName 值,但随后他们更改了他们的个人资料信息。您需要确保在发生这种情况时刷新该数据,否则您将向用户显示“陈旧”值。
  • 嗨@Aaron,感谢您的解释,抱歉我的问题不清楚,我很想将GetPlayerProfile函数用于其他事情,如果我再次调用它,我将再次处理切换场景但我不希望这种情况发生。只是在开始。
猜你喜欢
  • 2022-11-26
  • 2017-03-14
  • 1970-01-01
  • 2021-10-02
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
相关资源
最近更新 更多