Working minigame?
This commit is contained in:
@@ -11,19 +11,29 @@ namespace Minigames.CardSorting.Controllers
|
||||
/// <summary>
|
||||
/// Non-MonoBehaviour controller for conveyor belt logic.
|
||||
/// Handles spawning, speed, item lifecycle.
|
||||
/// Owns item tracking and emits events when items fall off or are sorted.
|
||||
/// Parallel to CornerCardManager in card system.
|
||||
/// </summary>
|
||||
public class ConveyorBeltController
|
||||
{
|
||||
private readonly Transform spawnPoint;
|
||||
private readonly Transform endPoint;
|
||||
private readonly Transform endPoint; // Visual end - scoring happens here
|
||||
private readonly Transform despawnPoint; // Off-screen - destruction happens here
|
||||
private readonly GameObject cardPrefab;
|
||||
private readonly GameObject garbagePrefab;
|
||||
private readonly ICardSortingSettings settings;
|
||||
|
||||
private List<SortableItem> activeItems = new List<SortableItem>();
|
||||
private HashSet<SortableItem> missedItems = new HashSet<SortableItem>(); // Items past visual end, moving to despawn
|
||||
private float currentSpeed;
|
||||
private float nextSpawnTime;
|
||||
private SortableItem lastSpawnedItem; // Track last spawned item for distance-based spawning
|
||||
|
||||
// Events - conveyor owns item lifecycle
|
||||
public event System.Action<SortableItem> OnItemSpawned; // Fired when new item spawns
|
||||
public event System.Action<SortableItem> OnItemFellOffBelt; // Fired at visual end (endPoint)
|
||||
public event System.Action<SortableItem> OnItemDespawned; // Fired at despawn point (destruction)
|
||||
public event System.Action<SortableItem, SortingBox, bool> OnItemSorted; // item, box, correct
|
||||
public event System.Action<SortableItem> OnItemDroppedOnFloor; // Fired when dropped outside any box
|
||||
|
||||
public float CurrentSpeed => currentSpeed;
|
||||
public int ActiveItemCount => activeItems.Count;
|
||||
@@ -31,36 +41,59 @@ namespace Minigames.CardSorting.Controllers
|
||||
public ConveyorBeltController(
|
||||
Transform spawnPoint,
|
||||
Transform endPoint,
|
||||
Transform despawnPoint,
|
||||
GameObject cardPrefab,
|
||||
GameObject garbagePrefab,
|
||||
ICardSortingSettings settings)
|
||||
{
|
||||
this.spawnPoint = spawnPoint;
|
||||
this.endPoint = endPoint;
|
||||
this.despawnPoint = despawnPoint;
|
||||
this.cardPrefab = cardPrefab;
|
||||
this.garbagePrefab = garbagePrefab;
|
||||
this.settings = settings;
|
||||
|
||||
this.currentSpeed = settings.InitialBeltSpeed;
|
||||
this.nextSpawnTime = 0f;
|
||||
this.lastSpawnedItem = null; // No items spawned yet
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update belt speed and check for items falling off.
|
||||
/// Update belt speed, check for items falling off, and handle distance-based spawning.
|
||||
/// </summary>
|
||||
public void Update(float deltaTime, float gameProgress)
|
||||
{
|
||||
UpdateBeltSpeed(gameProgress);
|
||||
CheckItemsOffBelt();
|
||||
CheckDistanceBasedSpawn(gameProgress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to spawn an item if enough time has passed.
|
||||
/// Check if we should spawn a new item based on distance from last spawn.
|
||||
/// Items spawn when last item has moved far enough from spawn point.
|
||||
/// </summary>
|
||||
public SortableItem TrySpawnItem(float currentTime, float gameProgress)
|
||||
private void CheckDistanceBasedSpawn(float gameProgress)
|
||||
{
|
||||
if (currentTime < nextSpawnTime) return null;
|
||||
// If no items spawned yet, spawn immediately
|
||||
if (lastSpawnedItem == null)
|
||||
{
|
||||
SpawnNewItem(gameProgress);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if last spawned item is far enough from spawn point
|
||||
float distanceFromSpawn = Mathf.Abs(lastSpawnedItem.transform.position.x - spawnPoint.position.x);
|
||||
|
||||
if (distanceFromSpawn >= settings.SpawnDistance) // Using InitialSpawnInterval as distance threshold
|
||||
{
|
||||
SpawnNewItem(gameProgress);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawn a new item at the spawn point.
|
||||
/// </summary>
|
||||
private SortableItem SpawnNewItem(float gameProgress)
|
||||
{
|
||||
// Weighted random: card or garbage?
|
||||
float totalWeight = settings.NormalCardWeight + settings.RareCardWeight +
|
||||
settings.LegendCardWeight + settings.GarbageWeight;
|
||||
@@ -93,20 +126,15 @@ namespace Minigames.CardSorting.Controllers
|
||||
item.Context.ConveyorSpeed = currentSpeed;
|
||||
|
||||
activeItems.Add(item);
|
||||
ScheduleNextSpawn(gameProgress);
|
||||
lastSpawnedItem = item; // Track for distance-based spawning
|
||||
|
||||
// Emit spawn event
|
||||
OnItemSpawned?.Invoke(item);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove item from tracking (when sorted or missed).
|
||||
/// </summary>
|
||||
public void RemoveItem(SortableItem item)
|
||||
{
|
||||
activeItems.Remove(item);
|
||||
}
|
||||
|
||||
private SortableItem SpawnGarbageItem()
|
||||
{
|
||||
if (settings.GarbageItems == null || settings.GarbageItems.Length == 0)
|
||||
@@ -123,6 +151,10 @@ namespace Minigames.CardSorting.Controllers
|
||||
if (item != null)
|
||||
{
|
||||
item.SetupAsGarbage(garbage);
|
||||
|
||||
// Subscribe to item events
|
||||
item.OnItemDroppedInBox += HandleItemDroppedInBox;
|
||||
item.OnItemReturnedToConveyor += HandleItemReturnedToConveyor;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -151,6 +183,10 @@ namespace Minigames.CardSorting.Controllers
|
||||
if (item != null)
|
||||
{
|
||||
item.SetupAsCard(cardData);
|
||||
|
||||
// Subscribe to item events
|
||||
item.OnItemDroppedInBox += HandleItemDroppedInBox;
|
||||
item.OnItemReturnedToConveyor += HandleItemReturnedToConveyor;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -164,31 +200,23 @@ namespace Minigames.CardSorting.Controllers
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to get a random card of a specific rarity.
|
||||
/// Uses CardSystemManager's internal DrawRandomCards logic.
|
||||
/// Gets a CardDefinition from CardSystemManager and converts to CardData.
|
||||
/// Does NOT affect player's collection or open boosters.
|
||||
/// </summary>
|
||||
private CardData GetRandomCardDataByRarity(CardRarity targetRarity)
|
||||
{
|
||||
// Use reflection or create cards manually
|
||||
// For now, open a temporary booster and filter
|
||||
// This is not ideal but works until we add a proper method to CardSystemManager
|
||||
// Get random card definition from manager
|
||||
var definition = CardSystemManager.Instance.GetRandomCardDefinitionByRarity(targetRarity);
|
||||
|
||||
// Better approach: Draw cards until we get one of the right rarity
|
||||
// Simulate drawing process
|
||||
int maxAttempts = 20;
|
||||
for (int i = 0; i < maxAttempts; i++)
|
||||
if (definition == null)
|
||||
{
|
||||
var drawnCards = CardSystemManager.Instance.OpenBoosterPack();
|
||||
CardSystemManager.Instance.AddBoosterPack(); // Restore the booster we used
|
||||
|
||||
var matchingCard = drawnCards.Find(c => c.Rarity == targetRarity);
|
||||
if (matchingCard != null)
|
||||
{
|
||||
return matchingCard;
|
||||
}
|
||||
Debug.LogWarning($"[ConveyorBeltController] No card definition found for rarity {targetRarity}");
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"[ConveyorBeltController] Failed to draw card of rarity {targetRarity} after {maxAttempts} attempts");
|
||||
return null;
|
||||
// Create CardData from definition using constructor
|
||||
// This properly links the definition and sets all properties
|
||||
return new CardData(definition);
|
||||
}
|
||||
|
||||
private void UpdateBeltSpeed(float gameProgress)
|
||||
@@ -201,7 +229,7 @@ namespace Minigames.CardSorting.Controllers
|
||||
speedMultiplier
|
||||
);
|
||||
|
||||
// Update all active items
|
||||
// Update all active items (including missed items moving to despawn)
|
||||
foreach (var item in activeItems)
|
||||
{
|
||||
if (item != null && item.Context.IsOnConveyor)
|
||||
@@ -213,6 +241,7 @@ namespace Minigames.CardSorting.Controllers
|
||||
|
||||
private void CheckItemsOffBelt()
|
||||
{
|
||||
// Check active items for reaching visual end point
|
||||
for (int i = activeItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var item = activeItems[i];
|
||||
@@ -222,25 +251,100 @@ namespace Minigames.CardSorting.Controllers
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if past end point
|
||||
if (item.transform.position.x > endPoint.position.x)
|
||||
// Check if past visual end point (not yet scored as missed)
|
||||
if (item.transform.position.x > endPoint.position.x && !missedItems.Contains(item))
|
||||
{
|
||||
// Mark as missed and emit event for scoring
|
||||
missedItems.Add(item);
|
||||
|
||||
// Transition item to FellOffConveyorState (will blink red)
|
||||
item.ChangeState("FellOffConveyorState");
|
||||
|
||||
OnItemFellOffBelt?.Invoke(item);
|
||||
|
||||
// Item continues moving, stays in activeItems until despawn
|
||||
}
|
||||
}
|
||||
|
||||
// Check missed items for reaching despawn point
|
||||
for (int i = activeItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var item = activeItems[i];
|
||||
if (item == null)
|
||||
{
|
||||
item.OnFellOffBelt();
|
||||
activeItems.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if past despawn point (time to destroy)
|
||||
if (item.transform.position.x > despawnPoint.position.x && missedItems.Contains(item))
|
||||
{
|
||||
// Remove from tracking
|
||||
activeItems.RemoveAt(i);
|
||||
missedItems.Remove(item);
|
||||
|
||||
// Clear lastSpawnedItem reference if this was it
|
||||
if (lastSpawnedItem == item)
|
||||
{
|
||||
lastSpawnedItem = null;
|
||||
}
|
||||
|
||||
// Emit despawn event for destruction
|
||||
OnItemDespawned?.Invoke(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ScheduleNextSpawn(float gameProgress)
|
||||
|
||||
/// <summary>
|
||||
/// Handle when an item is dropped in a box (correct or incorrect).
|
||||
/// </summary>
|
||||
private void HandleItemDroppedInBox(SortableItem item, SortingBox box, bool correct)
|
||||
{
|
||||
// Calculate next spawn time based on difficulty progression
|
||||
float interval = Mathf.Lerp(
|
||||
settings.InitialSpawnInterval,
|
||||
settings.MinimumSpawnInterval,
|
||||
gameProgress
|
||||
);
|
||||
|
||||
nextSpawnTime = Time.time + interval;
|
||||
// Remove from tracking and unsubscribe
|
||||
if (activeItems.Remove(item))
|
||||
{
|
||||
// Also remove from missed items if it was there
|
||||
missedItems.Remove(item);
|
||||
|
||||
// Clear lastSpawnedItem reference if this was it
|
||||
if (lastSpawnedItem == item)
|
||||
{
|
||||
lastSpawnedItem = null;
|
||||
}
|
||||
|
||||
item.OnItemDroppedInBox -= HandleItemDroppedInBox;
|
||||
item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor;
|
||||
|
||||
// Emit event for game manager to handle scoring, passing box and correctness
|
||||
OnItemSorted?.Invoke(item, box, correct);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle when an item is returned to conveyor (dropped outside box).
|
||||
/// Item transitions to DroppedOnFloorState and gets destroyed.
|
||||
/// </summary>
|
||||
private void HandleItemReturnedToConveyor(SortableItem item)
|
||||
{
|
||||
// Remove from tracking and unsubscribe (item will be destroyed)
|
||||
if (activeItems.Remove(item))
|
||||
{
|
||||
missedItems.Remove(item);
|
||||
|
||||
if (lastSpawnedItem == item)
|
||||
{
|
||||
lastSpawnedItem = null;
|
||||
}
|
||||
|
||||
item.OnItemDroppedInBox -= HandleItemDroppedInBox;
|
||||
item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor;
|
||||
|
||||
// Emit event for scoring
|
||||
OnItemDroppedOnFloor?.Invoke(item);
|
||||
|
||||
Debug.Log($"[ConveyorBeltController] Item dropped on floor: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
|
||||
}
|
||||
}
|
||||
|
||||
private CardRarity DetermineRarity(float roll)
|
||||
|
||||
@@ -26,6 +26,10 @@ namespace Minigames.CardSorting.Core
|
||||
private CardData cardData;
|
||||
private GarbageItemDefinition garbageItem;
|
||||
|
||||
// Events - item emits notifications, conveyor subscribes
|
||||
public event System.Action<SortableItem, SortingBox, bool> OnItemDroppedInBox;
|
||||
public event System.Action<SortableItem> OnItemReturnedToConveyor;
|
||||
|
||||
// Public accessors
|
||||
public SortableItemContext Context => context;
|
||||
public AppleMachine StateMachine => stateMachine;
|
||||
@@ -122,6 +126,17 @@ namespace Minigames.CardSorting.Core
|
||||
// Default behavior if state doesn't handle
|
||||
Logging.Debug($"[SortableItem] Drag started on {(isGarbage ? garbageItem.DisplayName : cardData.Name)}");
|
||||
}
|
||||
|
||||
// TODO: Fixed when base slot/draggable reworked
|
||||
public override void OnDrag(UnityEngine.EventSystems.PointerEventData eventData)
|
||||
{
|
||||
base.OnDrag(eventData);
|
||||
|
||||
if (!IsDragging) return;
|
||||
|
||||
// Perform raycast to detect what's underneath the dragged card
|
||||
DetectSlotUnderPointer(eventData);
|
||||
}
|
||||
|
||||
protected override void OnDragEndedHook()
|
||||
{
|
||||
@@ -132,17 +147,63 @@ namespace Minigames.CardSorting.Core
|
||||
{
|
||||
bool correctSort = box.ValidateItem(this);
|
||||
|
||||
// Notify game manager
|
||||
SortingGameManager.Instance?.OnItemSorted(this, box, correctSort);
|
||||
// Fire event IMMEDIATELY when card is released over bin
|
||||
// This allows manager to update score/UI right away
|
||||
OnItemDroppedInBox?.Invoke(this, box, correctSort);
|
||||
|
||||
// Transition to sorted state
|
||||
ChangeState("SortedState");
|
||||
// Transition to appropriate state based on correctness
|
||||
// State will handle fall-into-bin animation and destruction
|
||||
if (correctSort)
|
||||
{
|
||||
ChangeState("SortedCorrectlyState");
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeState("SortedIncorrectlyState");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dropped outside valid box - return to conveyor
|
||||
Logging.Debug("[SortableItem] Dropped outside box, returning to conveyor");
|
||||
ChangeState("OnConveyorState");
|
||||
// Dropped outside valid box - transition to dropped on floor state
|
||||
Logging.Debug("[SortableItem] Dropped outside box, transitioning to floor state");
|
||||
ChangeState("DroppedOnFloorState");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fixed when base slot/draggable reworked
|
||||
/// <summary>
|
||||
/// Detect which slot (if any) is under the pointer during drag.
|
||||
/// Updates CurrentSlot for drop detection.
|
||||
/// </summary>
|
||||
private void DetectSlotUnderPointer(UnityEngine.EventSystems.PointerEventData eventData)
|
||||
{
|
||||
// Perform raycast at pointer position to find slots
|
||||
var raycastResults = new System.Collections.Generic.List<UnityEngine.EventSystems.RaycastResult>();
|
||||
UnityEngine.EventSystems.EventSystem.current.RaycastAll(eventData, raycastResults);
|
||||
|
||||
SortingBox hoveredBox = null;
|
||||
|
||||
// Find first SortingBox in raycast results
|
||||
foreach (var result in raycastResults)
|
||||
{
|
||||
var box = result.gameObject.GetComponentInParent<SortingBox>();
|
||||
if (box != null)
|
||||
{
|
||||
hoveredBox = box;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update current slot (used in OnDragEndedHook)
|
||||
if (hoveredBox != null && hoveredBox != CurrentSlot)
|
||||
{
|
||||
_currentSlot = hoveredBox;
|
||||
Logging.Debug($"[SortableItem] Now hovering over {hoveredBox.BoxType} box");
|
||||
}
|
||||
else if (hoveredBox == null && CurrentSlot != null)
|
||||
{
|
||||
_currentSlot = null;
|
||||
Logging.Debug("[SortableItem] No longer over any box");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,16 +217,6 @@ namespace Minigames.CardSorting.Core
|
||||
stateMachine.ChangeState(stateName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when item falls off conveyor belt.
|
||||
/// </summary>
|
||||
public void OnFellOffBelt()
|
||||
{
|
||||
// Notify game manager
|
||||
SortingGameManager.Instance?.OnItemMissed(this);
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -35,6 +35,11 @@ namespace Minigames.CardSorting.Core
|
||||
public bool IsOnConveyor { get; set; } = true;
|
||||
public float ConveyorSpeed { get; set; } = 1f;
|
||||
|
||||
// Original transform data (captured on spawn for drag animations)
|
||||
public Vector3 OriginalScale { get; private set; }
|
||||
public Vector3 OriginalPosition { get; private set; }
|
||||
public Quaternion OriginalRotation { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Auto-find components if not assigned
|
||||
@@ -47,9 +52,16 @@ namespace Minigames.CardSorting.Core
|
||||
}
|
||||
}
|
||||
|
||||
if (animator == null && visualTransform != null)
|
||||
if (animator == null)
|
||||
{
|
||||
animator = visualTransform.GetComponent<CardAnimator>();
|
||||
// CardAnimator should be on root GameObject (animates root transform with Canvas scale)
|
||||
animator = GetComponent<CardAnimator>();
|
||||
|
||||
// Fallback: check Visual child (legacy setup)
|
||||
if (animator == null && visualTransform != null)
|
||||
{
|
||||
animator = visualTransform.GetComponent<CardAnimator>();
|
||||
}
|
||||
}
|
||||
|
||||
if (cardDisplay == null && visualTransform != null)
|
||||
@@ -70,6 +82,20 @@ namespace Minigames.CardSorting.Core
|
||||
/// </summary>
|
||||
public void SetupAsCard(CardData cardData)
|
||||
{
|
||||
// Capture original root transform for drag animations
|
||||
// This preserves the tiny world-space Canvas scale (e.g., 0.05)
|
||||
var currentScale = transform.localScale;
|
||||
if (currentScale.x < 0.01f && currentScale.y < 0.01f && currentScale.z < 0.01f)
|
||||
{
|
||||
OriginalScale = Vector3.one; // Fallback if scale is ~0
|
||||
}
|
||||
else
|
||||
{
|
||||
OriginalScale = currentScale;
|
||||
}
|
||||
OriginalPosition = transform.localPosition;
|
||||
OriginalRotation = transform.localRotation;
|
||||
|
||||
if (cardDisplay != null)
|
||||
{
|
||||
cardDisplay.SetupCard(cardData);
|
||||
@@ -85,6 +111,20 @@ namespace Minigames.CardSorting.Core
|
||||
/// </summary>
|
||||
public void SetupAsGarbage(Sprite sprite)
|
||||
{
|
||||
// Capture original root transform for drag animations
|
||||
// This preserves the tiny world-space Canvas scale (e.g., 0.05)
|
||||
var currentScale = transform.localScale;
|
||||
if (currentScale.x < 0.01f && currentScale.y < 0.01f && currentScale.z < 0.01f)
|
||||
{
|
||||
OriginalScale = Vector3.one; // Fallback if scale is ~0
|
||||
}
|
||||
else
|
||||
{
|
||||
OriginalScale = currentScale;
|
||||
}
|
||||
OriginalPosition = transform.localPosition;
|
||||
OriginalRotation = transform.localRotation;
|
||||
|
||||
if (garbageVisual != null)
|
||||
{
|
||||
garbageVisual.UpdateDisplay(sprite);
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Minigames.CardSorting.Core
|
||||
{
|
||||
[Header("Box Configuration")]
|
||||
[SerializeField] private BoxType boxType;
|
||||
[SerializeField] private Sprite boxSprite;
|
||||
|
||||
public BoxType BoxType => boxType;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using Data.CardSystem;
|
||||
using Input;
|
||||
using Minigames.CardSorting.Controllers;
|
||||
using Minigames.CardSorting.Core;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.CardSorting.Core
|
||||
@@ -19,11 +20,15 @@ namespace Minigames.CardSorting.Core
|
||||
{
|
||||
[Header("Scene References")]
|
||||
[SerializeField] private Transform conveyorSpawnPoint;
|
||||
[SerializeField] private Transform conveyorEndPoint;
|
||||
[SerializeField] private Transform conveyorEndPoint; // Visual end - items scored as missed here
|
||||
[SerializeField] private Transform conveyorDespawnPoint; // Off-screen - items destroyed here
|
||||
[SerializeField] private GameObject sortableCardPrefab;
|
||||
[SerializeField] private GameObject sortableGarbagePrefab;
|
||||
[SerializeField] private SortingBox[] sortingBoxes;
|
||||
|
||||
[Header("Effects")]
|
||||
[SerializeField] private CinemachineImpulseSource impulseSource; // Screen shake on incorrect sort
|
||||
|
||||
// Settings
|
||||
private ICardSortingSettings _settings;
|
||||
|
||||
@@ -32,6 +37,7 @@ namespace Minigames.CardSorting.Core
|
||||
private ConveyorBeltController Conveyor => _conveyorController ??= new ConveyorBeltController(
|
||||
conveyorSpawnPoint,
|
||||
conveyorEndPoint,
|
||||
conveyorDespawnPoint,
|
||||
sortableCardPrefab,
|
||||
sortableGarbagePrefab,
|
||||
_settings
|
||||
@@ -56,6 +62,11 @@ namespace Minigames.CardSorting.Core
|
||||
public event Action<SortableItem, SortingBox, bool> OnItemSortedEvent;
|
||||
public event Action<float> OnTimerUpdated; // Remaining time
|
||||
|
||||
// Global effect events
|
||||
public event Action<SortableItem> OnItemSortedCorrectly;
|
||||
public event Action<SortableItem> OnItemSortedIncorrectly;
|
||||
public event Action<SortableItem> OnItemFellOffBelt;
|
||||
|
||||
internal override void OnManagedAwake()
|
||||
{
|
||||
_instance = this;
|
||||
@@ -79,6 +90,13 @@ namespace Minigames.CardSorting.Core
|
||||
Score.OnCorrectSort += OnCorrectSort;
|
||||
Score.OnIncorrectSort += OnIncorrectSort;
|
||||
|
||||
// Subscribe to conveyor events
|
||||
Conveyor.OnItemSpawned += OnConveyorItemSpawned;
|
||||
Conveyor.OnItemFellOffBelt += OnConveyorItemFellOff;
|
||||
Conveyor.OnItemDespawned += OnConveyorItemDespawned;
|
||||
Conveyor.OnItemSorted += OnConveyorItemSorted;
|
||||
Conveyor.OnItemDroppedOnFloor += OnConveyorItemDroppedOnFloor;
|
||||
|
||||
// Start game automatically or wait for trigger
|
||||
// For now, auto-start
|
||||
StartGame();
|
||||
@@ -92,6 +110,15 @@ namespace Minigames.CardSorting.Core
|
||||
Score.OnCorrectSort -= OnCorrectSort;
|
||||
Score.OnIncorrectSort -= OnIncorrectSort;
|
||||
}
|
||||
|
||||
if (_conveyorController != null)
|
||||
{
|
||||
Conveyor.OnItemSpawned -= OnConveyorItemSpawned;
|
||||
Conveyor.OnItemFellOffBelt -= OnConveyorItemFellOff;
|
||||
Conveyor.OnItemDespawned -= OnConveyorItemDespawned;
|
||||
Conveyor.OnItemSorted -= OnConveyorItemSorted;
|
||||
Conveyor.OnItemDroppedOnFloor -= OnConveyorItemDroppedOnFloor;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -112,15 +139,8 @@ namespace Minigames.CardSorting.Core
|
||||
return;
|
||||
}
|
||||
|
||||
// Update conveyor
|
||||
// Update conveyor (handles spawning, movement, and despawning internally)
|
||||
Conveyor.Update(Time.deltaTime, gameProgress);
|
||||
|
||||
// Try spawn item
|
||||
var item = Conveyor.TrySpawnItem(Time.time, gameProgress);
|
||||
if (item != null)
|
||||
{
|
||||
OnItemSpawned?.Invoke(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartGame()
|
||||
@@ -167,47 +187,129 @@ namespace Minigames.CardSorting.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by SortableItem when placed in box.
|
||||
/// Called when conveyor spawns a new item.
|
||||
/// </summary>
|
||||
public void OnItemSorted(SortableItem item, SortingBox box, bool correct)
|
||||
private void OnConveyorItemSpawned(SortableItem item)
|
||||
{
|
||||
// Forward to public event for UI/other systems
|
||||
OnItemSpawned?.Invoke(item);
|
||||
|
||||
Logging.Debug($"[SortingGameManager] Item spawned: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when item reaches visual end of belt (via conveyor event).
|
||||
/// Item continues moving off-screen until despawn point.
|
||||
/// Scoring rules:
|
||||
/// - Trash fell off: Negative score (penalty)
|
||||
/// - Card fell off: Neutral (no score change)
|
||||
/// </summary>
|
||||
private void OnConveyorItemFellOff(SortableItem item)
|
||||
{
|
||||
// Only penalize TRASH items that fall off
|
||||
// Cards falling off are neutral (no score change)
|
||||
if (item.IsGarbage)
|
||||
{
|
||||
Score.RecordMissedItem();
|
||||
Logging.Debug($"[SortingGameManager] Trash fell off belt! {item.GarbageItem?.DisplayName} - PENALTY");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Debug($"[SortingGameManager] Card fell off belt: {item.CardData?.Name} - no penalty");
|
||||
}
|
||||
|
||||
// Fire global fell off belt event for effects
|
||||
OnItemFellOffBelt?.Invoke(item);
|
||||
|
||||
// Visual feedback could go here (e.g., "MISS!" popup)
|
||||
// Item will continue moving and be destroyed at despawn point
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when item is dropped on floor (via conveyor event).
|
||||
/// Scoring rules:
|
||||
/// - Trash dropped on floor: Negative score (penalty)
|
||||
/// - Card dropped on floor: Neutral (no score change)
|
||||
/// </summary>
|
||||
private void OnConveyorItemDroppedOnFloor(SortableItem item)
|
||||
{
|
||||
// Only penalize TRASH items dropped on floor
|
||||
// Cards dropped on floor are neutral (no score change)
|
||||
if (item.IsGarbage)
|
||||
{
|
||||
Score.RecordIncorrectSort();
|
||||
Logging.Debug($"[SortingGameManager] Trash dropped on floor! {item.GarbageItem?.DisplayName} - PENALTY");
|
||||
|
||||
// Trigger screen shake for trash dropped on floor
|
||||
if (impulseSource != null)
|
||||
{
|
||||
impulseSource.GenerateImpulse();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Debug($"[SortingGameManager] Card dropped on floor: {item.CardData?.Name} - no penalty");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when item reaches despawn point (via conveyor event).
|
||||
/// Actually destroys the item.
|
||||
/// </summary>
|
||||
private void OnConveyorItemDespawned(SortableItem item)
|
||||
{
|
||||
Logging.Debug($"[SortingGameManager] Item despawned: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
|
||||
|
||||
// Destroy the item
|
||||
if (item != null)
|
||||
Destroy(item.gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when conveyor confirms item was sorted (via event).
|
||||
/// Handles scoring only - the state (SortedCorrectlyState/SortedIncorrectlyState) handles animation and destruction.
|
||||
/// Scoring rules:
|
||||
/// - Correct sort: Positive score (cards or trash in correct box)
|
||||
/// - Incorrect trash: Negative score (trash in wrong box)
|
||||
/// - Incorrect card: Neutral (no score change)
|
||||
/// </summary>
|
||||
private void OnConveyorItemSorted(SortableItem item, SortingBox box, bool correct)
|
||||
{
|
||||
if (correct)
|
||||
{
|
||||
Score.RecordCorrectSort();
|
||||
Logging.Debug($"[SortingGameManager] Correct sort! {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
|
||||
|
||||
// Fire global correct sort event for effects
|
||||
OnItemSortedCorrectly?.Invoke(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
Score.RecordIncorrectSort();
|
||||
Logging.Debug($"[SortingGameManager] Incorrect sort! {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
|
||||
// Only penalize incorrect sorting for TRASH items
|
||||
// Cards incorrectly sorted are neutral (no score change)
|
||||
if (item.IsGarbage)
|
||||
{
|
||||
Score.RecordIncorrectSort();
|
||||
Logging.Debug($"[SortingGameManager] Incorrect trash sort! {item.GarbageItem?.DisplayName} - PENALTY");
|
||||
|
||||
// Fire global incorrect sort event for effects
|
||||
OnItemSortedIncorrectly?.Invoke(item);
|
||||
|
||||
// Trigger screen shake
|
||||
if (impulseSource != null)
|
||||
{
|
||||
impulseSource.GenerateImpulse();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Debug($"[SortingGameManager] Card sorted incorrectly: {item.CardData?.Name} - no penalty");
|
||||
}
|
||||
}
|
||||
|
||||
Conveyor.RemoveItem(item);
|
||||
OnItemSortedEvent?.Invoke(item, box, correct);
|
||||
|
||||
// Play animation then destroy
|
||||
if (item.Context?.Animator != null)
|
||||
{
|
||||
item.Context.Animator.PopOut(0.4f, () => {
|
||||
if (item != null)
|
||||
Destroy(item.gameObject);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(item.gameObject, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when item falls off belt.
|
||||
/// </summary>
|
||||
public void OnItemMissed(SortableItem item)
|
||||
{
|
||||
Score.RecordMissedItem();
|
||||
Conveyor.RemoveItem(item);
|
||||
|
||||
Logging.Debug($"[SortingGameManager] Item missed! {item.CardData?.Name ?? item.GarbageItem?.DisplayName}");
|
||||
// State handles animation and destruction - we just update score/UI here
|
||||
}
|
||||
|
||||
private void OnScoreChanged(int newScore)
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace Minigames.CardSorting.StateMachine.States
|
||||
public class BeingDraggedState : AppleState
|
||||
{
|
||||
private SortableItemContext _context;
|
||||
private Vector3 _originalScale;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -26,13 +25,12 @@ namespace Minigames.CardSorting.StateMachine.States
|
||||
|
||||
_context.IsOnConveyor = false;
|
||||
|
||||
// Store original scale
|
||||
if (_context.VisualTransform != null)
|
||||
// Visual feedback: scale up root transform by 10%
|
||||
// Use OriginalScale from context (captured at spawn, preserves world-space Canvas scale)
|
||||
if (_context.RootTransform != null && _context.Animator != null)
|
||||
{
|
||||
_originalScale = _context.VisualTransform.localScale;
|
||||
|
||||
// Visual feedback: scale up 10%
|
||||
_context.Animator?.AnimateScale(_originalScale * 1.1f, 0.2f);
|
||||
Vector3 targetScale = _context.OriginalScale * 1.1f;
|
||||
_context.Animator.AnimateScale(targetScale, 0.2f);
|
||||
}
|
||||
|
||||
Logging.Debug("[BeingDraggedState] Item being dragged, scaled up for feedback");
|
||||
@@ -40,10 +38,10 @@ namespace Minigames.CardSorting.StateMachine.States
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// Restore original scale
|
||||
// Restore original root transform scale (e.g., 0.05 for world-space Canvas)
|
||||
if (_context != null && _context.Animator != null)
|
||||
{
|
||||
_context.Animator.AnimateScale(_originalScale, 0.2f);
|
||||
_context.Animator.AnimateScale(_context.OriginalScale, 0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Minigames.CardSorting.Core;
|
||||
|
||||
namespace Minigames.CardSorting.StateMachine.States
|
||||
{
|
||||
/// <summary>
|
||||
/// Item was dropped outside any bin (on the floor).
|
||||
/// Plays "disappear" animation then destroys the item.
|
||||
/// </summary>
|
||||
public class DroppedOnFloorState : AppleState
|
||||
{
|
||||
private SortableItemContext _context;
|
||||
private SortableItem _item;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_context = GetComponentInParent<SortableItemContext>();
|
||||
_item = GetComponentInParent<SortableItem>();
|
||||
}
|
||||
|
||||
public override void OnEnterState()
|
||||
{
|
||||
if (_context == null) return;
|
||||
|
||||
_context.IsOnConveyor = false;
|
||||
|
||||
Logging.Debug("[DroppedOnFloorState] Item dropped on floor, blinking red then disappearing");
|
||||
|
||||
// Blink red briefly, then play disappear animation
|
||||
StartBlinkThenDisappear();
|
||||
}
|
||||
|
||||
private void StartBlinkThenDisappear()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Get the image to blink
|
||||
UnityEngine.UI.Image imageToBlink = null;
|
||||
|
||||
if (_context.CardDisplay != null)
|
||||
{
|
||||
imageToBlink = _context.CardDisplay.GetComponent<UnityEngine.UI.Image>();
|
||||
}
|
||||
else if (_context.GarbageVisual != null)
|
||||
{
|
||||
imageToBlink = _context.GarbageVisual.GetComponent<UnityEngine.UI.Image>();
|
||||
}
|
||||
|
||||
if (imageToBlink != null)
|
||||
{
|
||||
// Blink red briefly (2-3 times), then stop and disappear
|
||||
_context.Animator.BlinkRed(imageToBlink, 0.15f); // Fast blink
|
||||
|
||||
// After brief delay, stop blinking and play disappear animation
|
||||
_context.Animator.AnimateScale(_context.RootTransform.localScale, 0.5f, () =>
|
||||
{
|
||||
_context.Animator.StopBlinking();
|
||||
PlayDisappearAnimation();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// No image found, just disappear directly
|
||||
PlayDisappearAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayDisappearAnimation()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Tween scale down to 0 (disappear)
|
||||
// When complete, destroy the item
|
||||
_context.Animator.PopOut(0.4f, () =>
|
||||
{
|
||||
if (_item != null)
|
||||
{
|
||||
Logging.Debug("[DroppedOnFloorState] Animation complete, destroying item");
|
||||
Destroy(_item.gameObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b384e4988bf549f2b6e70d1ff0fa4bcd
|
||||
timeCreated: 1763557103
|
||||
@@ -0,0 +1,88 @@
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Minigames.CardSorting.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.CardSorting.StateMachine.States
|
||||
{
|
||||
/// <summary>
|
||||
/// Item reached the visual end of conveyor without being sorted.
|
||||
/// Becomes non-clickable and blinks red until despawn point.
|
||||
/// </summary>
|
||||
public class FellOffConveyorState : AppleState
|
||||
{
|
||||
private SortableItemContext _context;
|
||||
private SortableItem _item;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_context = GetComponentInParent<SortableItemContext>();
|
||||
_item = GetComponentInParent<SortableItem>();
|
||||
}
|
||||
|
||||
public override void OnEnterState()
|
||||
{
|
||||
if (_context == null) return;
|
||||
|
||||
// Keep IsOnConveyor = true so item continues moving to despawn point
|
||||
// Item is no longer sortable but must continue moving off-screen
|
||||
_context.IsOnConveyor = true;
|
||||
|
||||
Logging.Debug("[FellOffConveyorState] Item fell off conveyor, blinking red until despawn");
|
||||
|
||||
// Disable dragging - item can no longer be picked up
|
||||
if (_item != null)
|
||||
{
|
||||
_item.SetDraggingEnabled(false);
|
||||
}
|
||||
|
||||
// Start blinking red animation
|
||||
StartBlinkingRed();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_context == null || !_context.IsOnConveyor) return;
|
||||
|
||||
// Continue moving item toward despawn point (same logic as OnConveyorState)
|
||||
Vector3 movement = Vector3.right * _context.ConveyorSpeed * Time.deltaTime;
|
||||
_context.RootTransform.position += movement;
|
||||
}
|
||||
|
||||
private void StartBlinkingRed()
|
||||
{
|
||||
if (_context.Animator == null) return;
|
||||
|
||||
// Get the image to tint (CardDisplay or GarbageVisual)
|
||||
UnityEngine.UI.Image imageToBlink = null;
|
||||
|
||||
if (_context.CardDisplay != null)
|
||||
{
|
||||
imageToBlink =
|
||||
_context.CardDisplay.GetComponent<UnityEngine.UI.Image>()
|
||||
?? _context.CardDisplay.GetComponentInChildren<UnityEngine.UI.Image>();
|
||||
}
|
||||
else if (_context.GarbageVisual != null)
|
||||
{
|
||||
imageToBlink =
|
||||
_context.GarbageVisual.GetComponent<UnityEngine.UI.Image>()
|
||||
?? _context.GarbageVisual.GetComponentInChildren<UnityEngine.UI.Image>();
|
||||
}
|
||||
|
||||
if (imageToBlink != null)
|
||||
{
|
||||
_context.Animator.BlinkRed(imageToBlink);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// Stop blinking when state exits (item despawned)
|
||||
if (_context?.Animator != null)
|
||||
{
|
||||
_context.Animator.StopBlinking();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 619a38624dcf48b19913bd4e1ac28625
|
||||
timeCreated: 1763557115
|
||||
@@ -0,0 +1,73 @@
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Minigames.CardSorting.Core;
|
||||
|
||||
namespace Minigames.CardSorting.StateMachine.States
|
||||
{
|
||||
/// <summary>
|
||||
/// Item has been correctly sorted into the right box.
|
||||
/// Plays "fall into bin" animation then destroys the card.
|
||||
/// </summary>
|
||||
public class SortedCorrectlyState : AppleState
|
||||
{
|
||||
private SortableItemContext _context;
|
||||
private SortableItem _item;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_context = GetComponentInParent<SortableItemContext>();
|
||||
_item = GetComponentInParent<SortableItem>();
|
||||
}
|
||||
|
||||
public override void OnEnterState()
|
||||
{
|
||||
if (_context == null) return;
|
||||
|
||||
_context.IsOnConveyor = false;
|
||||
|
||||
Logging.Debug("[SortedCorrectlyState] Item correctly sorted, tweening to box then falling in");
|
||||
|
||||
// First tween to box center, then play fall animation
|
||||
TweenToBoxThenFall();
|
||||
}
|
||||
|
||||
private void TweenToBoxThenFall()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Get the box position (if available from CurrentSlot)
|
||||
var box = _item.CurrentSlot as SortingBox;
|
||||
if (box != null)
|
||||
{
|
||||
// Tween position to box center
|
||||
_context.Animator.AnimateLocalPosition(box.transform.position, 0.2f, () =>
|
||||
{
|
||||
// After reaching box, play fall animation
|
||||
PlayFallIntoBinAnimation();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// No box found, just play fall animation
|
||||
PlayFallIntoBinAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayFallIntoBinAnimation()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Tween scale down to 0 (looks like falling into bin)
|
||||
// When complete, destroy the card
|
||||
_context.Animator.PopOut(0.4f, () =>
|
||||
{
|
||||
if (_item != null)
|
||||
{
|
||||
Logging.Debug("[SortedCorrectlyState] Animation complete, destroying item");
|
||||
Destroy(_item.gameObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3ed2e6fb0814273926c33a178bdf42b
|
||||
timeCreated: 1763555977
|
||||
@@ -0,0 +1,109 @@
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Minigames.CardSorting.Core;
|
||||
|
||||
namespace Minigames.CardSorting.StateMachine.States
|
||||
{
|
||||
/// <summary>
|
||||
/// Item has been incorrectly sorted into the wrong box.
|
||||
/// Plays "fall into bin" animation then destroys the card.
|
||||
/// Same animation as correct sort, but different state for tracking/events.
|
||||
/// </summary>
|
||||
public class SortedIncorrectlyState : AppleState
|
||||
{
|
||||
private SortableItemContext _context;
|
||||
private SortableItem _item;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_context = GetComponentInParent<SortableItemContext>();
|
||||
_item = GetComponentInParent<SortableItem>();
|
||||
}
|
||||
|
||||
public override void OnEnterState()
|
||||
{
|
||||
if (_context == null) return;
|
||||
|
||||
_context.IsOnConveyor = false;
|
||||
|
||||
Logging.Debug("[SortedIncorrectlyState] Item incorrectly sorted, blinking red then tweening to box");
|
||||
|
||||
// Start blinking red briefly, then tween to box
|
||||
StartBlinkThenTween();
|
||||
}
|
||||
|
||||
private void StartBlinkThenTween()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Get the image to blink
|
||||
UnityEngine.UI.Image imageToBlink = null;
|
||||
|
||||
if (_context.CardDisplay != null)
|
||||
{
|
||||
imageToBlink = _context.CardDisplay.GetComponent<UnityEngine.UI.Image>();
|
||||
}
|
||||
else if (_context.GarbageVisual != null)
|
||||
{
|
||||
imageToBlink = _context.GarbageVisual.GetComponent<UnityEngine.UI.Image>();
|
||||
}
|
||||
|
||||
if (imageToBlink != null)
|
||||
{
|
||||
// Blink red briefly (2-3 times), then stop and continue with tween
|
||||
_context.Animator.BlinkRed(imageToBlink, 0.15f); // Fast blink
|
||||
|
||||
// After brief delay, stop blinking and tween to box
|
||||
_context.Animator.AnimateScale(_context.RootTransform.localScale, 0.5f, () =>
|
||||
{
|
||||
_context.Animator.StopBlinking();
|
||||
TweenToBoxThenFall();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// No image found, just tween directly
|
||||
TweenToBoxThenFall();
|
||||
}
|
||||
}
|
||||
|
||||
private void TweenToBoxThenFall()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Get the box position (if available from CurrentSlot)
|
||||
var box = _item.CurrentSlot as SortingBox;
|
||||
if (box != null)
|
||||
{
|
||||
// Tween position to box center
|
||||
_context.Animator.AnimateLocalPosition(box.transform.position, 0.2f, () =>
|
||||
{
|
||||
// After reaching box, play fall animation
|
||||
PlayFallIntoBinAnimation();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// No box found, just play fall animation
|
||||
PlayFallIntoBinAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayFallIntoBinAnimation()
|
||||
{
|
||||
if (_context.Animator == null || _item == null) return;
|
||||
|
||||
// Tween scale down to 0 (looks like falling into bin)
|
||||
// When complete, destroy the card
|
||||
_context.Animator.PopOut(0.4f, () =>
|
||||
{
|
||||
if (_item != null)
|
||||
{
|
||||
Logging.Debug("[SortedIncorrectlyState] Animation complete, destroying item");
|
||||
Destroy(_item.gameObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edef0fb846be4fd99d396ea27dca1e4f
|
||||
timeCreated: 1763555989
|
||||
@@ -1,34 +0,0 @@
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Minigames.CardSorting.Core;
|
||||
|
||||
namespace Minigames.CardSorting.StateMachine.States
|
||||
{
|
||||
/// <summary>
|
||||
/// Item has been successfully sorted into a box.
|
||||
/// Plays animation then marks for destruction.
|
||||
/// Manager handles the actual PopOut animation and destruction.
|
||||
/// </summary>
|
||||
public class SortedState : AppleState
|
||||
{
|
||||
private SortableItemContext _context;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_context = GetComponentInParent<SortableItemContext>();
|
||||
}
|
||||
|
||||
public override void OnEnterState()
|
||||
{
|
||||
if (_context == null) return;
|
||||
|
||||
_context.IsOnConveyor = false;
|
||||
|
||||
Logging.Debug("[SortedState] Item sorted, ready for destruction animation");
|
||||
|
||||
// Manager will handle PopOut animation and destruction
|
||||
// State just marks item as no longer on conveyor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0717f922952c4f228930ef0a5f6617b0
|
||||
timeCreated: 1763469776
|
||||
Reference in New Issue
Block a user