π― Repository Quality Improvement Report β PRD Feature-to-Code Alignment #166
Closed
Replies: 1 comment
-
|
This discussion was automatically closed because it expired on 2026-03-05T14:01:44.983Z.
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Analysis Date: 2026-03-04
Focus Area: PRD Feature-to-Code Alignment
Strategy Type: Custom (repository-specific)
Custom Area: Yes β this project has a detailed, approved PRD v1.1 covering 10 dragon costumes, double-jump, save persistence, power-up queue, audio system, and more. Mapping what's scaffolded vs. what's actually implemented reveals the highest-value next steps and prevents architecture drift.
Executive Summary
The Taekwondo Tech v2 Unity codebase has excellent foundational scaffolding β clean interfaces (
IDamageable,ICollectible,IPowerUp), a working enemy state machine with 6 states, and well-named namespaces β but critical PRD requirements are missing their implementations. Four directories (Input/,Persistence/,Costumes/,PowerUps/) contain only.gitkeepfiles. Key gaps include: no double-jump (explicitly required in Story 1), no save system (required for costume and robot-part persistence), noAudioManager(GameManager has a prominent TODO), and an input architecture inconsistency wherePlayerControllerbypassesInputManagerwith directInput.Get*calls.These gaps represent the highest-risk items for cross-platform delivery to WebGL, iOS, and Android. Addressing them now, while the codebase is young, will prevent the same accumulation of technical debt that made v1 (100K+ lines in 2 files) unmaintainable.
Full Analysis Report
Focus Area: PRD Feature-to-Code Alignment
Current State Assessment
Metrics Collected:
Input/,Persistence/,Costumes/,PowerUps/)GameManager.cs)AudioManagerclassPlayerControllerbypassesInputManagerFindings
Strengths
Interfaces.csdefinesIDamageable,ICollectible,IInteractable, andIPowerUpβ all keyed to PRD requirement IDs in XML docsEnemyStateMachineproperly implements the state patternPlayerCombat.csat 271 linesUnityEventinPlayerHealthandScoreManagerenables loose couplingPowerUpandCostumeItemβ correct forward planningAreas for Improvement
PlayerControllerusesInput.GetAxisRaw()andInput.GetButtonDown("Jump")directly, bypassing theInputManagersingleton β breaks the cross-platform abstraction layer required for touchscreen (PRD Story 1 AC: "Controls work equally well on keyboard, gamepad, and touchscreen")PlayerControlleronly handles single jump; PRD Story 1 explicitly requires "Player can jump and double-jump with satisfying physics"AudioManagerexists βGameManager.Start()has a TODO comment;Collectible.csusesAudioSource.PlayClipAtPoint()directly which will be inconsistent at scaleSaveSystemin the emptyPersistence/directory β PRD Story 2 requires "Progress saves between sessions" and Story 3 requires "Costume choice persists across sessions"CostumeManagerorDragonCostumedata model βCostumes/directory is empty despite 10 costumes + Legendary being a core PRD featureDetailed Analysis
Input Architecture Gap
PlayerCombat.cscorrectly routes input throughInputManager.Instance, subscribing toOnPunchInputandOnKickInputevents. However,PlayerController.csstill callsInput.GetAxisRaw("Horizontal")andInput.GetButtonDown("Jump")directly. This inconsistency means movement and jumping will not respond to touch or gamepad input when the platform layer is added. The fix requires addingOnMoveInput(with float parameter) andOnJumpInputevents toInputManager, and havingPlayerControllersubscribe to them.Double-Jump Missing from PRD Story 1
The
PlayerController.HandleInput()method checksInput.GetButtonDown("Jump") && _isGroundedbut has no jump count tracking. Story 1's acceptance criteria explicitly lists double-jump. This is a small, isolated change: add_jumpCountand_maxJumpsfields, and allow a second jump when_jumpCount < _maxJumps.AudioManager Needed
Collectible.cscallsAudioSource.PlayClipAtPoint(_collectSound, Camera.main.transform.position)directly. With the PRD requiring distinct SFX for 15+ events (jump, land, punch, kick, stomp, collect, hurt, defeat enemy, power-up activate, level complete, banana slip, banana deflect, 10 costume special moves), a centralizedAudioManageris essential for volume controls, mute support, and sound pooling.Save System Foundation
The
Persistence/directory is empty. Robot part collection (GameManager._robotPartsCollected) is in-memory only. Costume unlocks, robot build progress, and high scores all require persistence. ASaveSystemusingJsonUtility+Application.persistentDataPathwould cover all PRD persistence requirements.π€ Tasks for Copilot Agent
NOTE TO PLANNER AGENT: The following 5 tasks are designed for GitHub Copilot coding agent execution. Please split these into individual work items for separate processing.
Improvement Tasks
Task 1: Fix Input Routing in PlayerController
Priority: High
Estimated Effort: Small
Focus Area: Input Architecture / Cross-Platform Compatibility
Description:
PlayerController.csbypasses theInputManagersingleton and callsInput.GetAxisRaw()andInput.GetButtonDown()directly. This breaks the input abstraction layer thatPlayerCombat.cscorrectly uses. TheInputManagerneeds a float-parameterized move event and thePlayerControllershould subscribe to it.Acceptance Criteria:
InputManagerexposespublic UnityEvent(float) OnMoveInputfor horizontal movement (-1 to 1)InputManager.Update()invokesOnMoveInputeach frame with the current horizontal axis valuePlayerControllersubscribes toInputManager.Instance.OnMoveInputandInputManager.Instance.OnJumpInputinOnEnable/OnDisablePlayerControllerno longer callsInput.GetAxisRaw()orInput.GetButtonDown()directlyCode Region:
Unity/Assets/Scripts/Player/PlayerController.cs,Unity/Assets/Scripts/Core/InputManager.csIn Unity/Assets/Scripts/Core/InputManager.cs, add a new UnityEvent(float) called OnMoveInput that fires each Update with the current horizontal axis value. Also ensure OnJumpInput is already present (it is). Then update Unity/Assets/Scripts/Player/PlayerController.cs to remove the direct Input.GetAxisRaw("Horizontal") and Input.GetButtonDown("Jump") calls. Instead, subscribe to InputManager.Instance.OnMoveInput in OnEnable (storing the float as _moveInput) and subscribe to InputManager.Instance.OnJumpInput in OnEnable (calling Jump() when grounded). Unsubscribe in OnDisable. Keep all existing movement physics logic unchanged.Task 2: Implement Double-Jump in PlayerController
Priority: High
Estimated Effort: Small
Focus Area: Core Gameplay / PRD Story 1 Compliance
Description:
PRD Story 1 acceptance criteria explicitly requires "Player can jump and double-jump with satisfying physics." The current
PlayerController.HandleInput()only allows jumping when_isGrounded, with no jump count tracking.Acceptance Criteria:
PlayerControllerhas a[SerializeField] private int _maxJumps = 2field_jumpCountcounter resets to 0 when the player lands (becomes grounded)_jumpCount < _maxJumps(not just_isGrounded)_jumpCount_jumpForce) for feelIsJumpingandIsFallingproperties continue to work correctlyPlayerAnimatorcan distinguish first vs. second jump if needed (exposeJumpCountproperty)Code Region:
Unity/Assets/Scripts/Player/PlayerController.csTask 3: Create AudioManager Singleton
Priority: High
Estimated Effort: Medium
Focus Area: Audio Architecture / PRD Story 7 Compliance
Description:
GameManager.Start()has a TODO for AudioManager initialization.Collectible.cscallsAudioSource.PlayClipAtPoint()directly. PRD Story 7 requires 15+ distinct SFX events and separate music/SFX volume controls. A centralizedAudioManageris needed to support this at scale.Acceptance Criteria:
Unity/Assets/Scripts/Core/AudioManager.csin namespaceTaekwondoTech.CoreGameManager(persistent across scenes viaDontDestroyOnLoad)PlaySFX(AudioClip clip)method plays a one-shot sound effectPlayMusic(AudioClip clip, bool loop = true)method plays background musicStopMusic()method stops background musicSFXVolumeandMusicVolumefloat properties (0β1) with correspondingAudioSourcereferencesIsMutedbool property that silences all audio when trueGameManager.Start()TODO comment is replaced withAudioManager.Instancecheck/initialization noteCollectible.csupdated to callAudioManager.Instance.PlaySFX(_collectSound)if AudioManager exists, falling back gracefully if nullCode Region:
Unity/Assets/Scripts/Core/AudioManager.cs(new file),Unity/Assets/Scripts/Core/GameManager.cs,Unity/Assets/Scripts/Collectibles/Collectible.csTask 4: Create SaveSystem in Persistence Directory
Priority: Medium
Estimated Effort: Medium
Focus Area: Persistence / PRD Story 2 & 3 Compliance
Description:
The
Persistence/directory is empty. PRD Story 2 requires robot-part progress to save between sessions; Story 3 requires costume unlock state and active costume to persist. CurrentlyGameManager._robotPartsCollectedis in-memory only and resets on launch.Acceptance Criteria:
Unity/Assets/Scripts/Persistence/SaveSystem.csin namespaceTaekwondoTech.PersistenceSaveDataserializable class with fields:int robotPartsCollected,int[] unlockedCostumeIds,int activeCostumeId,int highScoreSaveSystem.Save(SaveData data)writes JSON toApplication.persistentDataPath/save.jsonSaveSystem.Load()returns aSaveData(or default/new if file doesn't exist)SaveSystem.Delete()removes the save fileGameManagerupdated to callSaveSystem.Load()on startup and persist_robotPartsCollectedon changeCode Region:
Unity/Assets/Scripts/Persistence/SaveSystem.cs(new file),Unity/Assets/Scripts/Core/GameManager.csCreate Unity/Assets/Scripts/Persistence/SaveSystem.cs with namespace TaekwondoTech.Persistence. Define a [System.Serializable] class SaveData with fields: public int robotPartsCollected = 0, public int[] unlockedCostumeIds = new int[0], public int activeCostumeId = -1, public int highScore = 0. Implement a static class SaveSystem with: private static readonly string SavePath = System.IO.Path.Combine(Application.persistentDataPath, "save.json"); public static void Save(SaveData data) that serializes via JsonUtility.ToJson and writes to SavePath; public static SaveData Load() that reads SavePath if it exists and returns JsonUtility.FromJson(SaveData), otherwise returns new SaveData(); public static void Delete() that calls File.Delete(SavePath) if the file exists. Add XML summary docs. Then update GameManager.cs: in Start(), call var save = SaveSystem.Load() and set _robotPartsCollected = save.robotPartsCollected; in IncrementRobotParts(), after incrementing, call SaveSystem.Save(new SaveData { robotPartsCollected = _robotPartsCollected }).Task 5: Scaffold CostumeManager and DragonCostume Data Model
Priority: Low
Estimated Effort: Small
Focus Area: Costume System Foundation / PRD Story 3 Compliance
Description:
The
Costumes/directory is empty. PRD Story 3 requires 10 dragon costumes + Legendary Mode. TheCollectibleType.CostumeItemenum value already exists, indicating planned integration. Scaffolding the data model and manager now prevents future architecture debt.Acceptance Criteria:
DragonCostumeData.csScriptableObject inUnity/Assets/Scripts/Costumes/with fields:int costumeId,string costumeName,CostumeElement element,string specialMoveName,Sprite costumeSprite,AudioClip specialMoveSound,string unlockDescriptionCostumeElementenum with values:Fire,Water,Earth,Wind,Lightning,Ice,Shadow,Light,Nature,Cosmic,LegendaryCostumeManager.csMonoBehaviour singleton inUnity/Assets/Scripts/Costumes/with[SerializeField] DragonCostumeData[] _allCostumesCostumeManager.GetCostume(int id)returns the matchingDragonCostumeDataor nullCostumeManager.ActiveCostumeIdint property with getter/setter (setter triggersOnCostumeChangedUnityEvent)Code Region:
Unity/Assets/Scripts/Costumes/DragonCostumeData.cs(new),Unity/Assets/Scripts/Costumes/CostumeManager.cs(new)Create Unity/Assets/Scripts/Costumes/DragonCostumeData.cs with namespace TaekwondoTech.Costumes. Define a public enum CostumeElement { Fire, Water, Earth, Wind, Lightning, Ice, Shadow, Light, Nature, Cosmic, Legendary }. Define a [CreateAssetMenu(fileName = "DragonCostume", menuName = "TaekwondoTech/Dragon Costume")] public class DragonCostumeData : ScriptableObject with SerializeField fields: int _costumeId, string _costumeName, CostumeElement _element, string _specialMoveName, Sprite _costumeSprite, AudioClip _specialMoveSound, string _unlockDescription. Add public readonly properties for each. Then create Unity/Assets/Scripts/Costumes/CostumeManager.cs with namespace TaekwondoTech.Costumes. Implement a MonoBehaviour singleton (DontDestroyOnLoad pattern). Add [SerializeField] private DragonCostumeData[] _allCostumes. Add public DragonCostumeData GetCostume(int id) that returns the matching item from _allCostumes where costumeId == id, or null. Add private int _activeCostumeId = -1 and public UnityEvent(int) OnCostumeChanged. Add public int ActiveCostumeId property whose setter sets _activeCostumeId and invokes OnCostumeChanged. Add XML summary docs.π Historical Context
Previous Focus Areas
π― Recommendations
Immediate Actions (This Week)
Short-term Actions (This Month)
Long-term Actions (This Quarter)
IPowerUpconcrete classes inPowerUps/directoryInput.*usage inInputManagerwithUnityEngine.InputSystem(New Input System) for full cross-platform robustnessSaveSystemwithCostumeManagerandScoreManagerfor complete session persistenceπ Success Metrics
Track these metrics to measure improvement in PRD Feature-to-Code Alignment:
Input.*calls outside InputManager: 2 β 0Next Steps
Costumes/andPowerUps/directories have implementationsGenerated by Repository Quality Improvement Agent
Next analysis: 2026-03-05 β Focus area will be selected based on diversity algorithm
References: Β§22672419084
Beta Was this translation helpful? Give feedback.
All reactions