如何更新Firebase Unity中的分数,而不是替换/重写它



每当我重新打开游戏并再次开始得分时,它都会替换以前的数据。请帮帮我,告诉我哪里做错了。

我使用的是Firebase实时数据库。

下面是我的分数脚本:

public static int cashValue;
Text cash;
void Start()    
{    
cash = GetComponent();    
}
void Update()    
{    
cash.text = "" + cashValue;    
}

这是我在Firebase实时数据库中保存分数的地方:

private IEnumerator UpdateKills(int _kills)    
{    
//Set the currently logged in user kills    
var DBTask = DBreference.Child("users").Child(User.UserId).Child("kills").SetValueAsync(_kills);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)    
{    
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");    
}    
else    
{    
//Kills are now updated    
}    
}

这就是我从Firebase实时数据库检索数据的地方:

private IEnumerator LoadUserData()    
{    
//Get the currently logged in user data    
var DBTask = DBreference.Child("users").Child(User.UserId).GetValueAsync();
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)    
{    
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");    
}    
else if (DBTask.Result.Value == null)    
{    
//No data exists yet    
xpField.text = "0";    
killsField.text = "0";    
deathsField.text = "0";    
}     
else    
{    
//Data has been retrieved    
DataSnapshot snapshot = DBTask.Result;    
xpField.text = snapshot.Child("xp").Value.ToString();    
killsField.text = snapshot.Child("kills").Value.ToString();    
deathsField.text = snapshot.Child("deaths").Value.ToString();    
}    
}

它运行得很好,但唯一的问题是它取代了Score,而不是更新它或从我离开的地方开始。

流程应该是这样的:

int myData;
bool isMyDataLoaded = false;
void Start() {
LoadMyData();
}
void LoadMyData() {
StartCoroutine(IELoadMyData());
}
void SetMyData() {
if(isMyDataLoaded) {
// Set only if the data from database was retreived
StartCoroutine(IESetMyData());
}
}
IEnumerator IELoadMyData() {
// Load your data from database here
if(<fetch was successful>) {
myData = <the result>;
isMyDataLoaded = true; // Set data loaded as true
}
}
IEnumerator IESetMyData() {
// Update your data here
}

现在,只要您想更新,请调用SetMyData。只有当数据首次在本地游戏中成功提取时,它才会在DB中设置新数据。

需要注意的是,您可能会成为缓存的牺牲品。基本上,GetValueAsync通常返回本地缓存的内容(除非禁用持久性——这可能不应该(,并请求服务器进行更新。SetValueAsync写入本地缓存,并最终在后台对其进行同步。

因此,要更新值,您应该始终使用Transaction。从…起https://firebase.google.com/docs/database/unity/save-data#save_data_as_transactions

private void UpdateKills(int _kills)  {
DBreference.Child("users").Child(User.UserId).Child("kills").RunTransaction(mutableData => {
// if the data isn't an int or is null, just make it 0
// then add the new number of kills
var kills = ((mutableData.value as? int) ?? 0) + _kills;
return TransactionResult.Success(mutableData);
});
}

这将需要重新调整您的逻辑,以便记录delta,而不是保存总的击杀数。然后,该事务将重复运行,直到成功为止(通常是一次,除非您的数据不同步,在这种情况下通常是两次(。

对于获取数据,最好注册ValueChanged侦听器并直接从中更新UI。通过这种方式,您可以始终与服务器同步,并且使用本地缓存足够智能,因此您不必担心总是阻塞网络访问(如果没有缓存,则会得到null(。此外,随着事务中本地缓存的更新,您将获得具有最新数据的ValueChanged事件。

显然,并不是每个游戏都能稳定地从服务器随机接收价值更新。但是,如果您可以在实时数据库中移动数据,使其更具反应性,您将充分利用其内置的本地缓存和同步逻辑。

最新更新