我正在嘗試在我的 Unity 專案中設定一個網路事件系統,該系統允許在其他客戶端上觸發事件。該事件還應該傳遞特定于該事件的 EventArgs 型別。
但是,顯然 System.EventArgs 不是可序列化的,因此不能直接通過 MLAPI 網路發送。因此,我使用 Unity 的 JsonUtility 類將類轉換為字串,然后發送該字串。此外,我發送另一個字串,它是特定的 eventArgsType.ToString()。
在客戶端,我然后將 eventArgsType 轉換為具有 GetType 的型別,然后希望將資料字串反序列化為正確的 eventArgs 類。我目前通過與可能的 eventArgs-Subtypes 進行比較的討厭的 if-else 案例來做,然后反序列化。這有效,但非常丑陋,并且我擁有的子型別越多,它就會失控。但我不太確定如何做到這一點,并希望得到任何提示。
我目前擁有的:
public class EventSystem : NetworkBehaviour
{
[...]
public void TriggerLocalAndNetwork(string eventName, EventArgs data)
{
ulong clientId = NetworkManager.Singleton.LocalClientId;
if (Instance._eventDictionary.TryGetValue(eventName, out var triggeredEvent))
{
triggeredEvent.Invoke(clientId, data); // Local Trigger
string argsTyp = data.ToString();
EventToServerRpc(eventName, clientId, EventArgsSerializer.Serialize(data), argsTyp);
}
}
[ServerRpc(RequireOwnership = false)]
private void EventToServerRpc(string eventName, ulong clientId, string data, string argsType)
{
EventToClientRpc(eventName, clientId, data, argsType);
}
[ClientRpc]
private void EventToClientRpc(string eventName, ulong clientId, string data, string argsType)
{
if (clientId == NetworkManager.Singleton.LocalClientId)
return;
if (!Instance._eventDictionary.TryGetValue(eventName, out var triggeredEvent))
return;
Type args = Type.GetType(argsType);
EventArgs eventArgs = EventArgs.Empty;
// This is what I want to get rid off
if (args == typeof(MagicAttackEventArgs))
{
eventArgs = EventArgsSerializer.Deserialize<MagicAttackEventArgs>(data);
}
else if (args == typeof(HealthSystem.HealthSystem.TakeDamageEventArgs))
{
eventArgs = EventArgsSerializer.Deserialize<HealthSystem.HealthSystem.TakeDamageEventArgs>(data);
}
triggeredEvent.Invoke(clientId, eventArgs);
}
}
public static class EventArgsSerializer
{
public static string Serialize(EventArgs eventArgs)
{
string json = JsonUtility.ToJson(eventArgs);
return json;
}
public static T Deserialize<T>(string input)
{
T eventArgs = JsonUtility.FromJson<T>(input);
return eventArgs;
}
}
我嘗試的而不是 if-else 部分是這樣的:
Type args = Type.GetType(argsType);
MethodInfo method = typeof(EventArgsSerializer).GetMethod(nameof(EventArgsSerializer.Deserialize));
MethodInfo generic = method.MakeGenericMethod(args);
var result = generic.Invoke(null, new object[]{data});
EventArgs eventArgs = (EventArgs) Convert.ChangeType(result, typeof(EventArgs));
triggeredEvent.Invoke(clientId, eventArgs);
但它產生了一個鑄造錯誤,我不確定我是否正確使用了這些工具,它的靈感來自https://stackoverflow.com/a/232621這個答案。
uj5u.com熱心網友回復:
根據檔案,該FromJson方法有一個多載,它需要一個Type
Type args = Type.GetType(argsType);
EventArgs eventArgs = (EventArgs)JsonUtility.FromJson(data,args);
uj5u.com熱心網友回復:
我建議使用支持多型的序列化庫。例如,參見System.Text.Json的文章,但對于大多數序列化庫來說,這是一個相當常見的功能。
這使您可以為可在反序列化時使用的訊息使用公共基類。我建議定義您自己的訊息型別,而不僅僅是使用EventArgs.
根據訊息,有幾種不同的方法可以做不同的事情:
- 虛擬方法,可能是最簡單的選擇,但如果該方法根據實際型別需要不同的引數,則可能更難使用。
- 模式匹配
- 訪客模式
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/347445.html
上一篇:如何獲得剛體速度的分量?
下一篇:2D游戲中的健康系統
