Add null check for active cell in AIPilot.UpdateCellContent()#130
Open
Shombith03 wants to merge 43 commits into
Open
Add null check for active cell in AIPilot.UpdateCellContent()#130Shombith03 wants to merge 43 commits into
Shombith03 wants to merge 43 commits into
Conversation
- Add GameplaySFXCategory enum with 11 categories (BlockDestroy, ShieldActivate, ShieldDeactivate, MineExplode, ProjectileLaunch, CrystalCollect, VesselImpact, GameEnd, ScoreReveal, PauseOpen, PauseClose) and PlayGameplaySFX method to AudioSystem with serialized AudioClip fields for each UI sounds: - ModalWindowManager: OpenView on ModalWindowIn, CloseView on ModalWindowOut (covers all 8+ modals: Profile, Settings, ArcadeConfig, HangarTraining, etc.) - NavLink.OnClick: SwitchView sound on tab/view switching - ArcadeScreen.ToggleView: SwitchView sound on Loadout/Explore toggle - PauseMenu: PauseOpen/PauseClose gameplay SFX on show/hide - PurchaseConfirmationModal.Confirm: Confirmed sound - ArcadeGameConfigureModal: Confirmed on config confirm, LetsGo on start game - All game launch buttons: LetsGo sound (ArcadeExploreView, ArcadeLoadoutView, DailyChallengeModal, FactionMissionModal, HangarTrainingModal) Gameplay sounds: - Prism.Explode/Implode: BlockDestroy SFX on block destruction - PrismStateManager: ShieldActivate/ShieldDeactivate SFX on shield state changes - Mine.Explode: MineExplode SFX - Projectile.LaunchProjectile: ProjectileLaunch SFX - VesselImpactor: CrystalCollect for crystal pickups, VesselImpact for prism/skimmer hits - EndGameCinematicController: GameEnd on winner calculated, ScoreReveal on score display https://claude.ai/code/session_01LT3ivtpFxXy6tx9SrQvP6o
Extends the GameplaySFXCategory with 4 new categories: - GunFire, BoostActivate, Explosion, CreatureDeath Gameplay sounds added: - FireGunActionExecutor.Fire: GunFire SFX on weapon discharge - ConsumeBoostActionExecutor.Consume: BoostActivate SFX on boost use - ChargeBoostActionExecutor.BeginDischarge: BoostActivate SFX on charged boost release - AOEExplosion.Detonate: Explosion SFX on area-of-effect detonation - LifeForm.Die: CreatureDeath SFX when flora/fauna entities are killed https://claude.ai/code/session_01LT3ivtpFxXy6tx9SrQvP6o
- GameCard: OptionClick on card click and favorite toggle - SwitchToggle: OptionClick on toggle state change - ProfileIconSelectButton: OptionClick on icon selection - GameplayRewardButton: Confirmed on reward claim - DailyRewardCard: Confirmed on free claim and ad watch reward https://claude.ai/code/session_01LT3ivtpFxXy6tx9SrQvP6o
Wire new SFX categories (DriftStart, DriftEnd, EnergyGain, SpeedBurst) into the gameplay systems that define the squirrel feel: - Drift engage/disengage sounds in DriftActionSO and legacy DriftAction - Energy gain chime when squirrel collects from NudgeShards - Speed burst whoosh on ModifyVelocityActionSO activation - Boost activate sound on simple BoostActionSO (was missing) https://claude.ai/code/session_01LT3ivtpFxXy6tx9SrQvP6o
…efab Generate WAV audio files for DriftStart, DriftEnd, EnergyGain, and SpeedBurst sound effects using synthesized tones. Wire them into the AudioSystem prefab so the serialized fields reference the new clips. Also explicitly declare the other gameplay SFX slots in the prefab (currently unassigned). https://claude.ai/code/session_01LT3ivtpFxXy6tx9SrQvP6o
All GameplaySFXCategory slots were set to {fileID: 0} (null), causing
PlayGameplaySFX to silently skip every sound. Map existing audio assets
to each category using best-fit matches from the Sounds library:
- BlockDestroy/VesselImpact → Crystal_Collision_Amplified
- CrystalCollect → Crystal_Glass
- MineExplode/Explosion → END GAME crash
- GameEnd → END GAME after crash
- ProjectileLaunch → Fly By 06_1
- GunFire → Click 12
- ScoreReveal → Data 24
- CreatureDeath → crys_enemlayer_var3_MN1-001
- ShieldActivate → Confirmed (menu)
- ShieldDeactivate/PauseClose → CloseView (menu)
- PauseOpen → OpenView (menu)
- BoostActivate → Upgrade (menu)
Also add debug warning log when a clip is still missing so it's no
longer silently swallowed.
https://claude.ai/code/session_01LT3ivtpFxXy6tx9SrQvP6o
…not yet assigned cellData.Cell can be null when UpdateCellContent is called from Initialize() before the game cell has been set up. Added null guard for activeCell. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…scoring log ShapeSignSpawner: Replaced dynamic Instantiate/Destroy with simple enable/disable of pre-placed scene GameObjects. Signs are now positioned and oriented by the designer in the editor. ShapeSign: Added OnEnable reset — clears _selected state, re-enables button interactability, snaps position back to base (undoing bob offset). SinglePlayerFreestyleController: ClearPlayerTrails() called immediately after SetPlayersActive() in OnCountdownTimerEnded so trail spawners never run in the lobby. ShowSigns() call takes no arguments now. ShapeDrawingManager: Enhanced FinishShape() log with par time, sample count, waypoint count. Added TakeDebugScreenshot() (F12 key or wire to UI button) — saves PNG to Application.persistentDataPath/Screenshots/. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…reestyle teardown Three critical performance fixes for explosion scaling: 1. PrismAOERegistry: Cap new prism hits to 48/frame per explosion. Previously 2000+ prisms destroyed in one frame (426ms spike). Now spreads across ~47 frames — unprocessed hits are re-found by the Burst spatial query on subsequent frames automatically. 2. PrismEffectsManager: Replace List with HashSet for active VFX tracking. Registration/unregistration was O(n) Contains + O(n) Remove per item. With 2000+ active VFX completing, the completion loop was O(n²). Now O(1) for all operations. 3. ExplosionImpactor: Cache and reuse _batchHitTracker HashSet instead of allocating new HashSet<int>(256) per explosion start. Also merges the freestyle connecting screen fix (scene teardown safety): - PrismEffectsManager._instanceDestroyed prevents auto-creating during teardown - Null-propagation on EnsureInstance calls in PrismExplosion/PrismImplosion - MinigameHUDView null check on playerScoreContainer https://claude.ai/code/session_01FnQQDjDMDPfpEPvrvXNtJN
…racy + ghost line
Shape Orientation:
- Added shapeOrientationEuler field (default -90,0,0) to ShapeDrawingManager
that rotates XY-plane shape waypoints to horizontal XZ plane so they face
the top-down reveal camera correctly.
- All waypoint/position calculations now go through rotation-aware helpers
(GetWorldWaypoint, GetAllWorldWaypoints, GetWorldPlayerStart).
Preview Cinematic Flow:
- StartShapeSequence now runs a two-phase flow:
Phase 1 (PreviewSequence): place player at start → lock input (IsStationary)
→ draw ghost shape → camera flies to top-down overview → holds → transitions
back to behind player → fires OnPreviewComplete event.
Phase 2 (BeginDrawing): controller shows Ready button on OnPreviewComplete,
player clicks Ready → controller calls BeginDrawing() → releases input,
starts timer, spawns first crystal.
- SinglePlayerFreestyleController overrides OnReadyClicked_ to detect shape-
prep state and call BeginDrawing() instead of normal countdown.
Input System Fix:
- Replaced UnityEngine.Input.GetKeyDown (legacy) with
Keyboard.current[Key].wasPressedThisFrame (new Input System package).
- Screenshot key field changed from KeyCode to Key enum.
Accuracy Fix:
- Root cause: the legacy Input.GetKeyDown threw InvalidOperationException
every frame in Update(), preventing SamplePlayerPosition() from ever running
→ 0 path samples → 0% accuracy.
- Also: accuracy calculation now uses rotation-aware waypoints matching actual
crystal positions.
Ghost Line Fix:
- Ghost line now uses rotation-aware waypoints (was rendering in XY plane,
invisible from most camera angles). Shader fallback chain added:
Sprites/Default → Universal Render Pipeline/Unlit.
Other:
- Default shapeScale increased from 1 to 3 for better visibility.
- Added _drawingStarted flag to prevent Update from running guide line /
sampling before BeginDrawing is called.
- Camera acquire/release extracted to helper methods (AcquireCamera,
ReleaseCamera) reused by both preview and reveal cinematics.
https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…hanger - Use IVesselStatus via IVessel.VesselStatus instead of GetComponent (root cause of 0% accuracy / 0 path samples — component on different GO) - Wire countdown timer into shape flow: Ready → countdown → BeginDrawing (vessel stays locked until countdown finishes) - Compute player spawn from first waypoint (30u behind, facing crystal) - Add SnowChanger prefab integration for directional shards - Fix all null checks from Unity truthy to != null for interface type https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
ProfileModal was routing through the disabled PlayFab PlayerDataController instead of the active UGS PlayerDataService, so name changes were silently dropped. ArcadeProfileWidget and ProfileIconSelectView lacked a singleton fallback for PlayerDataService (whose Awake detaches from hierarchy via DontDestroyOnLoad, breaking serialized Inspector refs) and gated saves on IsInitialized when the service is usable as soon as CurrentProfile exists. Default display name changed from static "Pilot" to "Pilot#XXXX" with a random 4-digit suffix so new players get unique names out of the box. https://claude.ai/code/session_018uU3m2F5XVUMoynp8jxdM4
Default name is now "Pilot1234" instead of "Pilot#1234". https://claude.ai/code/session_018uU3m2F5XVUMoynp8jxdM4
…-1ZgoJ Claude/add missing sounds 1 zgo j
…teardown fix The HashSet conversion broke explosion VFX. Reverted to original List-based tracking with identical processing flow. The only addition is the _instanceDestroyed pattern from the freestyle fix branch to prevent NullReferenceExceptions during scene teardown. The per-frame damage cap in PrismAOERegistry (48 hits/frame) and the cached HashSet in ExplosionImpactor remain — those are the primary performance wins. https://claude.ai/code/session_01FnQQDjDMDPfpEPvrvXNtJN
The _instanceDestroyed flag + ?. null-propagation operators were causing PrismExplosion/PrismImplosion VFX to silently skip registration with PrismEffectsManager. VFX objects spawned from the pool with team colors applied but never received frame updates, appearing as static colored blocks replacing destroyed prisms. - Remove _instanceDestroyed static flag and ResetStatics from PrismEffectsManager - Revert EnsureInstance() to always auto-create if no instance exists - Revert ?. to . on EnsureInstance().Register calls in PrismExplosion/PrismImplosion https://claude.ai/code/session_01FnQQDjDMDPfpEPvrvXNtJN
…ale to 7 - Add ScriptableEventNoParam field (onReturnShapePrismsEvent) raised in ExitShapeMode before ClearTrails — follows SOLID by decoupling pool return from ShapeDrawingManager via SO event channel - User wires EventListenerNoParam on shape prisms → Prism.ReturnToPool() - Increase default shapeScale from 3 to 7 (lightning blocks too close) - Move ClearTrails from ContinueFromReveal into ExitShapeMode (single exit path: raise event → return to pool → clear trail references) https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
ShapeSign: Remove bob/spin animation — signs stay exactly where placed in the scene editor. No script modifies position at any point. ShapeDrawingManager: - shapeScale default → 10 (lightning crystals too close at smaller scale) - Defensive StopSpawn() in BeginDrawing before releasing vessel - Stop player (IsStationary = true) when shape completes - Show EndShapeDetailHUD after reveal camera pan - On exit: respawn player at shape start, freeze, snap camera, then fire OnFreestyleResumed so controller shows connecting panel - Null _activeShape after using it for respawn position EndShapeDetailHUD (new): - Displays shape name, elapsed/par time, accuracy %, star rating - Screenshot button → ShapeDrawingManager.TakeDebugScreenshot - Exit button → hides HUD, exits shape mode - User creates UI layout in GameCanvas, wires TMP_Text + Button refs SinglePlayerFreestyleController: - Add MiniGameHUD reference for connecting panel flow - _returningFromShape flag: after shape exit, Ready enters lobby instead of calling SetPlayersActive again - OnShapeDrawingFinished: stop vessel, snap camera, show connecting panel via miniGameHUD.ShowConnectingFlow() MiniGameHUD: - Add public ShowConnectingFlow() wrapper for ResetForReplay() https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…t event ShapeSign: - Store position/rotation in Awake, enforce via LateUpdate every frame - Nothing (physics, parent changes, other scripts) can move signs from their scene-placed positions - OnSignButtonPressed uses _lockedPosition instead of transform.position ShapeDrawingManager — removed ALL VesselPrismController manipulation: - StartShapeSequence: fires onShapeGameModeStarted event instead of StopSpawn/ClearTrails. Just sets IsStationary = true. - BeginDrawing: just sets IsStationary = false. Vessel's natural prism spawning takes over. - HandleCrystalHit: removed StartSpawn/StopSpawn per-segment toggle. Keeps tracking/scoring logic only. - FinishShape: removed StopSpawn. Just sets IsStationary = true. - ExitShapeMode: removed ClearTrails. Uses onReturnShapePrismsEvent only (SO event for prism pool return). New ScriptableEventNoParam field: onShapeGameModeStarted - Fired when entering shape mode for a clean slate - User wires EventListenerNoParam on prisms → ReturnToPool https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
- RevealSequence: hide vesselHUD when showing EndShapeDetailHUD - ExitShapeMode: restore vesselHUD after cleanup - Controller returning-from-shape: explicitly ShowHUD when re-entering lobby (ResetForReplay hides it, SetPlayersActive isn't called again) https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
LateUpdate now faces the sign toward Camera.main while keeping position locked and the sign upright (zeroed Y look direction). Removed the locked rotation that prevented any facing behavior. Also: ShapeSignSpawner should be enabled in scene, its Signs list populated with the sign GameObjects, and the "(Removed)" missing script reference deleted from each sign. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…d FreestyleSign - Remove LateUpdate billboard rotation from ShapeSign — signs stay at their placed orientation - Remove IsStationary=true from FinishShape and ExitShapeMode so player keeps flying after shape completion - OnShapeDrawingFinished now teleports directly to lobby instead of showing connecting flow - Remove dead _returningFromShape field and its OnCountdownTimerEnded branch - Add FreestyleSign + FreestyleSignEvents for starting normal segment-spawner gameplay via a clickable sign - Wire FreestyleSignEvents into SinglePlayerFreestyleController https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…attern Vessel/projectile collision activates the sign instead of a UI button. Includes ResetTrigger() for lobby re-entry. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
ShapeSign & FreestyleSign: - Switch from UI Button to OnTriggerEnter (same as ModeSelectTrigger) - Lock position, billboard toward player camera in LateUpdate - Add ResetTrigger() for lobby re-entry SinglePlayerFreestyleController: - Add _isFreestylePrep state so freestyle follows the same flow as shape mode: freeze player → teleport to spawn → connecting panel → ready button → countdown → start gameplay - Route all null-shapeDef selections through StartFreestylePrep https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
ShapeSign & FreestyleSign: - Remove all LateUpdate, _lockedPosition, billboard, and transform manipulation. Signs are purely editor-positioned, just enable/disable. SinglePlayerFreestyleController: - Move gameData.StartTurn() out of ExitLobby() into BeginFreestyle() and StartShapeMode() so systems are enabled BEFORE the turn event fires. LocalCrystalManager.OnEnable subscribes to OnMiniGameTurnStarted, so it must be enabled before StartTurn() for crystals (and downstream flora/fauna) to spawn. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
Root cause: modeTriggers in the scene ARE the HeartShapeSign prefab instances (ModeSelectTrigger components added to them). EnterLobby() was recalculating position/rotation/scale every time, overriding the editor-placed transforms. Fix: - Remove all transform manipulation from EnterLobby() — just enable/disable and reset triggers - Remove triggerRingRadius, triggerScale, triggerForwardOffset fields - Restore ShapeSignSpawner field names to match scene serialized data (signEntries, ringRadius, height, faceCenter, signScale, origin) - Signs spawn once on first ShowSigns(), then just toggle visibility https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
The ModeSelectTrigger components live directly on the sign prefab instances in the scene. The controller just enables/disables them. ShapeSignSpawner was a dead middleman with no effect (its GO was disabled in the scene anyway). https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
Removed SpawnSigns() and all instantiation. Kept serialized field names (signEntries, ringRadius, etc.) so scene data isn't orphaned. ShowSigns/HideSigns now just toggle the prefab references directly. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
…s-vFvfH Optimize explosion processing and reduce GC allocations
ShapeSignSpawner was unnecessary indirection. Signs are editor-placed children of a parent GameObject. Controller now holds a signsParent reference and toggles SetActive in EnterLobby/ExitLobby, same pattern as modeTriggers. This fixes the two new signs not getting disabled. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
Resolved trivial conflict in MinigameHUDView.ClearPlayerList — kept development's explicit null check style. https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq
….1:38106/git/froglet-studio/Cosmic-Shore into claude/shape-signs-face-player-INiJp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Added a defensive null check for the active cell before attempting to access cell items in the
UpdateCellContent()method of the AIPilot class.Key Changes
activeCellvariable after retrieval fromcellData.CellImplementation Details
The new check
if (activeCell == null) return;is placed immediately after retrieving the active cell and before accessingcellData.CellItems, ensuring the method exits gracefully if the cell data is not ready rather than throwing an exception downstream.https://claude.ai/code/session_01Y1d7YaQBxppMr54ZGShjVq