Inventar Replikation Problem

  • Hallo Leute,


    zunächst einmal wollte ich sagen, dass ich es toll finde, dass sich hier mittlerweile eine große deutsche Community gebildet hat. Ganz zu Anfang, also vor ein paar Jahren, hatte ich mal sowas auf Skype gemacht. Ich glaube sogar, dass es den Channel sogar noch gibt. Seit langer Zeit bin ich nun mal wieder zu UE4 gewechselt und ich habe festgestellt, dass sich doch einiges geändert hat. Wahrscheinlich hat das aber nichts mit meinem Problem zu tun :)


    Ich suche momentan einen Denkanstoß bzw. auch einen Best-Practice zu folgender Problematik:

    Ich arbeite gerade an einem Inventarsystem, welches eigentlich ausschließlich für den Multiplayer gedacht ist. Momentan ist alles noch relativ simpel aufgebaut und funktioniert auch im Singleplayer. Nun möchte ich aber den Schritt in Richtung Replizierung wagen. Hier die Eckdaten:




    1. Ich habe eine Variable "Item Reference" vom Typ "Master Item" (Replizierter Actor)
    2. Drücke ich nun auf beispielsweise die Taste "F", führe ich ein custom event auf dem Server aus.

      Hierbei führt der Server einen Linetrace zwischen der Kamera(Server) und einem Vector in Blickrichtung aus.
    3. In der Linetrace-Funktion wird nun die Item Referenz gesetzt:

      Das funktioniert soweit ganz gut.
    4. Daraufhin wird auf dem Server die "AddItemToInventory"-Funktion aufgerufen. DIe prüft das Gwicht und enthält etwas weitere Logik. Am Ende dieser Funktion, wird dann das Item zu einem Array hinzugefügt und daraufhin Actor destroyed. Das Array ist replicated.

    Die zuvor genannten Punkte funktionieren soweit. Nun ergibt sich aber bei mir folgende Frage. Ich möchte den LineTrace z.B. auf den Client auslagern und diesen nicht vom Server erledigen lassen. Setze ich nun aber auf dem Client die Itemreferenz, kann der Server damit nichts anfangen, weil diese ja nur auf dem Client existiert. Denke ich da richtig? Ich hatte bereits versucht den LineTrace auf dem Client auszuführen und die Variable mit in das Custom Event zu geben, was aber nicht funktioniert hat. Bewege ich mich da auf dem Holzweg? Leider bin ich über den Hergang ziemlich verwirrt, wie sich sowas in der Regel umsetzen lässt.


    Wie würdet ihr das lösen?


    Vielen vielen Dank für eure Zeit.


    PS: Bei Bedarf kann ich gerne ein kleines Video anfertigen.


    MFG 3HMonkey

    • Offizieller Beitrag

    also, dieses Problem muss ich nochmal selber abends darstellen. Aber eins kann ich dir schonmal sagen, lass lieber den Server vieles erledigen. Das ist kaum Rechenaufwand.

    Ich glaube es gibt auch ein Problem mit linetrace am client, dass für Server weitergeleitet wird. Deswegen muss ich das selber nochmal testen.

  • Wenn du das wirklich über den Client regeln willst, dann würd ein Event machen was auf dem Client ausgeführt wird (Run on Owning Client heisst das glaub ich). Diesem Event gibts du dann alle notwendigen params mit, die du für den Linetrace brauchst.


    Allerdings stellt sich immer noch die Frage warum du das auf dem Client haben willst.


    bei ner Server Client Lösung arbeite ich meistens nach der Grundlage:

    Visuell = Client

    Berechnungen und Gamelogik = Server


    Gruss Veelos

  • Hallo und vielen Dank für eure Antworten!


    Generell kann die Logik auch auf dem Server bleiben. Ich werde versuchen die Prozesse so zu gestalten wie Veelos vorgeschlagen hat.


    Nur nochmal zum Replizierungshergang, exemplarisch an folgenden Beispiel:

    • Lokale Variabel (Array aus Structs z.b., welche stellvertretend für Items stehen) nennen wir sie ItemStructs
    • Event auf Server, welches die angesprochene Logik enthält (RunOnServer)
    • ItemStructs muss replicated sein, damit der Client immer die aktuellste Variable hat, um beispielsweise über diese in UMG zu iterieren, korrekt?


    Nun zu einem konkreten Problem, was auch mitunter ein Auslöser zur Fragestellung war.

    zusätzlich zu dem angesprochenen LineTrace, habe ich ein UMG Menü in Form einer Liste. Drücke ich nun auf eine Taste um mein Inventar zu öffnen, werden alle Item-Actors in einem gewissen Radius in meinem Inventar im Bereich "GroundItems" angezeigt. Man muss sich das so vorstellen, dass ich auf der linken Seite des Bildschirms ein Bereich GroundItems öffnet und auf der rechten Seite das eigentliche Inventar. Das Funktioniert auch soweit. Diese GroundItems werden in Form einer Liste aus Buttons angezeigt. Klickt man eines (Button in UMG), wird dieses dann im Inventar angezeigt, von der GroundItems-Liste entfernt und der Actor am Boden zerstört. Funktioniert gut im SP. Nur MP bereitet mir Kopfzerbrechen.

    Momentan parse ich alle Actors in einer Range um den PlayerCharacter, sobald das Inventar geöffnet ist alle 0,1 Sekunden. Ich mache das, weil ich möchte, dass wenn ich in die Nähe von Items komme, diese in dieser Liste angezeigt werden und wenn ich mich wieder entferne diese aus der Liste entfernt werden. Für SP ok, aber sollte ich das aber auf dem Server tun, müsste dieser mir ja alle 10tel Sekunde, pro Client das StructArray replizieren?


    MFG 3HMonkey

    • Offizieller Beitrag

    also, ständig parsen brauchst du nicht. Wenn du ActorBeginOverlap und ActorEndOverlap nutzt, dann kannst du mit begin das Item speichern und mit end das item löschen.


    Deine Replizierungshergang klingt gut, nur zu kurz um wirklich dir ein Feedback zu geben ^^

    Was du einfach bedenken musst, wenn du eine Variable für den repliziervorgang speichern möchtest, dann muss es vom Server gemacht werden. Es geht aber nur ums speichern. zB Kannst du komplizierte Rechenaufgaben beim Client erledigen lassen. Am Ende muss aber trotzdem an den Server die Daten gesendet werden. zB Rechenaufgabe(client)->CustomEvent(RunOnServer)->Set Variable. Leider ist dieser Vorgang manipulierbar vom Client. Desswegen sollte der Vorgang besser so lauten: CustomEvent(RunOnServer)->Rechenaufgabe(client)->SetVariable. Viele Sachen ergeben aber für spezielle Sachen sogenannte Lags, wenns um geschwindigkeit geht. Da lässt man einfach beide Seiten die Rechenaufgabe erledigen. Die sogenannten lags gleichen das aus und man bekommt nichts davon mit.


    zu deinem konkreten Problem, deine Items liegen auf dem Client und auf dem Server. Der Client könnte zb, ohne das der server davon mitbekommt, einfach schon mal sehen, was dort für items liegen. Sollte man ein Item einsammeln wollen, dann muss natürlich der Server es mitbekommen. Ab da kannst du es machen, dass der Server dieses nun erledigt.

  • Ich denke, dass ich alle Operationen auf dem Server laufen lassen möchte. Ich habe den Vorgang mal nach deinem Tipp modelliert. Allerdings besteht dabei folgendes Problem:

    Wie erwähnt parst momentan eine Funktion die Items auf dem Boden und bildet diese auf der linken Seite des Menüs ab:


    Die Items sind dabei in einem Actor-Array hinterlegt. Jeder Button steht also mit einem Actor in Verbindung. Es macht mir momentan echt Probleme das Actorarray zu replizieren, weil es dabei zu Nullpointer kommen kann, bzw. UMG bereits aktualisiert, aber das Array wurde noch nicht komplett repliziert worden ist. Der Client lädt quasi sein Array und nicht das, was vom Server repliziert wird (nur ab und an), weil dieses noch nicht angekommen ist.

    Das führt dann auch manchmal zu folgenden komischen Artefakten:



    Ich halte diesen Prozess generell als Denkwürdig... Ich habe keine Ahnung, wie ich den Prozess adäquat realisieren kann. Wenn jemand noch eine Idee hätte, wäre ich echt froh darüber :)


    LG 3HMonkey