groupsCommunity
Debugging and Profiling Tips
Debugging and Profiling Tips
Community guide for debugging s&box games based on official tools and developer recommendations.
Console Commands
Useful built-in commands (press ~ in game):
CODE
stat fps # Show FPS counter
stat net # Network statistics
stat physics # Physics performance
showtriggers # Visualize trigger volumes
showhitboxes # Show collision hitboxes
mat_wireframe # Wireframe renderingVisual Debugging
Draw gizmos and debug info:
CSHARP
public class Weapon : Component
{
protected override void OnUpdate()
{
// Draw debug ray for aim
if (Input.Down("attack1"))
{
var start = WorldPosition;
var end = start + WorldRotation.Forward * 10000;
// Red line: aim direction
DebugOverlay.Line(start, end, Color.Red, 0.1f);
var tr = Scene.Trace.Ray(start, end).Run();
if (tr.Hit)
{
// Green sphere: hit point
DebugOverlay.Sphere(tr.EndPosition, 10f, Color.Green, 0.5f);
// Normal arrow: surface normal
DebugOverlay.Arrow(tr.EndPosition, tr.EndPosition + tr.Normal * 50f, 10f, Color.Yellow, 0.5f);
}
}
}
// Draw persistent gizmo in editor
protected override void DrawGizmos()
{
// Shows weapon range in editor
Gizmo.Draw.LineCircle(WorldPosition, WorldRotation, 1000f, 32);
}
}Logging Best Practices
CSHARP
public class GameManager : Component
{
// Use Log.Category for filtering
public static Logger GameLog { get; } = new("Game");
public static Logger NetLog { get; } = new("Network");
void StartGame()
{
GameLog.Info($"Game starting with {PlayerCount} players");
if (PlayerCount < MinPlayers)
{
GameLog.Warning($"Low player count: {PlayerCount}/{MinPlayers}");
}
}
void NetworkEvent()
{
NetLog.Verbose($"Received RPC from {Rpc.CallerId}");
}
}Network Debugging
CSHARP
public class NetworkDebugger : Component
{
[ConCmd("debug_network")]
public static void DebugNetwork()
{
Log.Info($"Is Host: {Network.IsHost}");
Log.Info($"Is Client: {Network.IsClient}");
Log.Info($"Connection Count: {Network.Connections.Count()}");
foreach (var conn in Network.Connections)
{
Log.Info($" - {conn.DisplayName} (ID: {conn.Id})");
}
}
protected override void OnUpdate()
{
// Visualize ownership
if (Gizmo.IsSelected)
{
var ownerText = Network.IsOwner ? "OWNER" : (IsProxy ? "PROXY" : "HOST");
Gizmo.Draw.Text(ownerText, WorldPosition, "white", 24f);
}
}
}Performance Profiling
CSHARP
public class PerformanceMonitor : Component
{
private List<float> _frameTimes = new();
protected override void OnUpdate()
{
// Track frame times
_frameTimes.Add(Time.Delta);
if (_frameTimes.Count > 100) _frameTimes.RemoveAt(0);
// Log slow frames
if (Time.Delta > 0.033f) // < 30 FPS
{
Log.Warning($"Slow frame: {Time.Delta * 1000:F1}ms");
}
}
[ConCmd("perf_report")]
public static void PerformanceReport()
{
var avg = _frameTimes.Average() * 1000;
var max = _frameTimes.Max() * 1000;
Log.Info($"Frame Time: {avg:F1}ms avg, {max:F1}ms max");
Log.Info($"FPS: {1f / avg * 1000:F0}");
}
}Finding Memory Leaks
CSHARP
public class MemoryTracker : Component
{
private static int _instanceCount = 0;
public MemoryTracker()
{
_instanceCount++;
Log.Info($"Created {GetType().Name}. Total: {_instanceCount}");
}
protected override void OnDestroy()
{
_instanceCount--;
Log.Info($"Destroyed {GetType().Name}. Remaining: {_instanceCount}");
}
}Scene Debugging
CSHARP
[ConCmd("find_object")]
public static void FindObject(string name)
{
var obj = Scene.FindObjectByName(name);
if (obj.IsValid())
{
Log.Info($"Found: {obj.Name}");
Log.Info($" Position: {obj.WorldPosition}");
Log.Info($" Components: {string.Join(", ", obj.Components.GetAll().Select(c => c.GetType().Name))}");
// Teleport player to it
if (Scene.Camera.IsValid())
{
Scene.Camera.WorldPosition = obj.WorldPosition + Vector3.Up * 100;
}
}
else
{
Log.Warning($"Object '{name}' not found");
}
}Source
- Official debugging docs: https://sbox.game/dev/doc
- Facepunch developer console commands
- Community debugging tools and extensions
Was this helpful?