Beiträge von Tropid

    Das Fenster "window" ist nicht null und auch window.frame ist an der Stelle nicht null, sonst würde eine NullPointerException fliegen. Es wird im Konstruktor der Klasse "Hauptfenster" initialisiert, der beim Erzeugen des Objekts "window" aufgerufen wird. Und zwar in der initialize() Methode, woran auch nichts falsch ist.


    Das Problem liegt daran, dass du JFrame nur in der Main-Methode fahren kannst.


    Ebenso kannst du JFrames erzeugen wo du willst. Es gibt keinen zwingenden Grund diese in der main() Methode anzulegen. main() ist eine Methode wie jede andere, außer dass sie der Einstiegspunkt für das Programm ist. Der Aufruf von EventQueue.inokeLater() erzwingt, dass das Fenster im EDT (Event-Dispatch Thread) von Swing erzeugt wird. Alle Zugriffe auf GUI Komponenten müssen aus diesem Thread erfolgen, da Swing nicht threadsafe ist. Ob es unbedingt notwendig ist weiß ich im Moment nicht, da schau ich gleich mal nach.


    Lösung
    Ich bin mir nach wie vor zu 95% sicher, dass dein Problem von den Pipes '|' verursacht wird. Das ist ein Shell Feature, welches in Java nicht vorhanden sein muss. Also:
    a) Schreibe eine kleine Skriptdatei, die du stattdessen ausführst.
    b) Starte eine Shell (z.B. bash) und übergib der Shell deinen Befehl mit Pipes.

    Ich wäre mit pipes vorsichtig. Ich weiß nicht wie Java da drauf reagiert. Versuche mal den Befehl in eine ausführbare Datei zu schreiben und dann nur diese Datei auszuführen.


    Der Java Code ist in Ordnung an dieser Stelle (auch wenn sich die Frage stellt ob eine komplett Java Lösung nicht eleganter wäre, als die Linux Shell zu bemühen).

    Zuallererst musst du natürlich testen ob du in Reichweite stehst. Am besten misst du dazu die Distanz vom Schulterknochen zum Hebel.
    Danach greift ein Verfahren, dass sich "Inverse Kinematik" nennt. Üblicherweise werden bei Animationen zu jedem Gelenk die Drehwinkel gespeichert um das Skelett zu verformen ("direkte Kinematik"). Bei der inversen Kinematik werden diese Drehwinkel aus der gewünschten Zielposition eines Knochens bestimmt (der Hand in deinem Fall). Das ganze Verfahren kommt ursprünglich aus der Robotik. Unterstützung von der Unreal Engine ist vorhanden.


    Ein ähnliches Beispiel findest du in den "Content Examples". Dort schlägt ein Charakter in die Luft und wenn ein Hindernis getroffen wird führt er den Schlag nur bis zum Hindernis aus (siehe UE Dokumentation unten).


    Siehe hier:
    https://de.wikipedia.org/wiki/Inverse_Kinematik
    https://docs.unrealengine.com/…ation/IKSetups/index.html

    Hallo Harlyk,


    Ja stimmt der erste Satz triffts, der zweite den ich zitiert habe passt dann nicht mehr ganz dazu. Ich habe auch kaum Erfahrung mit Unity, es gibt aber durchaus die Variante die DeltaTime konstant zu halten um Bugs durch die unterschiedlichen Werte zu verhindern (v.a. in Extrembereichen nahe 0 oder sehr hohen Werten). Daher war ich mir nicht sicher, ob du nicht vielleicht das erwartet hast.


    In dem Fall fällt mir aber leider auch nichts dazu ein. Gerade die Explosionen sollten sich durchaus gleich verhalten.


    Durch die erhöhte Framerate kommen mehr Ticks durch denn Ticks sind ja durchgänge per Frame und das bedeutet irgendwas läuft schneller.


    Nicht ganz, Ticks und Frames werden üblicherweise synonym gebraucht. Innerhalb einer Sekunde wird eine gewisse Anzahl an Ticks (oder Frames) ausgeführt, je nachdem wie schnell das Spiel läuft. Wenn du also nicht die vergangene Zeit (DeltaTime) berücksichtigst ist die Geschwindigkeit des Spiels abhängig von deiner FPS Zahl. Trotzdem entspricht 1 Frame = 1 Tick.


    die sorgt dafür das eine gleichbleibende Anzahl von Ticks in einer definierten Zeit durchgeführt werden.


    Die Anzahl der Ticks bleibt nicht gleich. Es werden mehr oder weniger Ticks abhängig von deinen FPS. Deswegen musst du den Effekt mit Hilfe der DeltaTime ausgleichen. Stell dir vor du willst ein Auto um 100 Einheiten pro Sekunde bewegen. Das bedeutet in deiner Tick Methode bewegst du es um 100 * DeltaTime. Wenn das Spiel nun ganz langsam läuft und deine DeltaTime einer Sekunde entspricht entsteht dadurch eine Bewegung von 100 Einheiten (100 * 1.0). Wenn zwei Ticks in der Sekunde ausgeführt werden wird das Auto um 50 Einheiten pro Tick bewegt (100 * 0.5), bei 30 FPS um 3,34 Einheiten (100 * 1/30).


    jedoch zweifel ich ob es was bei den Explosionen bringt


    Für Explosionen verwendest du einen Impuls. Dieser überträgt seine gesamte Kraft auf einmal und ist somit nicht abhängig von der DeltaTime.


    irgendwie nicht schlau draus geworden bin wie dies in UE4 umgesetzt wird


    Die Umsetzung ist ziemlich simpel. Die AActor::Tick Methode wird mit einem float DeltaTime aufgerufen. Dieser entspricht ungefähr dem Wert, den der Frame/Tick braucht. Also bei einer FPS Zahl von 60 entspricht das ca. 16,7ms (1/60). Das verwendest du wie in dem Auto Beispiel oben.

    Eine "Force" in der Unreal Engine entspricht einer konstanten Kraft, muss also jeden Tick angewandt werden. Dementsprechend muss die "Force" auch mit der geschätzten Zeit, die der Frame benötigt (DeltaTime) verrechnet werden. Wenn du also den Wert für deine "Force" in "Force" pro Sekunde angibst, musst du den Wert einfach mit der DeltaTime multiplizieren.


    Im Gegensatz dazu würde ein Impuls die ganze Kraft auf einmal an ein Objekt abgeben.

    Ich muss mich leicht korrigieren. Du benötigst nicht zwingend "EditAnywhere" an deiner C++ SphereComponent sondern "VisibleAnywhere" und "BlueprintReadOnly" reichen ebenfalls aus. Diese Eigenschaften beziehen sich auf die Komponenten selbst und nicht auf die Eigenschaften der Komponenten. Somit ist "EditAnywhere" übertrieben.


    Dieses Beispiel funktioniert für mich problemlos:


    Actor Header

    Code
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Test")
    UStaticMeshComponent* Mesh;
    
    
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Test")
    USphereComponent* TriggerSphere;


    Actor Konstruktor

    Code
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
    
    
    TriggerSphere = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger"));
    TriggerSphere->AttachParent = Mesh;
    
    
    RootComponent = Mesh;

    Bei Blueprints kann ich leider nur bedingt Auskunft geben. Mein Ansatz wäre folgender:


    Der Client kann in seinen Optionen einen Namen setzen, der in seiner GameInstance gespeichert wird. Wenn er sich nun zu einem Server verbindet teilt er ihm nach dem Verbinden über ein "Server Event" (Event, dass auf dem Server ausgeführt wird) seinen Namen mit. Der Server speichert diesen Namen in dem zugehörigen PlayerState Objekt des Spielers, damit der Name auch zu allen anderen Spielern repliziert werden kann. (Voraussetzung dabei ist, dass die GameInstance eines Clients beim Verbinden zu einem Server nicht zurückgesetzt wird)


    Um das ganze in C++ zu machen gehst du folgendermaßen vor:


    Verbinde zu dem Server mit einer URL: "127.0.0.1:7777?PlayerName=<name>"


    1) Erzeuge eine Klasse für deinen eigenen GameMode
    2) Überschreibe die Methode "InitNewPlayer"
    3) Diese Methode erhält die Verbindungsparameter als String "Options"
    4) Lies den Namen des Clients folgendermaßen aus:


    Code
    FString PlayerName = UGameplayStatics::ParseOption(Options, TEXT("PlayerName"));


    5) Speichere den Namen im PlayerState Objekt des Spielers und repliziere diese Eigenschaft zu allen Clients.


    Wenn du das in Blueprints auf dem selben Weg schaffst wäre das zu bevorzugen.


    Siehe:
    Dokumentation - APlayerController::ClientTravel
    Dokumentation - AGameMode::InitNewPlayer
    Wiki - Passing arguments to server during connection


    EDIT:
    Beachte auch, dass es bereits eine Eigenschaft "PlayerName" in dem PlayerState Objekt gibt. Unter Umständen reicht dir dieser Name aus. Bei Steam oder anderen OnlineSubSystemen entspricht der Name üblicherweise dem Anzeigenamen (dein Steam Name). Wenn du ohne Steam o.Ä. spielst wird aktuell der Hostname deines PCs mit einer zufällig generierten ID am Ende verwendet.

    Zitat von xyt4n

    Dieses Projekt ist ziemlich wichtig und es wäre schade, wenn das Unternehmen für das ich arbeite, auf Unity verharren muss und Verluste macht.


    Zitat von xyt4n

    Ich weiß das es experimentell ist, aber viele sagen ja, dass es funktioniert.


    Diese beiden Aussagen deuten darauf hin, dass du vor hast diese Videotexturen in einer produktiven Umgebung zu verwenden. Und das ist einfach nicht zu empfehlen. Es gibt keine Garantie, dass jede Videodatei abgespielt werden kann oder dass auf jedem System alles funktioniert. Zudem können jederzeit Änderungen kommen, die inkompatibel zum aktuellen Stand sind. Aus diesem Grund hab ich nochmal explizit erwähnt, dass das Feature experimentell ist.


    Um daran anzuknüpfen schau dir doch nochmal die Dokumentation etwas genauer an:

    Zitat

    While the Windows plug-in is the most complete, it has issues with certain movie formats, such as H.264 encoded .mp4 files.


    Achte auch mal auf die Infobox im Abschnitt "MediaTexture Asset".


    Zu deinem Problem:
    1) Verwende eine einfache Datei, wie z.B. die Wildlife.wmv Videodatei die oft bei Windows dabei war (funktioniert bei mir)
    2) Starte das Video im Level BP oder wo auch immer. Wichtig ist, dass du die Methode "Play" auf einem Media Player Objekt aufrufst, dem du dein MediaPlayerAsset übergibst (Siehe Bild im Anhang). Andernfalls bleibt das Bild schwarz.

    Halbwegs professionelles Arbeiten ohne Versionskontrolle ist nicht realistisch. In der Einleitung zu git wird das bestimmt ganz gut erklärt. Einfach gesagt kann man damit "Savegames" von seinem Projekt machen, so dass man wieder zu alten Versionen zurückkehren kann, oder abgleichen was sich geändert hat.
    Spätestens wenn man mit anderen Leuten zusammen arbeitet, kommt man daran nicht mehr vorbei. Meistens wird dort ein zentrales "Repository" mit dem Projekt angelegt und alle Beteiligten laden sich den aktuellsten Stand herunter. Dann können sie an diesem Stand arbeiten und wenn sie eine Aufgabe erledigt haben (z.B. Beheben eines Bugs) können sie die Arbeit "committen". Das bedeutet die Änderungen gehen in das zentrale Repository über und alle anderen Teammitglieder können ihren Stand wieder mit dem zentralen Stand synchronisieren.


    Üblicherweise wird zur Versionsverwaltung für die Unreal Engine Perforce empfohlen. Soweit ich weiß verwendet auch Epic Perforce (Github/Git wird nur zum veröffentlichen des Source Codes verwendet). Git ist leider nur bedingt zu empfehlen (ich bin ein großer Freund von git). Git ist großartig wenn es um Projekte mit Source Code geht, ist aber nicht für Projekte mit einer großen Anzahl an Binärdateien geeignet (Assets wie Blueprints, Sounds, Animationen, Modelle, Texturen, Materialien, etc...). Das liegt daran, dass git ein dezentrales Versionsverwaltungssystem ist, welches nicht von einer permanenten Verbindung zum Server abhängt, sondern auch offline funktioniert. Das verhindert allerdings, dass Dateien gesperrt werden können (andere können diese Datei nicht bearbeiten). Und da kommen wir zu einem großen Vorteil von Perforce (SVN kann das auch, aber ich bin kein Freund von SVN). Perforce hält ständig Kontakt zu seinem Server und markiert alle Dateien in deinem lokalen Projektverzeichnis als "read-only". Um Dateien nun zu bearbeiten, teilt man dem Perforce Server mit an welchen Dateien man Änderungen vornehmen will und dieser testet dann ob diese Dateien bereits von jemand anderem gesperrt wurden. Ist dies der Fall muss man warten bis der andere damit fertig ist. Ohne diesen Test könnte es passieren, dass zwei Personen gleichzeitig an einem 3D Modell arbeiten und einer seine Änderungen danach verwerfen muss. Dies wird bei Perforce als "Exclusive Lock" Modus bezeichnet. Textdateien können weiterhin so eingestellt werden, dass sie gleichzeitig bearbeitetbar sind und dann "vereinigt" (Merge) werden können, was es erlaubt z.B. mehreren Programmierern an den selben C++ Dateien zu arbeiten (keine Blueprints!).


    Ein weiteres wichtiges Feature von Versionsverwaltung ist, das Projekt in mehrere Zweige zu unterteilen, die sich von dem Hauptprojekt abtrennen. Dies wird oft verwendet um nach Release einer Hauptversion noch Support dafür zu bieten. So können z.B. Sicherheitspatches auf eine alte Version angewendet werden ohne, dass man die neuen Features übernimmt (z.B. Android Sicherheitslücke wird entdeckt, einmal gepatcht und der Patch wird auch auf alte Android Versionen angewandt).
    Auch werden diese Zweige oft verwendet um experimentelle Features zu entwickeln. So kann das Entwicklungsteam auf dem experimentellen instabilen Zweig arbeiten während die kreativen Leute weiter mit der stabilen Version arbeiten können. Sobald die Entwickler dann zufrieden sind können sie die Zweige wieder zusammenführen.


    Es gibt auch noch viele weitere Vorteile von Versionsverwaltung, aber das würde hier den Rahmen sprengen.

    1) Video Texturen
    Das Feature ist nur als experimentell gekennzeichnet:


    https://answers.unrealengine.c…ia-texture-when-publ.html

    Zitat

    The Media Framework is not quite production ready yet and is still in the experimental stages. Some features may not work as expected, however we are currently working hard to resolve those issues as well as add addition features and support.


    Hier erwähnt einer vom Support auch noch ein experimentelles Plugin, dass auf VLC basiert welches in Zukunft mehr Möglichkeiten bereitstellen könnte.
    https://forums.unrealengine.co…-Texture-Resolution-Limit


    Lösung mit Unreal Engine 4.9
    Du solltest aber auf jeden Fall mal Version 4.9 testen. Dort kannst du einen relativen Pfad zu dem Video angeben, wenn du es in deinem Content/Movies Ordner ablegst. Beim Export wird dann das Video ebenfalls in dem entsprechendem Ordner kopiert. Und so funktioniert es bei mir auch.
    Für eine genaue Anleitung siehe bitte hier: https://docs.unrealengine.com/…MediaFramework/index.html


    Zusammengefasst bleibt es aber ein experimentelles Feature im Moment, weshalb du es momentan nicht in einer produktiven Umgebung verwenden kannst.



    2) Dynamisch Objekte laden
    Da kann ich dir leider nicht viel dazu sagen, aber der Prozess mit dem die Unreal Engine Daten in die Engine importiert ist relativ aufwändig. Es dürften viele Anpassungen in dieser Pipeline erledigt werden um die Datei in ein Format zu bringen, dass für die Engine benutzbar ist, da sind wahrscheinlich auch rechenintensivere Anpassungen dabei (vermute ich). Deswegen sieht es da wahrscheinlich eher schlecht aus das zur Laufzeit zu machen. Unter Umständen ist es möglich die Assets prozedural zu erzeugen, bzw Daten dazu von der Platte zu laden und daraus dynamisch ein Mesh zu generieren (sicher nicht trivial). Hierzu kann man dann gleich den neuen Asset Cache von der UE 4.9 verwenden (siehe "Runtime Asset Cache" in den Changenotes).
    Aber das sind nur meine Gedanken dazu. Eventuell geht es ja doch einfacher.

    Meshes aus 3D Programmen sind nicht nur performanter weil man mehr Kontrolle hat, sondern der Renderer kann auch einige starke Optimierungen vornehmen.


    Die Regel ist üblicherweise, du benutzt BSP um dein Level auszulegen und einen Prototyp zu bekommen und ersetzt danach nach und nach alles mit 3D Modellen.


    BSPs haben noch ein paar andere Nachteile, z.B. sind Kollisionen nicht wirklich konfigurierbar, aber für einfache Zwecke können sie durchaus ausreichend sein.

    Vergiss trotzdem nicht zu überprüfen ob überhaupt ein Spawner gefunden wird. Wenn kein Spawner im Level existiert wirst du einen NullPointer Fehler bekommen. Frage einfach die Länge des Arrays ab und wenn es <= 0 ist gib eine Warnung für die Entwickler aus, dass ein Spawner im Level platziert werden muss.

    Hallo Leute,


    Wenn ich eine deutsche Unreal Engine 4 Community suche finde ich recht schnell "unrealengine4.de". Wenn ich jedoch die Seite besuche sehe ich als erstes einen kurzen Artikel zu der Unreal Engine 4.1 (!). Das Forum wird als "[NEU]" angepriesen.


    Solange die News nicht gepflegt werden, würde ich vorschlagen die News und den Blog zu entfernen und das Forum möglichst direkt auf der Hauptseite zu platzieren. Ich vermute viele Leute sind erstmal abgeschreckt, wenn sie sehen, dass es seit 4.1 keine News mehr gab, obwohl das Forum eigentlich recht aktiv ist.

    Also auf deinem Bild ist keine Verknüpfung zwischen dem EnemySpawner und dem SetTimer Aufruf. Siehe im Anhang wie das ausschauen sollte (überprüfe am besten vor dem Get, ob überhaupt ein Enemy Spawner existiert, also ob die Länge des Arrays > 0 ist).


    Ich bin mit Blueprint Timern nicht so bewandert. Evtl finden BPs die Methode eines fremden Actors nicht (was ich mir allerdings nicht vorstellen kann). In diesem Fall kannst du eine Methode "SpawnEnemy" innerhalb des GameModes erstellen, der die "SpawnEnemy" Methode des Spawners aufruft.


    Was passiert denn wenn du einen Breakpoint setzt? Wird SpawnEnemy überhaupt aufgerufen?

    Wenn ich das beim Überfliegen richtig sehe versuchst du einen Timer zu erzeugen, der eine Methode "SpawnEnemy" aufrufen soll. Es ist allerdings nicht ersichtlich woher diese Methode kommt (du befindest dich im GameMode). Du musst den gefundenen EnemySpawner (der auch existieren muss im Level) mit dem SetTimer Knoten verbinden. Ansonsten wird er die Methode "SpawnEnemy" nicht finden, da diese zu dem EnemySpawner gehört.


    Zum Testen kannst du einen Breakpoint in der "SpawnEnemy" Methode setzen und schauen ob dieser aufgerufen wird.