module Lapis::Docs::C_GAMEPLAY_AND_DECLARATIVE_DSL::F_GAMEPLAY_LOGGING_AND_SENSORS

Overview

Gameplay Logging & Diagnostics DSL

Comprehensive guide to instrumenting Crystal gameplay nodes with high-performance diagnostic logging, custom gameplay domains, telemetry hooks, and zero-allocation release builds.

Executive Summary & Key Topics

Topic Method / Anchor Description
Gameplay Logging Patterns .topic_00_gameplay_logging_patterns Listing of common architectural patterns for game logging.
Logging Inside Custom Nodes .topic_01_node_logging Invoking Godot.log within node lifecycle methods and physics steps.
Defining Domain-Specific Filters .topic_02_gameplay_filters Grouping logs by game subsystem with custom colors and tags.
Performance Best Practices .topic_03_performance_considerations Ensuring high frame rates with compile-time elision and zero string allocation.

Related Guides & Source References

Defined in:

libgodot/docs/c_gameplay_and_declarative_dsl/f_gameplay_logging_and_sensors.cr

Class Method Summary

Class Method Detail

def self.topic_00_gameplay_logging_patterns : Nil #

Gameplay Logging Patterns: Listing of common architectural patterns for game logging.

Key Topics & Information

  • Combat & Damage Telemetry: Tracking hit points, damage calculation, and weapon attacks
  • AI State & Pathfinding: Logging behavior tree transitions and navigation milestones
  • Inventory & Item Transactions: Recording item additions, drops, and crafting events
  • Network & Multiplayer Replication: Logging RPC dispatches, state synchronization, and packet loss

def self.topic_01_node_logging : Nil #

Logging Inside Custom Nodes: Invoking Godot.log within node lifecycle methods and physics steps.

Within any custom node class, use Godot.log to record events:

require "libgodot"

node PlayerCharacter < CharacterBody2D do
  @[Export]
  property max_hp : Int32 = 100

  property current_hp : Int32 = 100

  signal died

  def take_damage(amount : Int32, source : String) : Void
    @current_hp = Math.max(0, @current_hp - amount)
    Godot.log :combat, "Player took #{amount} damage from #{source} (HP: #{@current_hp}/#{@max_hp})"

    if @current_hp == 0
      Godot.log :combat, "Player perished!"
      emit_died
    end
  end
end

def self.topic_02_gameplay_filters : Nil #

Defining Domain-Specific Filters: Grouping logs by game subsystem with custom colors and tags.

Declare your game's categories at the top of your system files:

define_log_filters do
  filter :combat,    tag: "{combat}",    name_tag: "COMBAT",    color: "#ff5555"
  filter :quest,     tag: "{quest}",     name_tag: "QUEST",     color: "#f1fa8c"
  filter :ai,        tag: "{ai}",        name_tag: "AI",        color: "#50fa7b"
  filter :dialogue,  tag: "{dialogue}",  name_tag: "DIALOGUE",  color: "#bd93f9"
end

When messages are printed, Godot's output console displays them with clear colored prefixes:

[21:45:10.123] [COMBAT] {combat} Player took 25 damage from GoblinArcher (HP: 75/100)
[21:45:12.456] [QUEST] {quest} Objective completed: 'Clear the goblin camp'

def self.topic_03_performance_considerations : Nil #

Performance Best Practices: Ensuring high frame rates with compile-time elision and zero string allocation.

  1. Never string-interpolate in hot physics loops without log level guards: Godot.log macros automatically guard argument evaluation. If :debug or :trace is disabled at compile time, the entire statement and string interpolation is removed:
    # Zero cost in release builds:
    Godot.log :trace, "Raycast check at #{global_position} returned #{hit}"
  2. Use Release Compilation for Shipping: In --release mode, lower severity logs are completely elided.