Ich entwickle ein auf Unity basierendes 3D-Visualisierungstool für WebGL. Der Benutzer interagiert selten mit der 3D-Szene und wenn er dies tut, geht es nur darum, die Kamera wie das Drehen oder Zoomen der Ansicht anzupassen. Ich habe vSync ( QualitySettings.vSyncCount
) deaktiviert und die Bildrate auf 30 ( Application.targetFrameRate
) gesperrt , um die CPU-Auslastung mindestens ein wenig zu reduzieren, während die Benutzer beim Bewegen der Kamera immer noch eine akzeptable Reaktionsfähigkeit aufweisen. Mit 30 fps bekomme ich eine CPU-Auslastung von ca. 30%. In Anbetracht der Hardware der unteren Preisklasse scheint dies immer noch zu hoch zu sein.
Um die CPU-Auslastung weiter zu verringern, habe ich zwei "Modi" eingeführt:
- Interaktiv: Läuft mit 30 fps
- Leerlauf: Läuft mit 10 fps
Ich habe einige Codezeilen geschrieben, um je nach Benutzerinteraktion zwischen diesen Modi zu wechseln. Wenn also eine Eingabe erkannt wird, verwendet die Anwendung mehr fps und nach einer bestimmten Zeit ohne Interaktion verwendet die Anwendung wieder weniger fps. Bisher funktioniert es ziemlich gut: Die App verwendet 30% im interaktiven Modus und 8% bis 10% der CPU im Leerlaufmodus.
Wenn Sie die Leerlaufbildrate auf 1 setzen, wird die CPU-Auslastung im Leerlaufmodus auf 1,5% reduziert. Das ist wirklich toll. Aber wie erwartet gibt es ein Problem. Grundsätzlich habe ich alle Update()
Methoden gesperrt, die nur einmal pro Sekunde aufgerufen werden sollen. Wenn der Benutzer mit der Kamera interagiert, wird das Ereignis mit einer erwarteten Verzögerung von etwa einer Sekunde verarbeitet.
Nun die Frage: Wie kann ich Benutzereingaben sofort erkennen, während die Anwendung mit einer niedrigen Bildrate ausgeführt wird, und auch sofort eine neue Bildrate (z. B. 30) ohne merkliche Verzögerung anwenden?
Ursprünglich wollte ich eine Art On-Demand-Rendering haben. Ich habe einige Beiträge darüber gelesen, wie Benutzer eine Textur rendern, um die Renderkosten in weniger interaktiven Szenen zu senken. Das dynamische Einstellen der Bildrate scheint meiner Meinung nach eine sauberere Lösung zu sein. Ich habe auch versucht, mit dieser FixedUpdate()
Methode nach Eingaben zu suchen und in den interaktiven Modus zu wechseln, aber das hat auch nicht funktioniert.
Hinweis Erwähnenswert ist auch, dass dieser Ansatz Fehler im Browser erzeugt, die darauf hinweisen, dass die Framerate der Anwendung 0 sein sollte (nicht in Bezug auf die Zielframerate von Unity, sondern wie in "Lassen Sie den Browser die Framerate verarbeiten" ). Obwohl dies eine andere Frage sein könnte, bezieht sie sich immer noch auf dieses Thema. Vielleicht hat auch jemand eine Antwort darauf!
Bearbeiten 1
Wie in den Kommentaren unten erwähnt, stellt Unity die Rückrufe bereit MonoBehaviour.OnApplicationPause
und MonoBehaviour.OnApplicationFocus
erkennt, ob die Anwendung den Fokus erhalten oder verlieren wird.
Das Problem ist jedoch folgendes: Meine Anwendung verliert fast nie den Fokus. Dies ist zwar eine nette zusätzliche Optimierung, aber es hilft mir nicht wirklich viel. Mein Problem ist, dass die App die meiste Zeit im Leerlauf ist und gleichzeitig den Fokus hat. Es ist wirklich nur der Benutzer, der die meiste Zeit am Fenster starrt.
Nur um etwas mehr Sinn zu machen: Ich ziele auf WebGL ab. Der einzige Zweck von Unity besteht darin, einige Dinge zu visualisieren, während der Benutzer hauptsächlich mit einigen HTML-Steuerelementen interagiert. Im seltenen Fall , dass er mit der 3D - Szene zu interagieren will, möchte ich die Framerate einstellen sagen 30. Die Idee ist , „Ich weiß nicht , die Szene neu rendern zu oft so lange , wie Sie dies nicht tun interact“ .
Hervorheben: In meinem relevantesten Anwendungsfall verliert die Anwendung nie den Fokus. Dies bedeutet, dass der einzige zuverlässige Indikator, der bestimmt, wann zwischen Bildratenprofilen gewechselt werden muss, auf Benutzereingaben basiert.
Tut mir leid, wenn mir das nicht klar war :)
Bearbeiten 2
Ich habe dieses Thema auf der Unity-Feedback-Seite veröffentlicht . Wenn Sie interessiert sind, probieren Sie es aus und hinterlassen Sie eine Stimme. Vielleicht erhält diese Anfrage genug Aufmerksamkeit, um von den Unity-Entwicklern unterstützt zu werden.
quelle
Antworten:
Ich denke, Render to Texture ist immer noch die beste Wahl. Wenn Sie einen "Screenshot" von dem gemacht haben, was die Kamera sieht, und nur diese Textur anzeigen, sollten die Renderkosten selbst bei 30 Bildern pro Sekunde günstig sein.
quelle
Also dachte ich darüber nach, was wäre, wenn Sie die Kamera einfach daran hindern würden, erneut zu rendern (ohne die Kamera zu deaktivieren), wenn der Benutzer stationär ist? Auf diese Weise können Sie die
Update
Funktion immer noch häufig aufrufen, sodass die Benutzereingaben weiterhin reagieren, das Gerät jedoch keinen hohen Ressourcenverbrauch aufweist. Nach einer kurzen Suche fand ich dies . Ich habe es noch nicht ausprobiert, es ist nur eine Idee, die Sie ausprobieren könnten.quelle