Files
CosmicClash/Game/scripts/perf_overlay.gd
T
Josh Creek 4fb7ddfecf docs(multiplayer): consolidate tracking into one document
multiplayer-todo.md and multiplayer-next.md tracked overlapping
information in two places. Fold everything into multiplayer-next.md
(architecture decisions, wire format, task breakdown with checkboxes,
gotchas list, testing notes) and delete multiplayer-todo.md. Section
numbers are unchanged, so existing code comments citing them by
section/task number still resolve; update every such reference to
point at the new filename.
2026-09-01 12:32:43 +01:00

63 lines
2.3 KiB
GDScript

extends CanvasLayer
# Autoload: toggleable frame-time/bottleneck overlay (F3 by default — see
# toggle_perf_overlay in project.godot's [input]). Read-only against
# Performance monitors; never touches rendering or gameplay state. Exists so
# 0.17/0.17b's graphics presets and resolution scaling are self-diagnosing —
# TIME_PROCESS vs total frame time tells the player whether they're CPU- or
# GPU-bound. See multiplayer-next.md task 0.20.
# ~2s of history at 60 fps; enough to make p50/p99 meaningful without the
# history itself being a rate-dependent quantity.
const HISTORY_SIZE := 120
var _label: Label
var _frame_times_ms: PackedFloat32Array = PackedFloat32Array()
var _history_index := 0
var _history_filled := 0
func _ready() -> void:
# A headless server never renders and has no input to toggle this with.
if DisplayServer.get_name() == "headless":
set_process(false)
return
layer = 100
_label = Label.new()
_label.add_theme_font_size_override("font_size", 14)
_label.add_theme_color_override("font_color", Color(0.4, 1.0, 0.5))
_label.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.85))
_label.add_theme_constant_override("shadow_offset_x", 1)
_label.add_theme_constant_override("shadow_offset_y", 1)
_label.position = Vector2(12, 12)
_label.visible = false
add_child(_label)
_frame_times_ms.resize(HISTORY_SIZE)
_frame_times_ms.fill(0.0)
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_perf_overlay") and _label:
_label.visible = not _label.visible
func _process(_delta: float) -> void:
if not _label or not _label.visible:
return
var frame_ms := Performance.get_monitor(Performance.TIME_PROCESS) * 1000.0
var physics_ms := Performance.get_monitor(Performance.TIME_PHYSICS_PROCESS) * 1000.0
_frame_times_ms[_history_index] = frame_ms
_history_index = (_history_index + 1) % HISTORY_SIZE
_history_filled = mini(_history_filled + 1, HISTORY_SIZE)
var sorted := _frame_times_ms.slice(0, _history_filled)
sorted.sort()
var p50 := sorted[sorted.size() / 2]
var p99 := sorted[int(sorted.size() * 0.99)]
_label.text = "FPS %d (p50 %.2fms p99 %.2fms)\nprocess %.2fms physics %.2fms\ndraw calls %d" % [
Performance.get_monitor(Performance.TIME_FPS),
p50, p99, frame_ms, physics_ms,
Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME),
]