Registriert: Di Feb 13, 2018 19:02 Beiträge: 24
Programmiersprache: Java
Hallo,
ich arbeite gerade an einem Android-Game (mit Java / OpenGL ES 2.0). Wenn ich im Spiel, bzw. in OpenGL Objekte verschiebe, dann ruckeln diese Objekte immer wieder, in regelmässigen Abständen.
Und unabhängig davon: Im Video fällt auf, dass die Qualle sich nicht synchron mit der Kamera bewegt, obwohl scheinbar beabsichtigt ist, dass die Qualle immer in der Mitte des Bildes sein soll. Daher lohnt es sich wahrscheinlich, anzuschauen, wo sich der Code zur Bewegung der Kamera vom Code zur Bewegung der Qualle unterscheiden.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
15-22 ms sind grundsätzlich kurz genug, um die Illusion einer flüssigen Bewegung aufrechtzuerhalten. Möglicherweise hast du es aber mit Mikrorucklern zu tun. Diese treten auf, wenn die Zeit zweier aufeinander folgender Frames sehr unterschiedlich ist. Dies kann z.B. dadurch passieren, dass die Java-Runtime plötzlich auf die Idee kommt, Speicher aufzuräumen (dazu muss sie das Programm kurz anhalten) oder dadurch, dass das Programm auf das Display wartet, dass sich mit fester Frequenz aktualisiert (nur wenn V-Sync an ist).
Die von dir verwendete Klasse GLSurfaceView ist mir nicht bekannt. Hat der Rendermode etwas mit V-Sync zu tun oder was macht der?
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Di Feb 13, 2018 19:02 Beiträge: 24
Programmiersprache: Java
Für setRenderMode gibt es zwei Konstanten "RENDERMODE_CONTINUOUSLY" und "RENDERMODE_WHEN_DIRTY".
- Bei RENDERMODE_CONTINUOUSLY wird onDrawFrame() immer wieder aufgerufen, so zusagen in Endlosschleife. - Bei RENDERMODE_WHEN_DIRTY wird onDrawFrame() nur dann ausgeführt, wenn die Anweisung durch glSurfaceView.requestRender(); gegeben wird.
Die Zeit zwischen den Frames ist immer relativ konstant, sie liegt in der Regel zwischen 16-19ms. Grössere Ausschläge, wie z.B. 200ms gibt es nicht. Das kan ich ausschliessen.
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Naja, die Millisekunden misst du doch in deinem Programm, oder? Falls der Grafiktreiber im Hintergrund Triple-Buffering betreibt, unterscheidet sich die Ausgabe des Displays zeitlich von der Frame-Fertigstellung deines Programms. Das sollte dann aber zu keinen allzu krassen Mikrorucklern führen.
Interessant zu wissen wäre noch, ob bei dir nur bestimmte Objekte ruckeln oder ob es das ganze Bild in gleicher Weise betrifft.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2622 Wohnort: Berlin
Programmiersprache: Go, C/C++
Es wäre praktisch die Spikes zu tracken. Meine erste Vermutung ist sehr einfach. Der Garbage Collector tut I'm Hintergrund aufräumen und dafür hält er alle threads an. Je nach dem, wieviel Dreck anfällt hast du Dan alle paar Sekunden ein frame mit z.b. 30ms und dann spielt die Art der time based Funktion eine große Rolle, weil die eventuell über kompensiert. Es kann auch passieren, dass du 1000fps hast und alle 2s Dan ein frame auf 120ms rutscht. Da hab ich mir in C# mit dem GC schon öfter ein Kampf geliefert. Die erste Lösung wäre den GC jeden Frame, als letztes auf zu rufen. Damit verteilt sich die last des GC auf jeden frame, statt auf einen, alle paar Sekunden. Ist es der GC und der brauch immer noch zu lange, dann muss man mit nem diagnostik Tool die Gründe für den garbage suchen und den Teil umschreiben. Ein Kumpel von hatte da diverse Basis Klassen angepasst, damit sein game gar kein garbage mehr wirft und somit frei vom GC war. Das ist der Hauptgrund für C++ in der game Industrie, gegenüber c# und Java. Unity hat sämtlichen engine code in c++ geschrieben und benutzen im high level c# code ausschließlich eigene Klassen mit Caches,um die Grundlast gering zu halten und stabile frame Zeiten zu bekommen. Ein mieses UI plugin, welches die text Werte jeden Frame neu zusammen Schuster und es ist vorbei.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Di Feb 13, 2018 19:02 Beiträge: 24
Programmiersprache: Java
Das Problem scheint der Garbage Collector zu sein. onDrawFrame() braucht für einen Durchlauf durchschnittlich 17ms, was absolut in Ordnung ist. Dazwischen gibt es jedoch immer wieder Sprünge auf bis zu fast 50ms. Und daher kommt auch das regelmässige ruckeln beim Verschieben. Es tritt so ca. 1x pro Sekunde auf.
Ich rufe jetzt am Ende von onDrawFrame() den Garbage Collector manuell auf. Dadurch wurde das ganze ein wenig besser. Die Sprünge sind aber immer noch bei ca. 40ms.
Was kann ich da noch machen? Bin total verzweifelt. Muss ich mich jetzt auch noch in C++ einarbeiten????
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Wie TAK schon geschrieben hat, kannst du auch schauen, an welchen Stellen dein Programm "Garbage" verursacht und versuchen, das zu vermeiden. Immer, wenn du irgendwo einer Referenz eine neue Speicheradresse zuweist, verwaist die alte*. Immer wenn eine Referenz zerstört wird, weil das Programm ihren Scope verlässt, verwaist der Speicherbereich, auf den sie zeigt*. Das kann man versuchen zu vermeiden und dem Garbage Colloector dadurch etwas Aufräumarbeit ersparen. Bestimmt gibt es Tools, die dein Programm analysieren und dir die entscheidenden Stellen im Code aufzeigen können. Da kenne ich mich aber nicht aus.
*vorausgesetzt, es gibt keine zweite Referenz die auch dorthin zeigt
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2622 Wohnort: Berlin
Programmiersprache: Go, C/C++
Das schöne ist, du hast mit Java da die besser unterstützte Sprache, im vergleich zu C#. Es gibt diverse Tools und Boardmittel um sich dinge genauer an zu gucken. Ich hab mal kurz gegoogelt und folgendes gefunden. Java GC monitoring
Was du suchst ist ein GC Profiler, Tracer oder Monitoring, welches dir sagt was der GC denn eigentlich macht. Da du 16-17ms Intervalle hast, vermutlich durch VSync, bedeutet es, du hast 60 Durchläufe deines Codes pro Sekunde. Solltest du z.B. ein Statistik Screen rendern, welcher jeden Frame die Strings neu baut, statt diese einmal in einer Klasse zu behalten und diese nur an zu passen, dann erzeugst du halt für jede String operation das 60zig fache an Objekten pro Sekunde. Also line[i]="Player "+i.ToString()+" ("+players[i].Name+")"+" "+players[i].Points.ToString(); für 10 Spieler würde pro GC Aufruf zu 10*60*4=2400 String Objekte führen, die er weg räumen muss, auch nur, wenn er so klever war die statischen Strings global an zu legen und für das zusammen fügen keine temporären instanzen an zu legen, sonnst wird es noch schlimmer. Der GC von Java ist extrem gut optimiert aber selbst bei vielen Tausend Objekten trifft dann Random Access und cold cache zu, was den GC nicht auf CPU sondern Speicher Geschwindigkeit limitiert.
Also keine Panik, du brauchst kein C++ um das Problem zu lösen, vor dir haben auch schon diverse andere Entwickler erfolgreich mit Java komplexe 3D Spiele geschrieben. Es braucht nur mehr Zeit bei der Speicherverwaltung, im Vergleich zu C++ aber man spart ja unmengen an Zeit bei diversen anderen Bereichen.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Mitglieder in diesem Forum: Bing [Bot] und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.