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>
56 lines
2.5 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|