2017-05-05 139 views
2

我想讓網絡代碼與我的遊戲邏輯分開。我不僅需要這樣做才能在單人遊戲模式和多人遊戲模式之間共享遊戲邏輯,我還希望能夠分離關注事物。讓Unity網絡代碼與遊戲邏輯分開

我目前的做法是爲我的網絡相關類生成代碼,使其具有在線和離線版本。我用T4模板做這個。

產生的階級是這樣的:

單機/單人版本:

// T4 GENERATED CODE 
// Head (Singleplayer version) 
class StandaloneHelloWorld : MonoBehaviour, IHelloWorld 
{ 
    private string name; 

    public void SayHello() 
    { 
     SayHelloInternal(); 
    } 

// Body 
    public string Name 
    { 
     get { return name; } 
     set { name = value; } 
    } 

    void SayHelloInternal() 
    { 
     Debug.Log(Name + ": Hello World"); 
    } 
} 

多人版本:

// T4 GENERATED CODE 
// Head (Multiplayer version) 
class NetworkedHelloWorld : NetworkBehaviour, IHelloWorld 
{ 
    [SyncVar] 
    private string name; 

    public void SayHello() 
    { 
     CmdSayHello(); 
    } 

    [Command] 
    void CmdSayHello() 
    { 
     RpcSayHello(); 
    } 

    [ClientRpc] 
    void RpcSayHello() 
    { 
     SayHelloInternal(); 
    } 

// Body 
    public string Name 
    { 
     get { return name; } 
     set { name = value; } 
    } 

    void SayHelloInternal() 
    { 
     Debug.Log(Name + ": Hello World"); 
    } 
} 

它們共用一個接口來隱藏從呼叫者的實現:

interface IHelloWorld 
{ 
    string Name { get; set; } 
    void SayHello(); 
} 

因此,您可以看到,兩個實現使用相同的主體,共享大部分代碼,而入口點取決於是否聯網。 另請注意,這兩個實現繼承了不同的基類。

優點:

  • 單人代碼具有朝向聯網代碼沒有依賴關係和(手動保持沒有具有至少)反之亦然
  • 無重複碼

缺點:

  • Unity中對接口的支持是有限的。我無法從編輯器內部引用IHelloWorld的場景實例。
  • 用戶必須爲單人/多人遊戲模式
  • 獨立的預製件經與T4 /代碼生成

你知道的更好的方法來處理這個染指?你是如何解決這個問題的?

回答

0

您可以以基於事件的方式構造代碼。這將允許系統註冊他們感興趣的事件。這自然地將邏輯從網絡代碼中分離出來。

舉一個例子,假設你想發射一顆子彈。 你可以通過調用火了:

new Event(EventType.FireProjectile, pos, dir, template)

然後,您可以註冊一個有興趣在此事件系統:

CollisionSystem.Register(EventType.FireProjectile, (e) => { 
    CollisionSystem.AddCollider(e.template.bounds); 
}); 

AudioSystem.Register(EventType.FireProjectile, (e) => { 
    AudioSystem.PlaySound("Woosh"); 
}); 

AISystem.Register(EventType.FireProjectile, (e) => { 
    AISystem.AlertAtPosition(e.pos); 
}); 

什麼是酷接下來就是你可以將此事件向NetworkSystem註冊將將其序列化,將其移動通過網絡,將其反序列化,然後在客戶機上將其燒掉。所以就客戶而言,這個事件在當地被稱爲。

NetworkSystem.Register(EventType.FireProjectile, (e) => { 
    NetworkSystem.Broadcast(e, Channel.Reliable); 
}); 

這是相當不錯的,只是你很快就會意識到這將導致無限循環的事件。當你向另一個客戶端發送一個FireProjectile事件時,他們會捕獲並釋放它。他們的NetworkSystem立即捕獲並通過網絡觸發它。

爲了解決這個問題,你需要爲每一個動作兩個事件 - 一個請求:FireProjectile和響應:ProjectileFired

前段時間,我曾爲一個個人項目使用過這樣的代碼庫。它使用C++,但如果你有興趣,你可以閱讀更多here。注意服務器和客戶端是如何註冊某些事件的,他們會轉發。