diff --git a/Assets/DebugOverlay/ConfigVar.cs b/Assets/DebugOverlay/ConfigVar.cs new file mode 100644 index 0000000..ee191c5 --- /dev/null +++ b/Assets/DebugOverlay/ConfigVar.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public interface IConfigVar +{ + string Name { get; } + string Description { get; } + string GetStringValue(); + bool TrySetValue(string input); + void ResetToDefault(); +} + +public struct ConfigVarFloat : IConfigVar +{ + private float m_Value; + private float m_DefaultValue; + private string m_Name; + private string m_Description; + + public string Name => m_Name; + public string Description => m_Description; + public float Value => m_Value; + + public ConfigVarFloat(string name, float defaultValue, string description = "") + { + m_Name = name; + m_DefaultValue = defaultValue; + m_Description = description; + m_Value = defaultValue; + } + + public string GetStringValue() + { + return m_Value.ToString("F3"); + } + + public bool TrySetValue(string input) + { + if (float.TryParse(input, out float newValue)) + { + m_Value = newValue; + return true; + } + return false; + } + + public void ResetToDefault() + { + m_Value = m_DefaultValue; + } +} + +public struct ConfigVarInt : IConfigVar +{ + private int m_Value; + private int m_DefaultValue; + private string m_Name; + private string m_Description; + + public string Name => m_Name; + public string Description => m_Description; + public int Value => m_Value; + + public ConfigVarInt(string name, int defaultValue, string description = "") + { + m_Name = name; + m_DefaultValue = defaultValue; + m_Description = description; + m_Value = defaultValue; + } + + public string GetStringValue() + { + return m_Value.ToString(); + } + + public bool TrySetValue(string input) + { + if (int.TryParse(input, out int newValue)) + { + m_Value = newValue; + return true; + } + return false; + } + + public void ResetToDefault() + { + m_Value = m_DefaultValue; + } +} + +public struct ConfigVarBool : IConfigVar +{ + private bool m_Value; + private bool m_DefaultValue; + private string m_Name; + private string m_Description; + + public string Name => m_Name; + public string Description => m_Description; + public bool Value => m_Value; + + public ConfigVarBool(string name, bool defaultValue, string description = "") + { + m_Name = name; + m_DefaultValue = defaultValue; + m_Description = description; + m_Value = defaultValue; + } + + public string GetStringValue() + { + return m_Value ? "1" : "0"; + } + + public bool TrySetValue(string input) + { + if (bool.TryParse(input, out bool newValue)) + { + m_Value = newValue; + return true; + } + // Also accept "0", "1" for bool + if (input == "0") + { + m_Value = false; + return true; + } + if (input == "1") + { + m_Value = true; + return true; + } + return false; + } + + public void ResetToDefault() + { + m_Value = m_DefaultValue; + } +} + +public static class ConfigVarRegistry +{ + private static Dictionary s_Vars = new Dictionary(); + + public static void Register(ref T configVar) where T : struct, IConfigVar + { + s_Vars[configVar.Name] = configVar; + } + + public static bool TryGetValue(string name, out IConfigVar configVar) + { + return s_Vars.TryGetValue(name, out configVar); + } + + public static bool TrySetValue(string name, string value) + { + if (s_Vars.TryGetValue(name, out IConfigVar configVar)) + { + return configVar.TrySetValue(value); + } + return false; + } + + public static bool TryGetFloat(string name, out float value) + { + if (s_Vars.TryGetValue(name, out IConfigVar configVar) && configVar is ConfigVarFloat floatVar) + { + value = floatVar.Value; + return true; + } + value = 0.0f; + return false; + } + + public static bool TryGetInt(string name, out int value) + { + if (s_Vars.TryGetValue(name, out IConfigVar configVar) && configVar is ConfigVarInt intVar) + { + value = intVar.Value; + return true; + } + value = 0; + return false; + } + + public static bool TryGetBool(string name, out bool value) + { + if (s_Vars.TryGetValue(name, out IConfigVar configVar) && configVar is ConfigVarBool boolVar) + { + value = boolVar.Value; + return true; + } + value = false; + return false; + } + + public static void ResetToDefault(string name) + { + if (s_Vars.TryGetValue(name, out IConfigVar configVar)) + { + configVar.ResetToDefault(); + } + } + + public static Dictionary.Enumerator GetAllVars() + { + return s_Vars.GetEnumerator(); + } + + public static int Count => s_Vars.Count; +} \ No newline at end of file diff --git a/Assets/DebugOverlay/ConfigVar.cs.meta b/Assets/DebugOverlay/ConfigVar.cs.meta new file mode 100644 index 0000000..331e4e4 --- /dev/null +++ b/Assets/DebugOverlay/ConfigVar.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b641be8ca74ea764b9ae0861c51e2bf3 \ No newline at end of file diff --git a/Assets/DebugOverlay/Console.cs b/Assets/DebugOverlay/Console.cs index 944080d..bc066e0 100644 --- a/Assets/DebugOverlay/Console.cs +++ b/Assets/DebugOverlay/Console.cs @@ -43,6 +43,10 @@ public Console() m_InputFieldBuffer = new char[k_InputBufferSize]; AddCommand("help", CmdHelp, "Show available commands"); AddCommand("dump", CmdDumpScene, "Dump scene hierarchy in active scene"); + AddCommand("cvarlist", CmdCvarList, "List all config variables"); + AddCommand("cvar", CmdCvar, "Get or set config variable: cvar [value]"); + AddCommand("cvarreset", CmdCvarReset, "Reset config variable to default: cvarreset "); + AddCommand("cvartest", CmdCvarTest, "Test config variable system"); Keyboard.current.onTextInput += OnTextInput; } @@ -91,6 +95,85 @@ void CmdHelp(string[] args) } } + void CmdCvarList(string[] args) + { + Write("Config Variables ({0}):\n", ConfigVarRegistry.Count); + var enumerator = ConfigVarRegistry.GetAllVars(); + while (enumerator.MoveNext()) + { + var kvp = enumerator.Current; + Write(" {0,-20} = {1,-10} {2}\n", kvp.Key, kvp.Value.GetStringValue(), kvp.Value.Description); + } + } + + void CmdCvar(string[] args) + { + if (args.Length == 0) + { + Write("Usage: cvar [value]\n"); + return; + } + + string varName = args[0]; + + if (args.Length == 1) + { + // Get value + if (ConfigVarRegistry.TryGetValue(varName, out IConfigVar configVar)) + { + Write("{0} = {1}\n", varName, configVar.GetStringValue()); + } + else + { + Write("Config variable '{0}' not found\n", varName); + } + } + else if (args.Length == 2) + { + // Set value + string value = args[1]; + if (ConfigVarRegistry.TrySetValue(varName, value)) + { + Write("{0} = {1}\n", varName, value); + } + else + { + Write("Failed to set {0} = {1}\n", varName, value); + } + } + else + { + Write("Usage: cvar [value]\n"); + } + } + + void CmdCvarReset(string[] args) + { + if (args.Length != 1) + { + Write("Usage: cvarreset \n"); + return; + } + + string varName = args[0]; + ConfigVarRegistry.ResetToDefault(varName); + Write("Reset {0} to default value\n", varName); + } + + void CmdCvarTest(string[] args) + { + Write("Testing config variable system...\n"); + + // Test setting and getting values + ConfigVarRegistry.TrySetValue("fov", "90.0"); + ConfigVarRegistry.TrySetValue("mousesensitivity", "100.0"); + ConfigVarRegistry.TrySetValue("showstats", "false"); + + Write("Set fov=90, mousesensitivity=100, showstats=false\n"); + Write("Use 'cvarlist' to see all variables\n"); + Write("Use 'cvar fov' to see current value\n"); + } + public void Init() { Init(null); diff --git a/Assets/Demo/fpscontroller.cs b/Assets/Demo/fpscontroller.cs index 85b2c96..30ac446 100644 --- a/Assets/Demo/fpscontroller.cs +++ b/Assets/Demo/fpscontroller.cs @@ -17,13 +17,15 @@ public class fpscontroller : MonoBehaviour { public Camera player_cam; - public float mouse_sensitivity = 75.0f; - public float jump_speed = 5.0f; - public float player_friction = 8.0f; - public float player_air_friction = 1.0f; - public float player_accel = 100.0f; - public float player_air_accel = 30.0f; - public float player_speed = 7.0f; + // Config variables for player settings + static ConfigVarFloat s_MouseSensitivity = new ConfigVarFloat("mousesensitivity", 75.0f, "Mouse sensitivity"); + static ConfigVarFloat s_Fov = new ConfigVarFloat("fov", 70.0f, "Field of view"); + static ConfigVarFloat s_JumpSpeed = new ConfigVarFloat("jumpspeed", 5.0f, "Jump speed"); + static ConfigVarFloat s_PlayerFriction = new ConfigVarFloat("playerfriction", 8.0f, "Player ground friction"); + static ConfigVarFloat s_PlayerAirFriction = new ConfigVarFloat("playerairfriction", 1.0f, "Player air friction"); + static ConfigVarFloat s_PlayerAccel = new ConfigVarFloat("playeraccel", 100.0f, "Player ground acceleration"); + static ConfigVarFloat s_PlayerAirAccel = new ConfigVarFloat("playerairaccel", 30.0f, "Player air acceleration"); + static ConfigVarFloat s_PlayerSpeed = new ConfigVarFloat("playerspeed", 7.0f, "Player movement speed"); private float cam_yaw = 0.0f; private Vector3 velocity = Vector3.zero; @@ -33,6 +35,16 @@ public class fpscontroller : MonoBehaviour void Start() { cc = GetComponent(); + + // Register config variables + ConfigVarRegistry.Register(ref s_MouseSensitivity); + ConfigVarRegistry.Register(ref s_Fov); + ConfigVarRegistry.Register(ref s_JumpSpeed); + ConfigVarRegistry.Register(ref s_PlayerFriction); + ConfigVarRegistry.Register(ref s_PlayerAirFriction); + ConfigVarRegistry.Register(ref s_PlayerAccel); + ConfigVarRegistry.Register(ref s_PlayerAirAccel); + ConfigVarRegistry.Register(ref s_PlayerSpeed); } void Update() @@ -43,7 +55,7 @@ void Update() // Turn player var turn_player = new Vector3(0, Mouse.current.delta.x.value, 0); - turn_player = turn_player * mouse_sensitivity * Time.deltaTime; + turn_player = turn_player * s_MouseSensitivity.Value * Time.deltaTime; transform.localEulerAngles += turn_player; // Fall down / gravity @@ -55,8 +67,8 @@ void Update() bool isGrounded = cc.isGrounded; - var friction = isGrounded ? player_friction : player_air_friction; - var accel = isGrounded ? player_accel : player_air_accel; + var friction = isGrounded ? s_PlayerFriction.Value : s_PlayerAirFriction.Value; + var accel = isGrounded ? s_PlayerAccel.Value : s_PlayerAirAccel.Value; // WASD movement float horizontal = Keyboard.current.aKey.isPressed ? -1.0f : 0.0f; @@ -82,10 +94,10 @@ void Update() } // Horizontal movement - var wantedGroundVel = move * player_speed; + var wantedGroundVel = move * s_PlayerSpeed.Value; var wantedGroundDir = moveMagnitude > 0.001f ? move / moveMagnitude : Vector3.zero; var speedMadeGood = Vector3.Dot(groundVelocity, wantedGroundDir); - var deltaSpeed = moveMagnitude * player_speed - speedMadeGood; + var deltaSpeed = moveMagnitude * s_PlayerSpeed.Value - speedMadeGood; if (deltaSpeed > 0.001) { var velAdjust = Mathf.Clamp(accel * Time.deltaTime, 0.0f, deltaSpeed) * wantedGroundDir; @@ -99,12 +111,18 @@ void Update() // Jump if (isGrounded && Keyboard.current.spaceKey.isPressed) { - velocity.y = jump_speed; + velocity.y = s_JumpSpeed.Value; } // Camera look up/down - cam_yaw += -Mouse.current.delta.y.value * mouse_sensitivity * Time.deltaTime; + cam_yaw += -Mouse.current.delta.y.value * s_MouseSensitivity.Value * Time.deltaTime; cam_yaw = Mathf.Clamp(cam_yaw, -70.0f, 70.0f); player_cam.transform.localEulerAngles = new Vector3(cam_yaw, 0, 0); + + // Apply FOV from config + if (player_cam != null) + { + player_cam.fieldOfView = s_Fov.Value; + } } } diff --git a/Assets/Game/Game.cs b/Assets/Game/Game.cs index 1ba3bdc..0d7b3b1 100644 --- a/Assets/Game/Game.cs +++ b/Assets/Game/Game.cs @@ -42,12 +42,21 @@ public void Init() m_Console.AddCommand("quit", CmdQuit, "Quit game"); + // Register config variables + RegisterConfigVars(); + m_Stats = new Stats(); m_Stats.Init(); Game.console.Write("^FFFGame initialized^F44.^4F4.^44F.\n"); } + void RegisterConfigVars() + { + // Config variables are now registered in their respective classes + // This method is kept for any global config vars that might be added in the future + } + public void Shutdown() { Debug.Assert(_instance == this); diff --git a/Assets/Game/Stats.cs b/Assets/Game/Stats.cs index c43c503..37307a7 100644 --- a/Assets/Game/Stats.cs +++ b/Assets/Game/Stats.cs @@ -12,7 +12,9 @@ public class Stats : IGameSystem long m_StopWatchFreq; long m_LastFrameTicks; - int m_ShowStats = 1; + // Config variables for stats display + static ConfigVarBool s_ShowStats = new ConfigVarBool("showstats", true, "Show performance stats"); + static ConfigVarInt s_ShowStatsLevel = new ConfigVarInt("showstatslevel", 1, "Stats detail level (0-2)"); public void Init() { @@ -21,12 +23,18 @@ public void Init() m_StopWatch.Start(); m_LastFrameTicks = m_StopWatch.ElapsedTicks; Debug.Assert(System.Diagnostics.Stopwatch.IsHighResolution); - Game.console.AddCommand("showstats", CmdShowstats, "Show or hide stats"); + + // Register config variables + ConfigVarRegistry.Register(ref s_ShowStats); + ConfigVarRegistry.Register(ref s_ShowStatsLevel); + + Game.console.AddCommand("showstats", CmdShowstats, "Toggle stats display"); } private void CmdShowstats(string[] args) { - m_ShowStats = (m_ShowStats + 1) % 3; + int currentLevel = s_ShowStatsLevel.Value; + s_ShowStatsLevel.TrySetValue(((currentLevel + 1) % 3).ToString()); } void CalcStatistics(float[] data, out float mean, out float variance, out float minValue, out float maxValue) @@ -56,7 +64,7 @@ void CalcStatistics(float[] data, out float mean, out float variance, out float float[] fpsHistory = new float[50]; public void TickUpdate() { - if (m_ShowStats < 1) + if (!s_ShowStats.Value) return; long ticks = m_StopWatch.ElapsedTicks; @@ -72,12 +80,18 @@ public void TickUpdate() DebugOverlay.Write(30, 0, "Open console (F12) and type: \"showstats\" to toggle graphs"); - if (m_ShowStats < 2) + if (s_ShowStatsLevel.Value < 2) return; DebugOverlay.Write(0, 4, "Hello, {0,-5} world!", Time.frameCount % 100 < 50 ? "Happy" : "Evil"); DebugOverlay.Write(0, 5, "FrameNo: {0,7}", Time.frameCount); DebugOverlay.Write(0, 6, "MonoHeap:{0,7} kb", (int)(UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong() / 1024)); + + // Display some config variables + float fovValue, mouseValue; + ConfigVarRegistry.TryGetFloat("fov", out fovValue); + ConfigVarRegistry.TryGetFloat("mousesensitivity", out mouseValue); + DebugOverlay.Write(0, 7, "FOV:{0,6:###.##} Mouse:{1,6:###.##}", fovValue, mouseValue); /// Graphing difference between deltaTime and actual passed time float fps = Time.deltaTime * 1000.0f;