数组 returns 错误值只有第一次
Array returns bad values only first time
所以我在使用 Steamworks(排行榜)时遇到了一些奇怪的问题。当我触发我的函数以获得分数时,通过调试我知道它只工作 fine.However 我的数组在第一个函数 运行 总是 returns 默认值 values.After 我触发第二个函数时间一切正常。我试图找出问题所在,但失败了。
这是我在这种情况下使用的全部代码:
统计结构
USTRUCT(BlueprintType)
struct FScorePackage
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
FString PlayerName = "working";
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
int32 Rank = 0;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
int32 Score = 0;
};
向 Steam 发送请求的函数:
.h
UFUNCTION(BlueprintCallable, Category = "Steam|Leaderboard", meta = (Latent, LatentInfo = "LatentInfo", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
TArray<FScorePackage> DownloadScoresAroundUser(UObject* WorldContextObject, int AboveUser, int BelowUser, struct FLatentActionInfo LatentInfo);
.cpp
TArray<FScorePackage> USteamLeaderboard::DownloadScoresAroundUser(UObject* WorldContextObject, int AboveUser, int BelowUser, struct FLatentActionInfo LatentInfo)
{
if (!m_CurrentLeaderboard)
{
return Scores;
}
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject))
{
FLatentActionManager& LatentActionManager = World->GetLatentActionManager();
if (LatentActionManager.FindExistingAction<SteamLeaderboardLatentClass>(LatentInfo.CallbackTarget, LatentInfo.UUID) == NULL)
{
// load the specified leaderboard data around the current user
SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries(m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -AboveUser, BelowUser);
m_callResultDownloadScore.Set(hSteamAPICall, this,&USteamLeaderboard::OnDownloadScore);
LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, new SteamLeaderboardLatentClassScores(LatentInfo));
return Scores;
}
return Scores;
}
return Scores;
}
现在来自 steam 的回调函数:
.h
void OnDownloadScore(LeaderboardScoresDownloaded_t *pResult, bool bIOFailure);
CCallResult <USteamLeaderboard, LeaderboardScoresDownloaded_t> m_callResultDownloadScore;
.cpp
void USteamLeaderboard::OnDownloadScore(LeaderboardScoresDownloaded_t *pCallback, bool bIOFailure)
{
if (!bIOFailure)
{
m_nLeaderboardEntries = __min(pCallback->m_cEntryCount, 30);
for (int index = 0; index < m_nLeaderboardEntries; index++)
{
SteamUserStats()->GetDownloadedLeaderboardEntry(pCallback->m_hSteamLeaderboardEntries, index, &m_leaderboardEntries[index], NULL, 0);
}
TranslateEntries();
scores = true;
}
}
最后是将分数写入数组的函数:
.h
UFUNCTION(BlueprintCosmetic, Category = "Steam|Leaderboard")
TArray<FScorePackage> TranslateEntries();
.cpp
TArray<FScorePackage> USteamLeaderboard::TranslateEntries()
{
FScorePackage ThisScore;
Scores.Init(ThisScore, 30);
for (int i = 0; i < 30; i++)
{
ThisScore.PlayerName = GetSteamName(m_leaderboardEntries[i].m_steamIDUser);
ThisScore.Rank = m_leaderboardEntries[i].m_nGlobalRank;
ThisScore.Score = m_leaderboardEntries[i].m_nScore;
Arrayas[i] = ThisScore;
}
return Scores;
}
Scores 数组只是静态 TArray Scores,而 scores=true 仅用于在调用 DownloadScoresAroundUser 后继续进行函数的潜在检查:)
我的正常流程是:
1.I 已经有排行榜的句柄。
2.I正在调用 DownloadScoresAroundUser。
3.Flow 进入 latent,由于 scores=false 而无法继续。
4.After 我收到了来自 Steam OnDownloadScore 火灾的回调,为我提供了所有需要的信息(已检查是否确实如此!)。
5.Then 我调用 TranslateEntries 来获取数组中所有带有名称和排名的分数。
6.Then 我正在打印整个数组(在 unreal 中使用 break 包)并获取我的结构的默认值。
7.After 我再次启动整个循环,我得到了正确的值。
如果需要任何进一步的信息,请告诉我:)
Translateentries 将数据从 0 复制到 30,但实际上只有 "Callback->m_cEntryCount" 被初始化。所以如果它 < at 30,从 "Callback->m_cEntryCount" 到 30 的数据可能是错误的。你能打印出这个变量的值 "in SteamLeaderboard::OnDownloadScore" 吗?
这是一个猜测,但您似乎遇到了延迟问题。当您发出下载乐谱的请求时,这是一个不会阻塞的耗时调用。您设置了一个将在分数准备好时调用的回调,然后 return 现有的空 Scores
对象。
当您第二次调用时,已经过了足够的时间来下载乐谱并 Scores
填充乐谱,因此 return 有一些乐谱。
请注意,您有一个潜在的竞争条件,其中 DownloadScoresAroundUser
可以访问 (return) Scores
而您的回调正在填充该向量。
这是一种可能的解决方案。在乐谱完成加载之前,DownloadScoresAroundUser
return 是一个空乐谱(或者可能表明正在加载乐谱)。加载分数并填充 Scores
后,它将 return 那些。此外,回调(除了填充 Scores
之外)可以某种方式通知 DownloadScoresAndUser
的调用者新分数可用。他们可以通过再次调用以获取更新的分数并刷新显示来对此作出响应。
所以我在使用 Steamworks(排行榜)时遇到了一些奇怪的问题。当我触发我的函数以获得分数时,通过调试我知道它只工作 fine.However 我的数组在第一个函数 运行 总是 returns 默认值 values.After 我触发第二个函数时间一切正常。我试图找出问题所在,但失败了。
这是我在这种情况下使用的全部代码:
统计结构
USTRUCT(BlueprintType)
struct FScorePackage
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
FString PlayerName = "working";
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
int32 Rank = 0;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
int32 Score = 0;
};
向 Steam 发送请求的函数: .h
UFUNCTION(BlueprintCallable, Category = "Steam|Leaderboard", meta = (Latent, LatentInfo = "LatentInfo", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
TArray<FScorePackage> DownloadScoresAroundUser(UObject* WorldContextObject, int AboveUser, int BelowUser, struct FLatentActionInfo LatentInfo);
.cpp
TArray<FScorePackage> USteamLeaderboard::DownloadScoresAroundUser(UObject* WorldContextObject, int AboveUser, int BelowUser, struct FLatentActionInfo LatentInfo)
{
if (!m_CurrentLeaderboard)
{
return Scores;
}
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject))
{
FLatentActionManager& LatentActionManager = World->GetLatentActionManager();
if (LatentActionManager.FindExistingAction<SteamLeaderboardLatentClass>(LatentInfo.CallbackTarget, LatentInfo.UUID) == NULL)
{
// load the specified leaderboard data around the current user
SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries(m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -AboveUser, BelowUser);
m_callResultDownloadScore.Set(hSteamAPICall, this,&USteamLeaderboard::OnDownloadScore);
LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, new SteamLeaderboardLatentClassScores(LatentInfo));
return Scores;
}
return Scores;
}
return Scores;
}
现在来自 steam 的回调函数: .h
void OnDownloadScore(LeaderboardScoresDownloaded_t *pResult, bool bIOFailure);
CCallResult <USteamLeaderboard, LeaderboardScoresDownloaded_t> m_callResultDownloadScore;
.cpp
void USteamLeaderboard::OnDownloadScore(LeaderboardScoresDownloaded_t *pCallback, bool bIOFailure)
{
if (!bIOFailure)
{
m_nLeaderboardEntries = __min(pCallback->m_cEntryCount, 30);
for (int index = 0; index < m_nLeaderboardEntries; index++)
{
SteamUserStats()->GetDownloadedLeaderboardEntry(pCallback->m_hSteamLeaderboardEntries, index, &m_leaderboardEntries[index], NULL, 0);
}
TranslateEntries();
scores = true;
}
}
最后是将分数写入数组的函数:
.h
UFUNCTION(BlueprintCosmetic, Category = "Steam|Leaderboard")
TArray<FScorePackage> TranslateEntries();
.cpp
TArray<FScorePackage> USteamLeaderboard::TranslateEntries()
{
FScorePackage ThisScore;
Scores.Init(ThisScore, 30);
for (int i = 0; i < 30; i++)
{
ThisScore.PlayerName = GetSteamName(m_leaderboardEntries[i].m_steamIDUser);
ThisScore.Rank = m_leaderboardEntries[i].m_nGlobalRank;
ThisScore.Score = m_leaderboardEntries[i].m_nScore;
Arrayas[i] = ThisScore;
}
return Scores;
}
Scores 数组只是静态 TArray Scores,而 scores=true 仅用于在调用 DownloadScoresAroundUser 后继续进行函数的潜在检查:)
我的正常流程是: 1.I 已经有排行榜的句柄。 2.I正在调用 DownloadScoresAroundUser。 3.Flow 进入 latent,由于 scores=false 而无法继续。 4.After 我收到了来自 Steam OnDownloadScore 火灾的回调,为我提供了所有需要的信息(已检查是否确实如此!)。 5.Then 我调用 TranslateEntries 来获取数组中所有带有名称和排名的分数。 6.Then 我正在打印整个数组(在 unreal 中使用 break 包)并获取我的结构的默认值。 7.After 我再次启动整个循环,我得到了正确的值。
如果需要任何进一步的信息,请告诉我:)
Translateentries 将数据从 0 复制到 30,但实际上只有 "Callback->m_cEntryCount" 被初始化。所以如果它 < at 30,从 "Callback->m_cEntryCount" 到 30 的数据可能是错误的。你能打印出这个变量的值 "in SteamLeaderboard::OnDownloadScore" 吗?
这是一个猜测,但您似乎遇到了延迟问题。当您发出下载乐谱的请求时,这是一个不会阻塞的耗时调用。您设置了一个将在分数准备好时调用的回调,然后 return 现有的空 Scores
对象。
当您第二次调用时,已经过了足够的时间来下载乐谱并 Scores
填充乐谱,因此 return 有一些乐谱。
请注意,您有一个潜在的竞争条件,其中 DownloadScoresAroundUser
可以访问 (return) Scores
而您的回调正在填充该向量。
这是一种可能的解决方案。在乐谱完成加载之前,DownloadScoresAroundUser
return 是一个空乐谱(或者可能表明正在加载乐谱)。加载分数并填充 Scores
后,它将 return 那些。此外,回调(除了填充 Scores
之外)可以某种方式通知 DownloadScoresAndUser
的调用者新分数可用。他们可以通过再次调用以获取更新的分数并刷新显示来对此作出响应。