Introdução ao problema:
dois tipos
// Sincroniza dados, incluindo dados do usuário
public class SysMessage
{ public int dti { get; definir; } public UserData playerJMsg { get; definir; } }
// Dados do usuário
public class UserData
{ public string playerId{ get; definir; } //nome do usuário
public string email{ get; set; }//email
public int Execution { get; set; }// força física
public long gold { get; set; } // moeda do jogo
}
O tipo SysMessage geralmente é retornado por heartbeat, e os dados retornados por heartbeat não são dados completos, apenas alguns campos serão sincronizados, por exemplo, apenas ouro em UserData será sincronizado.
Depois que recebo os dados json do servidor, eles são analisados diretamente nas classes
dados SysMessage = JsonMapper.ToObject<SysMessage>(@request.downloadHandler.text);
No entanto, após a análise da classe, alguns campos que não precisam ser sincronizados são inicializados, ou seja, o email é nulo e a execução é 0
Como resultado, não sei se é um campo que precisa ser sincronizado, precisamos apenas sincronizar os campos contidos nos dados do json.
Solução
sys1 são dados json recebidos diretamente para JsonData: JsonMapper.ToObject(@request.downloadHandler.text)["sysMessage"]
Os dados json solicitados por unityWebRequest usados aqui
var sys = sys1 as JsonData;
if (m_user == null) m_user = JsonMapper.ToObject<UserData>(sys["playerJMsg"].ToJson());
else
{ try { var player = sys["playerJMsg"]; / / Mesclar dados do usuário foreach (var p in m_user.GetType().GetProperties()) { try { if (null != player[p.Name]) {// precisa sincronizar dados if (p.Name == "pet " ) {// é um tipo
p.SetValue(m_user, JsonMapper.ToObject<HeroData>(JsonMapper.ToJson(player[p.Name]))); }
else
{
// Determine o tipo de dados original, caso contrário, a conversão poderá falhar
if (p.PropertyType.Name == "String")
{ p.SetValue(m_user, player[p.Name].ToString()); } else if (p.PropertyType.Name == "Int64") { p.SetValue(m_user, Convert.ToInt64 (jogador [p.Name].ToString()));
}
else if (p.PropertyType.Name == "Int32")
{ p.SetValue(m_user, Convert.ToInt32(player[p.Name].ToString())); } } } } catch { Console.WriteLine("playerJMsg não encontrado "+ p.Name); } } } catch (FormatException) {
Console.WriteLine("sys não encontrado playerJMsg");
}
}
O uso de try catch aqui é porque uma vez que jsonData não contém uma chave, um erro será relatado imediatamente. Por exemplo, sys não contém o campo playerMsg. Se sys["playerMsg"] for usado diretamente, um erro será relatado Aqui está uma tentativa de obter os campos de que precisamos.
System.Collections.Generic.KeyNotFoundException: a chave fornecida não estava presente i
Dessa forma, apenas alguns dados são sincronizados para evitar o problema de valor padrão causado pela conversão direta de json para classe, e não está claro quais são sincronizados.