2017-05-05 2 views
2

Ich möchte den Netzwerkcode von meiner Spiellogik getrennt halten. Ich muss das nicht nur tun, um die Spiellogik zwischen Einzel- und Multiplayer-Spielmodi teilen zu können, ich möchte es auch wegen der Trennung von Sorgen.Den Unity-Netzwerkcode getrennt von der Spiellogik halten

Mein aktueller Ansatz besteht darin, den Code für meine netzwerkbezogenen Klassen so zu generieren, dass es eine Online- und eine Offline-Version gibt. Ich mache das mit T4-Vorlagen.

Die resultierenden Klassen wie folgt aussehen:

Standalone/Einzel Version:

// 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"); 
    } 
} 

Multiplayer-Version:

// 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"); 
    } 
} 

Sie beide teilen eine Schnittstelle, die Umsetzung von den Anrufern zu verstecken:

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

So wie Sie sehen können, verwenden beide Implementierungen den gleichen Körper und teilen den meisten Code, während die Einstiegspunkte davon abhängen, dass die Implementierung vernetzt ist oder nicht. Beachten Sie auch, dass die beiden Implementierungen unterschiedliche Basisklassen erben.

Vorteile:

  • Single Code keine Abhängigkeiten Richtung vernetzten Code hat und umgekehrt
  • Keine doppelten Code

Nachteile (keine, die manuell zumindest beibehalten werden muss):

  • Die Unterstützung für Schnittstellen in Unity ist begrenzt. Ich wäre nicht in der Lage, Szeneninstanzen von IHelloWorld aus dem Editor heraus anzusprechen.
  • mit getrennten Prefabs für Einzelspieler-/Multiplayer-Modi Mit
  • zu halten mit T4/Code-Generierung einzumischen

Ergänzender besserer Möglichkeiten kennen, damit umzugehen? Wie hast du dieses Problem gelöst?

Antwort

0

Sie könnten den Code ereignisbasiert strukturieren. Dadurch können sich Systeme bei Ereignissen registrieren, an denen sie interessiert sind. Dies trennt natürlich die Logik vom Netzwerkcode.

Als Beispiel wollen wir ein Projektil abfeuern. Sie können es Feuer durch den Aufruf:

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

können Sie dann Systeme registrieren, die bei dieser Veranstaltung interessiert sind:

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); 
}); 

Was cool ist neben können Sie dieses Ereignis in das NetworkSystem Register, das wird serialisieren Sie es, verschieben Sie es über das Netz, deserialisieren Sie es und feuern Sie es auf dem Client-Computer ab. Soweit der Kunde betroffen ist, wurde dieses Ereignis lokal aufgerufen.

Das ist ziemlich gut, außer dass Sie bald feststellen werden, dass dies eine endlose Schleife von Ereignissen verursacht. Wenn Sie ein FireProjektile-Ereignis an den anderen Client senden, fangen sie es ab und zünden es. Sofort fängt ihr NetworkSystem es und feuert es über das Netz ab.

Um dies zu beheben, benötigen Sie zwei Ereignisse für jede Aktion - eine Anfrage: FireProjectile und Antwort: ProjectileFired.

Ich habe vor einiger Zeit mit einer solchen Codebasis für ein persönliches Projekt gearbeitet. Es ist in C++, aber wenn Sie interessiert sind, können Sie mehr here lesen. Beachten Sie, wie sich der Server und der Client bei bestimmten Ereignissen registrieren, die sie weiterleiten.

Verwandte Themen