champions-of-luneraria/Assets/Luneraria/View/LuneDebugOverlay.cs
Martin Stickelbroeck 3871b3e2e6 U2C Simulation/View Binding
Fester Simulationstakt und Ansichten, die nur lesen; Nachweis, dass die Partie
bei jeder Bildrate dieselbe ist.

- LuneClock: Akkumulator, ganze Schritte zu 0,05 s, Alpha zum Interpolieren.
- LuneMatchRunner: Host-Ablauf einer Bot-Partie (Planung über die
  Befehlsschnittstelle, Kampf im festen Takt, Abrechnung, nächste Runde);
  LuneMatchDriver reicht in Update nur Bildzeit weiter.
- LuneTrace: Fingerabdruck der Partie (jeder Schritt, jede Abrechnung) und der
  reine Kernlauf zum Vergleich.
- Ansichten: LuneMatchView, LuneUnitView (interpolierte Position, Blickrichtung,
  Clips aus Kampfereignissen, Teamring, Lebensbalken), LuneBuildingView mit
  Einsturz und Ruine aus den autoritativen HP, Turmblitze, LuneCameraRig wie
  lune_camera.gd, vorläufige Debug-Anzeige (kein HUD; U3 portiert das G3-HUD).
- Einheitenbibliothek: Kohlenbeißer aus 131 Teilen zu einem Mesh, Animator-
  Controller mit den Blender-Clips, Ring- und Balkenmeshes, Markermaterialien.
- Tests: EditMode (30/60/120 fps, unbegrenzt, Ruckler, 8x Tempo; Seed 2 und
  Seed 9 ab Runde 21) und PlayMode in der Szene bei echten Bildraten 30, 60,
  120 und unbegrenzt: überall derselbe Fingerabdruck wie der Kern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 17:31:18 +02:00

56 lines
2.5 KiB
C#

using System.Linq;
using System.Text;
using Luneraria.Core;
using UnityEngine;
namespace Luneraria.View
{
/// <summary>
/// Temporary match readout for U2 (round, phase, buildings, heroes, boss, winner). Not a HUD:
/// the G3 HUD is ported in U3 and replaces this overlay.
/// </summary>
public sealed class LuneDebugOverlay : MonoBehaviour
{
public LuneMatchDriver Driver;
GUIStyle _style;
GUIContent _content = new GUIContent();
float _next;
void OnGUI()
{
if (Driver == null || Driver.Runner == null)
return;
if (_style == null)
_style = new GUIStyle(GUI.skin.box) { alignment = TextAnchor.UpperLeft, fontSize = 15, wordWrap = true, padding = new RectOffset(10, 10, 8, 8) };
// Four refreshes a second: building the text every GUI pass produced garbage each frame.
if (Time.unscaledTime >= _next)
{
_content.text = Text(Driver.Runner);
_next = Time.unscaledTime + .25f;
}
GUI.Box(new Rect(12, 12, 430, 150), _content, _style);
}
public static string Text(LuneMatchRunner runner)
{
LuneMatch match = runner.Match;
var text = new StringBuilder();
text.AppendFormat("U2 Debug (kein HUD) · Runde {0} · {1}\n", match.RoundNumber, runner.Current);
for (int team = 0; team < 2; team++)
{
int towers = match.Map.Buildings.Count(b => b.Team == team && b.Tier != "core" && match.BuildingHp[b.Id] > 0.0);
double core = match.BuildingHp[team == 0 ? "blau_ancient" : "rot_ancient"];
text.AppendFormat("{0}: Türme {1}/8 · Ancient {2:0}\n", team == 0 ? "Blau" : "Rot", towers, core);
}
if (match.Combat != null)
{
int heroes = match.Combat.Units.Count(u => u.Kind == "hero" && u.Alive);
int boss = match.Combat.Units.Count(u => u.Kind == "boss" && u.Alive);
text.AppendFormat("Kampf {0:0.0} s · Einheiten {1} · Helden {2} · Boss {3}\n", match.Combat.Elapsed, match.Combat.Units.Count(u => u.IsMobile() && u.Alive), heroes, boss);
}
if (match.Phase == Phase.Over)
text.AppendFormat("Sieger: {0} · {1}", match.Winner == 0 ? "Blau" : match.Winner == 1 ? "Rot" : "Unentschieden", match.EndNote);
return text.ToString();
}
}
}