Beiträge von Phoenix-100

    Hey zusammen


    1. Da hört es aber schon so ziemlich auf. GamMode ist wohl nur einmal auf dem Server existent?

    Ja, der existiert nur einmal und zwar auf dem Server. Der ist dazu gedacht, grundlegende Regeln zu implementieren. Etwa wie viele Spieler die Runde erlaubt, wie und wann ist Spiel vorbei oder gewonnen etc. Der GameMode wird bei jeder Runde zurückgesetzt.


    2. Wozu brauch ich GameState?

    Unter umständen musst du Daten zur Akuellen Spielrunde speichern. Zum Beispiel ob die Runde schon begonnen hat oder wie lange diese schon läuft oder deine spezifischen Daten, die nicht auf einen Spieler bezogen sind (In Battlefield zum Beispiel die Tickets). Im Gegensatz zum GameMode, können alle Spieler auf den GameState zugreifen. Wird bei jeder Runde zurückgesetzt.


    3. Warum kann ich Dinge die in PlayerState speichere nicht einfach im PlayerController Speichern?

    Der PlayerController representiert den "Willen" des Spielers. Jeder Spieler hat also einen PlayerController. Im Multiplayer hat jeder lokale Spieler aber nur Zugriff auf seinen eigenen PlayerController, also nur einen. Das ist ein Problem, denn was machst du jetzt mit Daten, auf die alle Spieler zugreifen sollen? Wie zum Beispiel der Name des Spielers, wie oft der gestorben ist etc. Mit dem PlayerState kannst du diese Infos ganz einfach mit allen Spielern teilen weil dieser im Gegensatz zum PlayerController an alle Spieler repliziert werden. Beides wird bei jeder Runde zurückgesetzt, bleibt aber über den Tot des Pawns bestehen.


    4. In meinem Spiel muss ich z.b. ein "Deck Karten" im Menü auswählen und das ins Game übertragen das wäre dann ja GameInstance.

    Die GameInstance ist Sinngemäss das Spielfenster oder der Prozess. Im Grunde die Instanz des laufenden Spiels, er wird erstellt wenn das Spiel gestartet wird und erst wieder gelöscht wenn es geschlossen wird. Deswegen werden Daten darin gespeichert, die über die gesamte Dauer, bis zum schliessen des Spiels ,behalten werden müssen. Das kannst du also so machen, es gibt aber auch andere Weg die Daten von einem Level in das nächste zu kopieren.


    5. Gibt es einen davon wovon der Server immer weiß? Sprich ich nichts replicaten muss zu anderen Spielern oder dem Server?

    Der Sever weiss immer von allem, er wiederspiegelt den einzig "wahren" Zustand des Spiels. Ich habs oben schon beschrieben.

    Nur der Server hat den GameMode, alle haben den GameState. Die Clients haben nur den eignene PlayerController, haben aber alle PlayerStates. Die GameInstance existiert nur einmal.


    6. In welchem Blueprint spawne ich was? z.b. meine Handkarten würde ich worüber spawnen? Macht das einen Unterschied?

    Das darfst du selber entscheiden :) Persönlich würde ich in einem Kartenspiel nur die Kartendaten replicaten, also wer welche Karten besitzt. Wenn die Karten offen sind würde ich das als Array im PlayerState machen, wenn nicht vermutlich im PlayerController. Viele würden vermutlich aber den Pawn nutzen. Ich würde einen eigenen Actor "Spielebrett" machen. Dieses nimmt das Karten Array von den Spielern entgegen und stellt diese dar. Der Lokale Spieler ist dadurch immer am selben Ort. Bei jedem Update soll das Spielbrett dann aktualisieren. Meine Begründung dafür wäre, dass ich weniger Daten über das Netz senden muss und den Rest, sound, effekte etc. einfach lokal machen kann und mich nicht weiter um Networking / lag kümmern muss. Aber das kannst du machen wie du willst.

    Hallo


    Sieht mir nach Indoor aus? Sind diese Flecken auch draussen da?

    Falls ja, würde ich mir die Lighmaps UVs anschauen.


    Kann den Einfluss von Emission nicht nachvollziehen. Sind die nach dem Rebuild tatsächlich weg? Weil wenn du das material änderst, wird die Scene wieder dynamisch beleuchted.


    Gruss

    Hallo


    Mixamo Character haben eine anderen Skeletontree als der Default UE4 Character. Das ist also nicht miteinander kompatibel.

    Du musst die Animation an den Mixamo Character anpassen oder umgekehrt. Das geht per Animation Retargeting.

    Oder du passt den Skeleton an.


    Falls beide den selben Skeleton haben, kannst bzw. musst du den Skeleton beim Import der Animation auswählen. Oder wiederum Animation Retargeting.


    Gruss

    Hey zusammen


    Die Engine hat viele Performance Tools.

    Ein schneller Befehl ist "stat unit", den kennst du vermutlich schon. Er zeigt dir nicht nur die Zeit für ein Frame also FPS, sondern auch die Zeit der der Game Thread braucht, also für CPU Code (Blueprints), die Draw zeit und GPU Zeit. Ideal für die erste Indikation wo das Performance Bottleneck ist.


    Je nachdem wo das Problem liegt, kannst du mit weiteren Commands genauer auf den Grund gehen. Hier eine Liste davon.

    Für dein Ziel wäre das dann vielleicht stat Uobject, dass dir die Performance von UObjects anzeigt.


    Tiefgreifender gehts mit Profiling über mehrere Frames. Der Command ist auch in der Liste, nämlich stat StartFile zum starten der Aufzeichnung und stat StopFile zum stoppen. Es erlaub dir die CPU und GPU über einen längeren Verlauf aufzuzeichnen.

    Es speichert das unter deinem Project Saved/Profiling. Die Engine kann das direkt anzeigen. Dazu unter Window->Developer->Session Fronted. Dort kannst du das File unter Profiling laden und anschauen. Dort kannst du alles auswählen und analysieren was du brauchst.

    Auch einzelen Objekte. Vergiss nicht smoothing und FPS Cap auszumachen, sonst sind die Werte falsch. Am Besten testest du das auch im Standalone Game.


    Gruss

    Hey zusammen


    Zu diesem Thema gibt ganze Bücher. Zur Ergänzung wieso überhaupt Multithreading nötig ist bezogen mit einem Beispiel der Unreal Engine. Nehmen wir einmal an, du hast einen rechenintensiven Task, das kann zum Beispiel AI sein, Animation, oder kürzlich habe ich Positionsberechnungen für eine Formation durchführen müssen. Als Beispiel stellvertretend sagen wir mal, wir müssen alle Primzahlen bis zu 1'000'000 ausgeben.


    Los geht's, einfach in Blueprint ein Loop bis zu einer Mio:



    Wenn ich das jetzt ausführe freezed das ganze Spiel für ein paar Sekunden und bricht den Loop dann ab. Es wirkt also so als ob das hängen geblieben ist. Das ist also absolut keine Option. Das sieht man auch sonst häufig zum Beispiel bei Ladeanimationen, wenn der Mainthread blockiert ist, bleibt einfach die Animation stehen. Wieso passiert das? Der Mainthread bearbeitet das Sequenziell, also alles andere muss warten bis diese Rechenintensive Operation abgeschlossen ist. Entsprechend friert das Bild ein, keine Inputs mehr möglich etc.


    Wie löst man das jetzt? Mann kann das an den Tick hängen und pro Tick nur eine oder ein paar dieser Zahlen berechnen, sodass der Mainthread nicht blockiert.



    Und siehe da - das Spiel friert nicht mehr ein. Aber nun dauert das ewig. Was vorher eine Minute gedauert hat, dauert nun über eine Stunde. Was nun? Multithreading!

    Dazu der erstelle ich die Klasse PrimeNumberWorker und implementiere Runnable.




    Was immer jetzt in Run ausgeführt wird passiert auf einem eigenen Thread.

    Erstellen und gleich starten kann ich den mit:

    C++: Starten
        Worker = new FPrimeNumberWorker(Iterations);

    Und wieder löschen:

    Code: Löschen
      delete Worker;

    Okay. Wenn ich den jetzt ausführe, keine Einfrieren und die Berechnung dauert wieder etwa eine Minute - Cool :)

    Wie du siehst, hat das Potential für wirklich(!) erhebliche Performanceoptimierung. Kommt aber auch mit starker Limitierungen, so kannst du nicht einfach Daten auf deinem Mainthread lesen oder Schreiben. Ein Teil dieser Problematik hat schon Tomarr erklärt.


    Das war jetzt etwas unnötig ausschweifend. Zurück zum Punkt. Der BP den du gepostet hast funktioniert bei mir. Natürlich siehts nicht gut aus, weil jetzt wechselt der Animation mehrfach pro Sekunden, also jedes Update gibts unter Umständen ein Wechsel.


    Für deinen Zweck gibts den RandomSequencePlayer. Der ist Threadsafe und macht genau was du willst. Er wechselt die Animation random. Du kannst sagen wie oft er dieselbe Animation spielen soll, welche Wahrscheinlichkeit etc. So funktioniert's:



    Auf der rechten Seite kannst du alle die Animation hinzufügen die du möchtest.


    Gruss

    Hallo


    Das ist kein Compilierungsfehler, lediglich eine nett gemeinte Warnung, dass der Animation Blueprint per Default Multithreaded ist zur Optimierung. Die random Methode die du aufrufst ist allerdings nicht Thread safe, zumindest hat sie das nicht definiert und deswegen die Warnung.

    Du kannst das Multithreading direkt im AnimationBP deaktivieren unter Classsettings->Optimization. Das würde ich die allerdings nicht empfehlen, denn dann läuft das auf einem Thread was die Performance negative beinflussen kann.

    Der Eventgraph wird nicht auf mehreren Threads ausgeführt, deswegen dort auch die ganze Logik wo du die Methode auch problemlos aufrufen kannst.
    Allerdings hätte ich jetzt gesagt das sollte trotzdem problemlos funktionieren? Hast du es ausprobiert?


    Gruss

    Bo0m Interactive nein eigentlich einfacher, du solltest nur das erstellte Patch Pak file das unter [ProjectName]\Saved\StagedBuilds[PlatformName][ProjectName]\Content\Paks erstellt wird kopieren zum Folder vom Spieler [ProjectName]\Releases[VersionNumber][PlatformName].


    Hier die Doks dazu.


    Geloscht Danke für die richtig Stellung. Das ist schon cool wenn nicht mal der Entwickler das ganze Spiel hochladen muss. Auch an @'Bo0m Interactive' das mit Steam habe ich überlesen. Viele Plattformen die Provision verlangen bieten solche Services. Wäre spannend zu Wissen wie nahe dieses System and die richtigen Patches von der Effizienz her rankommt, vor allem bei grossen Änderungen.


    Gruss

    Hallo


    Zunächst hast du ein Interactor als Argument in der "Interact" Message. Den übergibst du aber gar nicht, machst aber im zweiten Screen etwas damit. Zusätzlich ist nicht sichergestellt, dass der Actor den du im ersten Screen Traced überhaupt das Interface implementiert.


    Du kannst das Problem analytisch lösen indem du es Debuggst. Schritt für Schritt. Dazu kannst du rechts klicken auf das Interact im ersten Screen -> Add Debug Point. Dasselbe im zweiten bei Add To Inventory.


    Wenn du jetzt das Spiel startest, kannst du den Code Schritt für Schritt ausführen.


    Gruss

    Hey zusammen


    Du kannst einfach einen Patch erstellen und diesen dann verteilen ohne, dass du das komplette Spiel neue verteilen musst. Wenn ich Geloscht richtig verstanden hat, hat er einfach das ganze Spiel wieder versendet. Das ist dann halt gleich gross, bei kleinen Spielen kein Problem, bei grösseren schon. Man stelle sich ein Flight Simulator vor und bei jedem Patch das komplette Spiel neue herunterladen musst. Bei den 100 GB kann das je nachdem eine Weile dauern und die meisten Menschen stören sich ohnehin an Patches.

    Full Rebuild hat meines Wissens nichts mit Patching oder Verteilen zu tun, sondern lediglich ob es vorherige Builds nutzt um die Packaging Time zu verkürzen, wenns deaktiviert ist versteht sich. Beim developen cool, für Shipping eher nicht.


    Ein Patch ist sehr viel kleiner und erstellt hast du den ja schon.

    Also nach meinem Wissen und Verständnis musst du den einfach noch in den richtigen Folder ziehen, auf Windows gemäss Doks [ProjectName]\Releases[VersionNumber][PlatformName]. Wenn das ein "echtes" Projekt ist solltest du da irgendein Installer machen, der das halt verschiebt. Geht auch relativ simpel. Nach dem Verschieben wird der Patch automatisch gemountet, da musst du nichts mehr machen. Also nur kopieren, das war's.


    Der Vorteil ist, dass der Patch viel kleiner ist.


    Gruss

    Hallo


    Ich habe leider nicht verstanden was dein Ziel ist. Wenn du einfach nur die Kamera rotieren möchtest musst du nichts Casten.

    Du hast ja den Springarm und daran hängt die Kamera. Cameraboom ist nur ein Name, es ist und bleibt ein Springarm. Du kannst die Komponente nennen wie immer du willst. Wenn du diesen Springarms mit dem Namen Cameraboom nun rotierst, rotiert auch die Kamera, weil die hängt da dran. Den zu rotieren ist ganz einfach.



    Wenn du jetzt X drückst rotiert die Camera um 90 Grad.


    Ich vermute allerdings du hast das Thridperson als Projekt Grundlage verwendet. Dort gibts schon einiges an Code.

    Namentlich das rotieren über die Maus und es hat UsePawnControlRotation aktiviert. Das musst du deaktivieren oder du kannst nur über den Controller rotieren. Das geht ganz einfach bei den Details vom SpringArm (CameraBoom).


    Wenn du die Kamera per Trigger Box rotieren möchtest, kannst du das obige in eine Funktion packen.

    Vermutlich wolltest du hier Casten und das macht auch Sinn. Also Cast auf den ThirdpersonCharacter und dann deine Funktion aufrufen.


    Klingt komplizierter als es ist :)

    Hallo


    Im Grunde machen die dasselbe. Das erste if macht das Implizit per Boolean conversion. Bedeutet beim ersten wird ein nullptr einfach zu false.


    Was jetzt besser ist darfst du selbst entscheiden.

    Der Grund dafür ist wohl, dass das später eingeführt worden ist mit dem impliziten Boolean conversion. Die Sprache entwickelt sich ja auch immer weiter.


    // Edit: Oops Nicht genau genug gelesen :/. Dachte du meintest den Unterschied zwischen:

    Code
    if(EquippedWeapon){
    }
    und 
    if(EquippedWeapon != nullptr) {
    }

    Bei deiner eigentlichen Frage bin ich bei Tomarr. Manche bevorzugen das erste andere das Zweite.

    Diskutiert wird aber eher die Lesbarkeit.


    Gruss

    Hallo freezernick

    Dein Link zeigt die direkte Initalisierung die ich schon gepostet habe. Das kennen wir. Also:

    Code
        bool bAiming1(false);
    Oder 
        bool bAiming2{false};

    Was wir allerdings nicht kennen ist eure Methode. Die wir nur als Funktionsaufruf kennen und bei uns auch nicht kompiliert.

    Also deine 2 und 3 Variante:

    C++
    bAiming = false;
    bAiming(false);
    bAiming{false}

    Das sind alles Wege, um Variablen zu initialisieren.


    Mehr dazu hier:

    https://www.educative.io/edpre…riable-with-braces-in-cpp

    Ich habe wirklich keine Ahnung wie ihr das zum komplieren bringt. Genau dieser Code kompiliert bei dir?


    Edit:

    Dein Beispiel funktioniert auf der Webseite die du gepostet hast auch nicht:

    Code
    main.cpp:7:16: error: ‘bAiming’ cannot be used as a function
       bAiming(false);
                    ^
    main.cpp:8:10: error: expected ‘;’ before ‘{’ token
       bAiming{false};

    Könnte es sein das Ihr das einfach verwechselt und die direkte Initialisierung meint?

    Ich habe nach mehr Code gefragt weil das von mir aus nicht funktionieren sollte. Und bei mir funktioniert dein Code auch nicht, es gibt einen Kompilierungsfehler. Genau dieser Code kompliert bei dir?


    Ich kenne die direkte initialisierung etwa:

    Code
        bool bAiming1(false);
    Oder 
        bool bAiming2{false};

    Nutzt du irgendwelche Makros die dir Getter und Setter generieren oder sonst was?

    Ansonsten freue ich mich drauf wenn das jemand beantwortet, dann kann ich auch etwas dazulernen.

    Du könntest vermutlich den Component einfach austauschen.

    Aber das müsste ja mit den Forces synchronisiert werden. Egal ob mit Materials oder ABC.

    Hast du das denn irgendwo mal gesehen? Bestimmt möglich aber sicher aufwändig.

    Ich sehe eingentlich Particles eher wie beim Video von Faba, jede Menge davon aber nicht die höchste quali, cooler Effekt.

    Aber ansonsten läuft dir hin und wieder eine Ratte über den Weg und das wird die Performance ja nicht killen.