Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions Assets/Game/ConfigVar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using System;
using UnityEngine;

public static class ConfigVar
{
// Static arrays for O(1) access - no dictionary lookups in hot loops
private static string[] m_Names = new string[128];
private static float[] m_FloatValues = new float[128];
private static int[] m_IntValues = new int[128];
private static bool[] m_BoolValues = new bool[128];
private static ConfigVarType[] m_Types = new ConfigVarType[128];
private static int m_Count = 0;

public enum ConfigVarType { Float, Int, Bool }

// Fast access methods for hot loops
public static float GetFloat(int id) => m_FloatValues[id];
public static int GetInt(int id) => m_IntValues[id];
public static bool GetBool(int id) => m_BoolValues[id];

// Registration methods
public static int RegisterFloat(string name, float defaultValue, string description = "")
{
int id = m_Count++;
m_Names[id] = name;
m_FloatValues[id] = defaultValue;
m_Types[id] = ConfigVarType.Float;

// Add console command for setting
Game.console.AddCommand(name, (args) => CmdSetFloat(id, args), description);
return id;
}

public static int RegisterInt(string name, int defaultValue, string description = "")
{
int id = m_Count++;
m_Names[id] = name;
m_IntValues[id] = defaultValue;
m_Types[id] = ConfigVarType.Int;

Game.console.AddCommand(name, (args) => CmdSetInt(id, args), description);
return id;
}

public static int RegisterBool(string name, bool defaultValue, string description = "")
{
int id = m_Count++;
m_Names[id] = name;
m_BoolValues[id] = defaultValue;
m_Types[id] = ConfigVarType.Bool;

Game.console.AddCommand(name, (args) => CmdSetBool(id, args), description);
return id;
}

// Console command handlers using existing StringFormatter
private static void CmdSetFloat(int id, string[] args)
{
if (args.Length < 1)
{
Game.console.Write("{0} = {1}\n", m_Names[id], m_FloatValues[id]);
return;
}

if (float.TryParse(args[0], out float value))
{
m_FloatValues[id] = value;
Game.console.Write("{0} = {1}\n", m_Names[id], value);
}
else
{
Game.console.Write("Invalid value for {0}\n", m_Names[id]);
}
}

private static void CmdSetInt(int id, string[] args)
{
if (args.Length < 1)
{
Game.console.Write("{0} = {1}\n", m_Names[id], m_IntValues[id]);
return;
}

if (int.TryParse(args[0], out int value))
{
m_IntValues[id] = value;
Game.console.Write("{0} = {1}\n", m_Names[id], value);
}
else
{
Game.console.Write("Invalid value for {0}\n", m_Names[id]);
}
}

private static void CmdSetBool(int id, string[] args)
{
if (args.Length < 1)
{
Game.console.Write("{0} = {1}\n", m_Names[id], m_BoolValues[id] ? "true" : "false");
return;
}

if (bool.TryParse(args[0], out bool value))
{
m_BoolValues[id] = value;
Game.console.Write("{0} = {1}\n", m_Names[id], value ? "true" : "false");
}
else
{
Game.console.Write("Invalid value for {0}\n", m_Names[id]);
}
}

// List all config vars
public static void CmdList(string[] args)
{
Game.console.Write("Config Variables:\n");
for (int i = 0; i < m_Count; i++)
{
switch (m_Types[i])
{
case ConfigVarType.Float:
Game.console.Write(" {0} = {1}\n", m_Names[i], m_FloatValues[i]);
break;
case ConfigVarType.Int:
Game.console.Write(" {0} = {1}\n", m_Names[i], m_IntValues[i]);
break;
case ConfigVarType.Bool:
Game.console.Write(" {0} = {1}\n", m_Names[i], m_BoolValues[i] ? "true" : "false");
break;
}
}
}
}
2 changes: 2 additions & 0 deletions Assets/Game/ConfigVar.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Assets/Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void Init()
m_Console.Init();

m_Console.AddCommand("quit", CmdQuit, "Quit game");
m_Console.AddCommand("cvarlist", ConfigVar.CmdList, "List all config variables");

m_Stats = new Stats();
m_Stats.Init();
Expand Down
38 changes: 37 additions & 1 deletion Assets/Game/Stats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ public class Stats : IGameSystem

int m_ShowStats = 1;

// Config variable IDs for fast access
private static int s_FovId;
private static int s_MouseSensitivityId;
private static int s_ShowDebugInfoId;
private static int s_GraphScaleId;

public void Init()
{
m_StopWatch = new System.Diagnostics.Stopwatch();
Expand All @@ -22,13 +28,31 @@ public void Init()
m_LastFrameTicks = m_StopWatch.ElapsedTicks;
Debug.Assert(System.Diagnostics.Stopwatch.IsHighResolution);
Game.console.AddCommand("showstats", CmdShowstats, "Show or hide stats");
Game.console.AddCommand("demo", CmdDemo, "Demo config variable usage");

// Register config variables
s_FovId = ConfigVar.RegisterFloat("fov", 70.0f, "Field of view");
s_MouseSensitivityId = ConfigVar.RegisterFloat("mousesens", 1.0f, "Mouse sensitivity");
s_ShowDebugInfoId = ConfigVar.RegisterBool("showdebug", true, "Show debug information");
s_GraphScaleId = ConfigVar.RegisterFloat("graphscale", 1.5f, "Graph scale factor");
}

private void CmdShowstats(string[] args)
{
m_ShowStats = (m_ShowStats + 1) % 3;
}

private void CmdDemo(string[] args)
{
Game.console.Write("Config Variable Demo:\n");
Game.console.Write("Try these commands:\n");
Game.console.Write(" fov = 90\n");
Game.console.Write(" mousesens = 2.5\n");
Game.console.Write(" showdebug = false\n");
Game.console.Write(" graphscale = 2.0\n");
Game.console.Write(" cvarlist\n");
}

void CalcStatistics(float[] data, out float mean, out float variance, out float minValue, out float maxValue)
{
float sum = 0, sum2 = 0;
Expand Down Expand Up @@ -63,14 +87,26 @@ public void TickUpdate()
float frameDurationMs = (ticks - m_LastFrameTicks) * 1000 / (float)m_StopWatchFreq;
m_LastFrameTicks = ticks;

// Fast access to config variables - no allocations or lookups
float fov = ConfigVar.GetFloat(s_FovId);
float mouseSens = ConfigVar.GetFloat(s_MouseSensitivityId);
bool showDebug = ConfigVar.GetBool(s_ShowDebugInfoId);
float graphScale = ConfigVar.GetFloat(s_GraphScaleId);

DebugOverlay.SetColor(Color.yellow);
DebugOverlay.SetOrigin(0, 0);

DebugOverlay.Write(1, 0, "FPS:{0,6:###.##}", 1.0f / Time.deltaTime);
fpsHistory[Time.frameCount % fpsHistory.Length] = 1.0f / Time.deltaTime;
DebugOverlay.DrawGraph(1, 1, 9, 1.5f, fpsHistory, Time.frameCount % fpsHistory.Length, Color.green);
DebugOverlay.DrawGraph(1, 1, 9, graphScale, fpsHistory, Time.frameCount % fpsHistory.Length, Color.green);

DebugOverlay.Write(30, 0, "Open console (F12) and type: \"showstats\" to toggle graphs");

// Show config variables if debug is enabled
if (showDebug)
{
DebugOverlay.Write(1, 3, "FOV: {0}, MouseSens: {1}", fov, mouseSens);
}

if (m_ShowStats < 2)
return;
Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,46 @@ and it will work like this:

![Pretty picture](https://user-images.githubusercontent.com/4175246/28582984-d215e5f2-7167-11e7-99ff-e96b2981b9bb.gif)

## Config Variables

The project includes a high-performance config variable system inspired by Quake and Source engines. Config variables can be set from the console and provide O(1) access for use in hot loops.

### Usage

```c#
// Register config variables (typically in Init())
int fovId = ConfigVar.RegisterFloat("fov", 70.0f, "Field of view");
int mouseSensId = ConfigVar.RegisterFloat("mousesens", 1.0f, "Mouse sensitivity");
int showDebugId = ConfigVar.RegisterBool("showdebug", true, "Show debug information");

// Fast access in hot loops
float fov = ConfigVar.GetFloat(fovId);
float mouseSens = ConfigVar.GetFloat(mouseSensId);
bool showDebug = ConfigVar.GetBool(showDebugId);
```

### Console Commands

```
> fov = 90
fov = 90
> mousesens = 2.5
mousesens = 2.5
> showdebug = false
showdebug = False
> cvarlist
Config Variables:
fov = 90
mousesens = 2.5
showdebug = False
> demo
Config Variable Demo:
Try these commands:
fov = 90
mousesens = 2.5
showdebug = false
graphscale = 2.0
cvarlist
```