Files
documentation/planning/UTILITY_PLANNING.md
2025-12-29 17:37:04 -06:00

24 KiB

3D Game Development Library Gameplan

Overview

This document outlines a strategic plan for building a comprehensive C# library ecosystem for 3D game development in Godot. The libraries are organized by dependency hierarchy to ensure clean architecture, minimal coupling, and maximum reusability across projects.

Core Principles

1. Dependency-Driven Development

  • Bottom-Up Approach: Build foundational systems first
  • Minimal Dependencies: Each library should depend on as few others as possible
  • Clear Interfaces: Libraries communicate through well-defined APIs
  • Event-Driven Architecture: Use events to decouple systems that need to communicate

2. Quality over Speed

  • Complete One Library Before Starting Next: Fully implement, test, and document each library
  • Test-Driven Development: Create example projects for each library
  • API Documentation: Document public interfaces as you build
  • Refactor When Needed: Don't be afraid to improve APIs based on usage experience

3. Real-World Validation

  • Iterative Improvement: Refine APIs based on actual usage
  • Performance Monitoring: Profile libraries in real game scenarios

Development Phases

Phase 1: Foundation Libraries (Highest Priority)

These libraries form the bedrock of your game development ecosystem. They have minimal dependencies and provide essential functionality that nearly all other systems will use.

1.1 - EinSoftworks.Input

Status 🟢 Complete
Priority 🔴 Critical
Dependencies EinSoftworks.Utilities only

Why Build First:

  • Nearly every game system needs input handling
  • Input systems rarely depend on other game systems
  • Provides immediate value for any game project
  • Foundation for camera controls, character movement, and UI navigation

Core Features:

// Action-based input system
public class InputManager : Node
{
    // Core input queries
    public bool IsActionPressed(string action);
    public bool IsActionJustPressed(string action);
    public bool IsActionJustReleased(string action);
    public float GetActionStrength(string action);
    public Vector2 GetVector(string negativeX, string positiveX, string negativeY, string positiveY);

    // Input mapping and customization
    public void RemapAction(string action, InputEvent newEvent);
    public void SaveInputMap();
    public void LoadInputMap();
    public void ResetToDefaultInputMap();

    // Advanced features
    public bool WasActionPressedInWindow(string action, float timeWindow);
    public void SetDeadzone(string action, float deadzone);
    public InputDevice GetLastUsedDevice();
}

// Input buffering for precise timing
public class InputBuffer
{
    public void BufferInput(string action, float bufferTime);
    public bool ConsumeBufferedInput(string action);
    public void ClearBuffer();
}

Validation Game Ideas:

  • Simple character that moves with WASD
  • Menu navigation system
  • Basic interaction system (press E to interact)

1.2 - EinSoftworks.Events

Status 🟢 Complete
Priority 🔴 Critical
Dependencies EinSoftworks.Utilities only

Why Build Second:

  • Essential for decoupling systems
  • Prevents circular dependencies between libraries
  • Enables loose coupling between game systems
  • Small scope makes it quick to implement correctly

Core Features:

// Global event system
public static class GameEvents
{
    // Player events
    public static event Action<Vector3> PlayerMoved;
    public static event Action<float> PlayerHealthChanged;
    public static event Action PlayerDied;

    // Game state events
    public static event Action<string> StateChanged;
    public static event Action<string> SceneChanged;
    public static event Action GamePaused;
    public static event Action GameResumed;

    // Input events
    public static event Action<string> ActionPressed;
    public static event Action<string> ActionReleased;
}

// Type-safe event bus
public class EventBus<T> where T : class
{
    public void Subscribe(Action<T> handler);
    public void Unsubscribe(Action<T> handler);
    public void Publish(T eventData);
    public void Clear();
}

// Event pooling for performance
public class PooledEvent<T> where T : class, new()
{
    public static T Get();
    public static void Return(T item);
}

Validation Game Ideas:

  • System where player movement triggers camera updates (without direct coupling)
  • Health system that updates UI without direct references
  • Scene transition system using events

1.3 - EinSoftworks.StateManagement

Status 🔴 Incomplete
Priority 🔴 Critical
Dependencies EinSoftworks.Utilities, EinSoftworks.Events

Why Build Third:

  • State management is fundamental to game logic
  • Can utilize the event system for state transition notifications
  • Foundation for character AI, game flow, and UI states
  • More complex than input/events but still foundational

Core Features:

// Generic state machine
public class StateMachine<T> where T : class
{
    public T CurrentState { get; private set; }
    public T PreviousState { get; private set; }

    public void ChangeState(T newState);
    public void Update(float delta);
    public void FixedUpdate(float fixedDelta);

    // Transition system
    public void AddTransition(T from, T to, Func<bool> condition);
    public void AddAnyTransition(T to, Func<bool> condition);
    public void AddTransition(T from, T to, string triggerEvent);

    // Events
    public event Action<T, T> StateChanged; // (from, to)
}

// Base state class
public abstract class State
{
    public abstract void Enter();
    public abstract void Update(float delta);
    public abstract void FixedUpdate(float fixedDelta);
    public abstract void Exit();

    // Optional overrides
    public virtual void HandleInput() { }
    public virtual void OnDrawGizmos() { }
}

// Hierarchical state support
public class HierarchicalStateMachine<T> : StateMachine<T> where T : class
{
    public void AddSubState(T parentState, StateMachine<T> subStateMachine);
    public StateMachine<T> GetSubStateMachine(T parentState);
}

Validation Game Ideas:

  • Character with idle/walking/running/jumping states
  • Game with menu/playing/paused/game-over states
  • AI enemy with patrol/chase/attack states

Phase 2: Core 3D Systems (High Priority)

These libraries provide essential 3D game functionality and build upon the foundation libraries.

2.1 - EinSoftworks.Camera

Status 🔴 Incomplete
Priority 🟡 High
Dependencies EinSoftworks.Input, EinSoftworks.Events, EinSoftworks.StateManagement

Why Build Fourth:

  • Essential for any 3D game
  • Benefits from input system for camera controls
  • Can use state management for different camera modes
  • Independent enough to develop without character systems

Core Features:

// Main camera controller
public partial class CameraController : Node3D
{
    public enum CameraMode { FirstPerson, ThirdPerson, Orbit, Fixed, Cinematic }

    [Export] public CameraMode Mode { get; set; }
    [Export] public Node3D Target { get; set; }
    [Export] public float Sensitivity { get; set; } = 1.0f;
    [Export] public bool InvertY { get; set; } = false;

    // Camera positioning
    public void SetTarget(Node3D target);
    public void SetPosition(Vector3 position, float transitionTime = 0f);
    public void SetLookAt(Vector3 lookAt, float transitionTime = 0f);

    // Camera effects
    public void Shake(float intensity, float duration);
    public void Zoom(float targetFOV, float duration);
    public void SetCameraMode(CameraMode mode, float transitionTime = 1f);

    // Collision prevention
    public void EnableCollisionAvoidance(bool enabled);
    public void SetCollisionLayers(uint layers);
}

// Specialized camera types
public class FirstPersonCamera : CameraController
{
    [Export] public float MouseSensitivity { get; set; } = 0.1f;
    [Export] public float MinPitch { get; set; } = -90f;
    [Export] public float MaxPitch { get; set; } = 90f;
}

public class ThirdPersonCamera : CameraController
{
    [Export] public float Distance { get; set; } = 5f;
    [Export] public float Height { get; set; } = 2f;
    [Export] public Vector3 Offset { get; set; }
    [Export] public bool AutoRotate { get; set; } = true;
}

public class OrbitCamera : CameraController
{
    [Export] public float MinDistance { get; set; } = 2f;
    [Export] public float MaxDistance { get; set; } = 10f;
    [Export] public float ZoomSpeed { get; set; } = 1f;
}

Validation Game Ideas:

  • First-person camera with mouse look
  • Third-person camera that follows a moving object
  • Orbit camera for examining 3D models

2.2 - EinSoftworks.Physics

Status 🔴 Incomplete
Priority 🟡 High
Dependencies EinSoftworks.Utilities, EinSoftworks.Events

Why Build Fifth:

  • Nearly all 3D games need physics utilities
  • Independent of complex game systems
  • Provides foundation for character controllers and interaction systems
  • Can be validated independently

Core Features:

// Raycast utilities
public static class PhysicsUtils
{
    public static bool Raycast(Vector3 origin, Vector3 direction, float maxDistance,
                              uint collisionMask = uint.MaxValue);
    public static RaycastHit RaycastWithInfo(Vector3 origin, Vector3 direction, float maxDistance);
    public static RaycastHit[] RaycastAll(Vector3 origin, Vector3 direction, float maxDistance);

    // Shape casting
    public static bool SphereCast(Vector3 origin, float radius, Vector3 direction, float maxDistance);
    public static bool BoxCast(Vector3 origin, Vector3 size, Vector3 direction, float maxDistance);

    // Overlap detection
    public static Node3D[] OverlapSphere(Vector3 center, float radius, uint collisionMask);
    public static Node3D[] OverlapBox(Vector3 center, Vector3 size, uint collisionMask);
}

// Physics materials management
public class PhysicsMaterialManager : Node
{
    public void RegisterMaterial(string name, PhysicsMaterial material);
    public PhysicsMaterial GetMaterial(string name);
    public void ApplyMaterial(RigidBody3D body, string materialName);
}

// Trigger volume system
public partial class TriggerVolume : Area3D
{
    [Signal] public delegate void BodyEnteredEventHandler(Node3D body);
    [Signal] public delegate void BodyExitedEventHandler(Node3D body);

    public bool IsBodyInside(Node3D body);
    public Node3D[] GetBodiesInside();
}

Validation Game Ideas:

  • Character that detects ground beneath them
  • Interaction system using raycasts
  • Trigger volumes that activate when player enters

Phase 3: Character and Interaction Systems (Medium Priority)

These systems focus on character control and world interaction, building upon the previously established libraries.

3.1 - EinSoftworks.Movement

Status 🔴 Incomplete
Priority 🟡 High
Dependencies EinSoftworks.Input, EinSoftworks.Physics, EinSoftworks.StateManagement, EinSoftworks.Events

Why Build Sixth:

  • Core to most 3D games
  • Benefits from all previously built systems
  • Complex enough to require solid foundations
  • Can be thoroughly tested with camera systems

Core Features:

// Base character controller
public partial class CharacterController3D : CharacterBody3D
{
    [Export] public float Speed { get; set; } = 5f;
    [Export] public float JumpVelocity { get; set; } = 4.5f;
    [Export] public float Acceleration { get; set; } = 10f;
    [Export] public float Friction { get; set; } = 10f;

    // Ground detection
    public bool IsOnFloor();
    public bool IsOnWall();
    public bool IsOnCeiling();
    public float GetFloorAngle();
    public Vector3 GetFloorNormal();

    // Movement
    public void Move(Vector3 direction, float delta);
    public void Jump();
    public void ApplyGravity(float delta);

    // State integration
    public StateMachine<MovementState> StateMachine { get; private set; }
}

// Movement states
public class IdleState : MovementState
{
    public override void Enter() { /* Set idle animation */ }
    public override void Update(float delta) { /* Check for movement input */ }
}

public class WalkingState : MovementState
{
    public override void Enter() { /* Set walking animation */ }
    public override void Update(float delta) { /* Handle movement */ }
}

public class JumpingState : MovementState
{
    public override void Enter() { /* Apply jump force, set animation */ }
    public override void Update(float delta) { /* Handle air control */ }
}

// Specialized controllers
public class FirstPersonController : CharacterController3D
{
    [Export] public float MouseSensitivity { get; set; } = 0.1f;
    public Node3D Head { get; set; }
}

public class ThirdPersonController : CharacterController3D
{
    [Export] public bool RotateToMovement { get; set; } = true;
    [Export] public float RotationSpeed { get; set; } = 10f;
}

Validation Game Ideas:

  • First-person character with WASD movement and mouse look
  • Third-person character that rotates to movement direction
  • Platformer character with precise jumping mechanics

3.2 - EinSoftworks.Interaction

Status 🔴 Incomplete
Priority 🟡 Medium
Dependencies EinSoftworks.Input, EinSoftworks.Physics, EinSoftworks.Events

Why Build Seventh:

  • Common need in 3D games
  • Builds naturally on physics and input systems
  • Can be developed independently of complex character systems
  • Provides immediate gameplay value

Core Features:

// Interactable base class
public partial class Interactable : Node3D
{
    [Export] public string InteractionText { get; set; } = "Interact";
    [Export] public float InteractionRange { get; set; } = 2f;
    [Export] public bool RequiresLineOfSight { get; set; } = true;
    [Export] public bool OneTimeUse { get; set; } = false;

    [Signal] public delegate void InteractedEventHandler(Node3D interactor);
    [Signal] public delegate void FocusedEventHandler(Node3D interactor);
    [Signal] public delegate void UnfocusedEventHandler(Node3D interactor);

    public virtual bool CanInteract(Node3D interactor) { return true; }
    public virtual void Interact(Node3D interactor) { }
    public virtual void OnFocused(Node3D interactor) { }
    public virtual void OnUnfocused(Node3D interactor) { }
}

// Interaction detector
public partial class InteractionDetector : Node3D
{
    [Export] public float DetectionRange { get; set; } = 3f;
    [Export] public string InteractionAction { get; set; } = "interact";

    public Interactable CurrentInteractable { get; private set; }
    public Interactable[] GetInteractablesInRange();
    public void TryInteract();

    [Signal] public delegate void InteractableFoundEventHandler(Interactable interactable);
    [Signal] public delegate void InteractableLostEventHandler(Interactable interactable);
}

// Specific interactable types
public class PickupItem : Interactable
{
    [Export] public string ItemId { get; set; }
    [Export] public int Quantity { get; set; } = 1;
    [Export] public AudioStream PickupSound { get; set; }
}

public class Door : Interactable
{
    [Export] public bool IsLocked { get; set; } = false;
    [Export] public string RequiredKey { get; set; }
    [Export] public float OpenAngle { get; set; } = 90f;
    [Export] public float OpenSpeed { get; set; } = 2f;
}

Validation Game Ideas:

  • Player that can pick up items and open doors
  • Interaction UI that shows prompts when near interactables
  • Key-door system with locked interactions

Phase 4: Advanced Game Systems (Lower Priority)

These systems provide advanced functionality for complete games and can be built once the core systems are stable.

4.1 - EinSoftworks.SceneManagement

Status 🔴 Incomplete
Priority 🟢 Medium-Low
Dependencies EinSoftworks.StateManagement, EinSoftworks.Events

Core Features:

public class SceneManager : Node
{
    public string CurrentScene { get; private set; }
    public bool IsLoading { get; private set; }

    public async Task LoadSceneAsync(string scenePath, bool additive = false);
    public async Task UnloadSceneAsync(string sceneName);
    public void LoadSceneWithTransition(string scenePath, SceneTransition transition);

    [Signal] public delegate void SceneLoadStartedEventHandler(string scenePath);
    [Signal] public delegate void SceneLoadCompletedEventHandler(string scenePath);
    [Signal] public delegate void SceneUnloadedEventHandler(string sceneName);
}

4.2 - EinSoftworks.SaveSystem

Status 🔴 Incomplete
Priority 🟢 Medium-Low
Dependencies EinSoftworks.StateManagement, EinSoftworks.SceneManagement

Core Features:

public class SaveManager : Node
{
    public void SaveGame(string slotName = "default");
    public bool LoadGame(string slotName = "default");
    public void DeleteSave(string slotName);
    public string[] GetSaveSlots();

    public void RegisterSaveable(ISaveable saveable);
    public void UnregisterSaveable(ISaveable saveable);
}

public interface ISaveable
{
    string GetSaveId();
    Dictionary<string, object> GetSaveData();
    void LoadSaveData(Dictionary<string, object> data);
}

4.3 - EinSoftworks.UI

Status 🔴 Incomplete
Priority 🟢 Low
Dependencies EinSoftworks.Input, EinSoftworks.StateManagement, EinSoftworks.Events

Core Features:

public class UIManager : Control
{
    public void ShowMenu(string menuName);
    public void HideMenu(string menuName);
    public void HideAllMenus();
    public T GetMenu<T>(string menuName) where T : Control;

    [Signal] public delegate void MenuShownEventHandler(string menuName);
    [Signal] public delegate void MenuHiddenEventHandler(string menuName);
}

Implementation Strategy

Getting Started Checklist

Some high level checklist items to maybe follow while building these out.

EinSoftworks.Input

  • Set up library repository structure
  • Implement basic action queries (IsActionPressed, etc.)
  • Add input mapping and saving/loading
  • Create input buffer system
  • Build validation game: Simple character movement
  • Document all public APIs
  • Test with multiple input devices

EinSoftworks.Events

  • Implement global event system
  • Create type-safe event bus
  • Add event pooling for performance
  • Build validation game: Decoupled player-camera system
  • Document event naming conventions
  • Test event performance under load

EinSoftworks.StateManagement

  • Implement generic state machine
  • Add transition system with conditions
  • Create hierarchical state support
  • Build validation game: Character with multiple states
  • Document state design patterns
  • Test state machine performance

EinSoftworks.Physics

  • Implement raycast utilities
  • Add shape casting methods
  • Create trigger volume system
  • Build validation game: Ground detection system
  • Document physics best practices
  • Test physics performance

EinSoftworks.Camera

  • Implement base camera controller
  • Add specialized camera types (FPS, 3rd person, orbit)
  • Create camera effects (shake, zoom)
  • Build validation game: Multiple camera modes
  • Document camera usage patterns
  • Test camera smoothness and responsiveness

Validation Games Strategy

Perhaps create small, focused games to test each library combination:

Foundation Tests

  • Input Test: Character that responds to all input types
  • Event Test: Multiple systems communicating via events
  • State Test: Character with idle/walk/run/jump states

Integration Tests

  • Physics Test: Character with ground detection and jumping
  • Camera Test: Switching between camera modes
  • Combined Test: Third-person character with camera following

Advanced Tests

  • Movement Test: Full 3D character controller
  • Interaction Test: World with pickups and doors
  • Complete Game: Small game using all built libraries

Common Pitfalls to Avoid

1. Circular Dependencies

// ❌ BAD: Camera depends on Character, Character depends on Camera
public class Character { public Camera AttachedCamera; }
public class Camera { public Character Target; }

// ✅ GOOD: Use events or generic interfaces
public class Character { /* Publishes movement events */ }
public class Camera { public Node3D Target; } // Subscribes to events

2. Over-Engineering Early

// ❌ BAD: Complex inheritance hierarchy from the start
public abstract class BaseMovement<T> where T : IMovementConfig { }

// ✅ GOOD: Start simple, refactor when needed
public class CharacterController3D : CharacterBody3D { }

3. Feature Creep

  • Focus on core functionality first
  • Add advanced features only after core is solid
  • Each library should have a single, clear purpose

4. Premature Optimization

  • Build it working first
  • Profile and optimize only when needed
  • Don't sacrifice clarity for minor performance gains

Long-Term Maintenance

Versioning Strategy

  • Use semantic versioning (major.minor.patch)
  • Hardcore versioning adherence probably isn't necessary... should roughly keep versioning schema going just in case.

Documentation

  • Maintain comprehensive documentation