Das G3-HUD steht im Spiel; die Abnahme (U3D) folgt. - U3B: alle Bereiche und Komponenten aus Godot übertragen (LuneHud, Lanes, Bossgrotte, nächste Welle, Kaufkarten, Armee, Held mit Items und Talenten, Angriffschampions, Team, Ereignisse, Minimap, Tooltip, Optionen, Partieende). Porträts aus den echten Modellen, einmal gerendert. - Offene G3-Punkte umgesetzt: „1 WELLE“ als Band am Porträtrand, Schadens- und Rüstungssymbole auf den Karten, Armeewert, Heldenporträts auf der Minimap. Befehlsplatz für die Ultimates der geplanten Helden reserviert (verborgen). - U3C: LuneGame verdrahtet Befehle (gleiche Schnittstelle wie die Bots), Bereit mit 1-s-Sperre nach dem Kampf, Tempo und Pause, Tasten wie in G3, Kamera-Ziele, Auswahl im Feld, Planungsvorschau und Aufstellungsflächen. Ersetzt die U2-Debug-Anzeige. Bot-Partien und Benchmark unverändert. - Szenen- und Bibliotheksbauer idempotent: Animator-Controller und Post-Processing-Profil werden an Ort und Stelle aktualisiert. Die Szene bekommt bei jedem Bau neue Objekt-IDs, der Inhalt ist gleich. - Prüfung (Port von verify_g3, Teile A–H): 699 Prüfungen ohne Fehler. EditMode 23/23, PlayMode 12/12, Fingerabdrücke der Bot-Partien unverändert (DCE95C96556F3A1A, 7B8E43AEFC0D60C5). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
74 lines
3.9 KiB
C#
74 lines
3.9 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Luneraria.Core;
|
|
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
|
|
namespace Luneraria.View.Tests
|
|
{
|
|
/// <summary>
|
|
/// U2C in the real scene: the bot match of seed 2 runs with every view attached while the
|
|
/// player loop runs at 30, 60, 120 FPS and unlimited (Application.targetFrameRate, VSync off).
|
|
/// Each run must reproduce the core's fingerprint. The measured frame rates show that the
|
|
/// frame timing really differed. Writes docs/port/logs/u2c/scene-frame-rates.json.
|
|
/// </summary>
|
|
public sealed class SceneFrameRateTests
|
|
{
|
|
const float Speed = 24f;
|
|
|
|
[UnityTest]
|
|
public IEnumerator SceneMatchIsTheSameAtRealFrameRates()
|
|
{
|
|
var options = new MatchOptions { Seed = 2, HumanSlot = -1 };
|
|
LuneTrace core = LuneTrace.RunCore(options, 1, 0, "");
|
|
var report = new StringBuilder("{\n \"match\": \"seed 2, bots, speed " + Speed + "x\",\n \"core_hash\": \"" + core.Hash.ToString("X16") + "\",\n \"core_steps\": " + core.Steps + ",\n \"runs\": [\n");
|
|
var failures = new List<string>();
|
|
int[] rates = { 30, 60, 120, -1 };
|
|
for (int index = 0; index < rates.Length; index++)
|
|
{
|
|
QualitySettings.vSyncCount = 0;
|
|
Application.targetFrameRate = rates[index];
|
|
yield return PlayModeSupport.Load();
|
|
var driver = Object.FindAnyObjectByType<LuneMatchDriver>();
|
|
driver.HumanSlot = -1;
|
|
driver.Seed = 2;
|
|
driver.StartRound = 1;
|
|
driver.ExtraGold = 0;
|
|
driver.Speed = Speed;
|
|
driver.Restart();
|
|
driver.Runner.PlanningSeconds = .5;
|
|
driver.Runner.SettledSeconds = .5;
|
|
var rig = Object.FindAnyObjectByType<LuneCameraRig>();
|
|
rig.Interactive = false;
|
|
rig.LookAt(new Vec2(0, 0), 60f, true);
|
|
float start = Time.realtimeSinceStartup;
|
|
int frames = 0;
|
|
int maxSteps = 0;
|
|
while (driver.Runner.Current != LuneMatchRunner.Stage.Over && Time.realtimeSinceStartup - start < 600f)
|
|
{
|
|
yield return null;
|
|
frames++;
|
|
maxSteps = Mathf.Max(maxSteps, driver.Runner.StepsThisFrame);
|
|
}
|
|
float seconds = Time.realtimeSinceStartup - start;
|
|
LuneTrace trace = driver.Runner.Trace;
|
|
string label = rates[index] > 0 ? rates[index] + " fps" : "unlimited";
|
|
bool same = trace.Hash == core.Hash && trace.Steps == core.Steps;
|
|
if (!same)
|
|
failures.Add(label + ": " + trace.Hash.ToString("X16") + " / " + trace.Steps + " steps");
|
|
Debug.Log(string.Format("LUNE_SCENE_FPS {0}: {1} frames in {2:0.0} s = {3:0.0} fps, up to {4} steps per frame, hash {5:X16}, same={6}", label, frames, seconds, frames / seconds, maxSteps, trace.Hash, same));
|
|
report.AppendFormat(" {{\"target\": \"{0}\", \"frames\": {1}, \"seconds\": {2}, \"measured_fps\": {3}, \"max_steps_per_frame\": {4}, \"steps\": {5}, \"hash\": \"{6:X16}\", \"winner\": {7}, \"same_as_core\": {8}}}{9}\n",
|
|
label, frames, PlayModeSupport.Number(seconds), PlayModeSupport.Number(frames / seconds), maxSteps, trace.Steps, trace.Hash, driver.Runner.Match.Winner, same ? "true" : "false", index < rates.Length - 1 ? "," : "");
|
|
}
|
|
Application.targetFrameRate = -1;
|
|
report.Append(" ]\n}\n");
|
|
string logs = PlayModeSupport.Evidence("logs", "u2c");
|
|
Directory.CreateDirectory(logs);
|
|
File.WriteAllText(Path.Combine(logs, "scene-frame-rates.json"), report.ToString());
|
|
Assert.IsEmpty(failures, string.Join("\n", failures));
|
|
}
|
|
}
|
|
}
|