Fix card cleanup after dismissing minigame

This commit is contained in:
Michal Pikulski
2025-12-16 17:35:05 +01:00
parent b516b093af
commit ba1e506bc6
4 changed files with 154 additions and 6 deletions

View File

@@ -23,6 +23,7 @@ namespace Minigames.CardSorting.Controllers
private readonly GameObject cardPrefab;
private readonly GameObject garbagePrefab;
private readonly ICardSortingSettings settings;
private readonly Transform spawnContainer; // Container for all spawned items
private List<SortableItem> activeItems = new List<SortableItem>();
private HashSet<SortableItem> missedItems = new HashSet<SortableItem>(); // Items past visual end, moving to despawn
@@ -48,7 +49,8 @@ namespace Minigames.CardSorting.Controllers
Transform despawnPoint,
GameObject cardPrefab,
GameObject garbagePrefab,
ICardSortingSettings settings)
ICardSortingSettings settings,
Transform spawnContainer)
{
this.spawnPoint = spawnPoint;
this.endPoint = endPoint;
@@ -56,6 +58,7 @@ namespace Minigames.CardSorting.Controllers
this.cardPrefab = cardPrefab;
this.garbagePrefab = garbagePrefab;
this.settings = settings;
this.spawnContainer = spawnContainer;
this.currentSpeed = settings.InitialBeltSpeed;
this.lastSpawnedItem = null; // No items spawned yet
@@ -169,7 +172,7 @@ namespace Minigames.CardSorting.Controllers
float randomOffsetY = Random.Range(settings.SpawnOffsetY.x, settings.SpawnOffsetY.y);
Vector3 spawnPos = spawnPoint.position + new Vector3(0f, randomOffsetY, 0f);
GameObject obj = Object.Instantiate(garbagePrefab, spawnPos, Quaternion.identity);
GameObject obj = Object.Instantiate(garbagePrefab, spawnPos, Quaternion.identity, spawnContainer);
SortableItem item = obj.GetComponent<SortableItem>();
if (item != null)
@@ -212,7 +215,7 @@ namespace Minigames.CardSorting.Controllers
float randomOffsetY = Random.Range(settings.SpawnOffsetY.x, settings.SpawnOffsetY.y);
Vector3 spawnPos = spawnPoint.position + new Vector3(0f, randomOffsetY, 0f);
GameObject obj = Object.Instantiate(cardPrefab, spawnPos, Quaternion.identity);
GameObject obj = Object.Instantiate(cardPrefab, spawnPos, Quaternion.identity, spawnContainer);
SortableItem item = obj.GetComponent<SortableItem>();
if (item != null)
@@ -497,6 +500,39 @@ namespace Minigames.CardSorting.Controllers
Debug.Log("[ConveyorBeltController] Conveyor stopped - all items disabled");
}
/// <summary>
/// Destroy all active items on the conveyor.
/// Called when quitting to main level to cleanup spawned items.
/// </summary>
public void DestroyAllItems()
{
Debug.Log($"[ConveyorBeltController] Destroying {activeItems.Count} active items");
// Unsubscribe from all item events and destroy them
for (int i = activeItems.Count - 1; i >= 0; i--)
{
var item = activeItems[i];
if (item != null)
{
// Unsubscribe from events
item.OnItemDroppedInBox -= HandleItemDroppedInBox;
item.OnItemDroppedOnFloor -= HandleItemDroppedOnFloor;
item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor;
item.OnDragStarted -= HandleItemDragStarted;
// Destroy the game object
Object.Destroy(item.gameObject);
}
}
// Clear all tracking
activeItems.Clear();
missedItems.Clear();
lastSpawnedItem = null;
Debug.Log("[ConveyorBeltController] All items destroyed and tracking cleared");
}
}
}

View File

@@ -24,6 +24,7 @@ namespace Minigames.CardSorting.Core
[SerializeField] private GameObject sortableCardPrefab;
[SerializeField] private GameObject sortableGarbagePrefab;
[SerializeField] private SortingBox[] sortingBoxes;
[SerializeField] private Transform spawnedItemsContainer; // Container for all spawned items (optional, will auto-create if null)
[Header("Effects")]
[SerializeField] private CinemachineImpulseSource impulseSource; // Screen shake on incorrect sort
@@ -45,7 +46,8 @@ namespace Minigames.CardSorting.Core
conveyorDespawnPoint,
sortableCardPrefab,
sortableGarbagePrefab,
_settings
_settings,
GetOrCreateSpawnContainer()
);
// Public accessor for states to check game over status
@@ -91,6 +93,26 @@ namespace Minigames.CardSorting.Core
Logging.Debug("[SortingGameManager] Initialized with settings");
}
/// <summary>
/// Get or create the container for spawned items.
/// Ensures all cards/garbage are organized in the hierarchy.
/// </summary>
private Transform GetOrCreateSpawnContainer()
{
if (spawnedItemsContainer != null)
return spawnedItemsContainer;
// Auto-create container if not assigned
var containerObj = new GameObject("[Spawned Items]");
spawnedItemsContainer = containerObj.transform;
spawnedItemsContainer.SetParent(transform); // Parent to manager for organization
spawnedItemsContainer.localPosition = Vector3.zero;
Logging.Debug("[SortingGameManager] Auto-created spawned items container");
return spawnedItemsContainer;
}
internal override void OnManagedStart()
{
// Subscribe to score events
@@ -247,6 +269,54 @@ namespace Minigames.CardSorting.Core
StartCoroutine(EndGameSequence());
}
/// <summary>
/// Cleanup all dynamically spawned items (cards/garbage).
/// Called when quitting to main level to prevent items from lingering on screen.
/// </summary>
public void CleanupAllItems()
{
Logging.Debug("[SortingGameManager] Cleaning up all spawned items");
// Tell conveyor to destroy all active items
// Use the property which handles lazy initialization
Conveyor?.DestroyAllItems();
// Also destroy any remaining children in the spawn container
if (spawnedItemsContainer != null)
{
int childCount = spawnedItemsContainer.childCount;
if (childCount > 0)
{
Logging.Debug($"[SortingGameManager] Cleaning up {childCount} items from spawn container");
for (int i = childCount - 1; i >= 0; i--)
{
var child = spawnedItemsContainer.GetChild(i);
if (child != null)
{
Destroy(child.gameObject);
}
}
}
}
// Final safety check: search for any orphaned items in case of edge cases
var allItems = FindObjectsByType<SortableItem>(FindObjectsSortMode.None);
if (allItems.Length > 0)
{
Logging.Warning($"[SortingGameManager] Found {allItems.Length} orphaned items, cleaning up...");
foreach (var item in allItems)
{
if (item != null && item.gameObject != null)
{
Logging.Debug($"[SortingGameManager] Destroying orphaned item: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
Destroy(item.gameObject);
}
}
}
}
private IEnumerator EndGameSequence()
{
// Calculate rewards

View File

@@ -108,6 +108,13 @@ namespace Minigames.CardSorting.UI
private async void OnCloseClicked()
{
// Cleanup all spawned items before transitioning
var gameManager = SortingGameManager.Instance;
if (gameManager != null)
{
gameManager.CleanupAllItems();
}
// Hide screen
if (canvasGroup != null)
{