Further updates to state machines

This commit is contained in:
Michal Pikulski
2025-11-05 13:48:25 +01:00
parent 15fe4bdce6
commit 210823344a
25 changed files with 2209 additions and 4382 deletions

View File

@@ -1978,11 +1978,11 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3} - target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 1.85 value: 0.09
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3} - target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 5.14 value: 3.44
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3} - target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3}
propertyPath: m_LocalEulerAnglesHint.x propertyPath: m_LocalEulerAnglesHint.x

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 2c9ee06300474fb41b711f1c49f72d94 guid: 97f767ded753d524086106f3c39a645f
DefaultImporter: PrefabImporter:
externalObjects: {} externalObjects: {}
userData: userData:
assetBundleName: assetBundleName:

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,17 @@
using Core.SaveLoad;
using UnityEngine; using UnityEngine;
using Pixelplacement; using Pixelplacement;
public class BirdEyesBehavior : MonoBehaviour public class BirdEyesBehavior : MonoBehaviour
{ {
private StateMachine statemachine; private AppleMachine statemachine;
private Animator animator; private Animator animator;
public bool correctItemIsIn; public bool correctItemIsIn;
[SerializeField] private Animator bushAnimator; // Assign in Inspector [SerializeField] private Animator bushAnimator; // Assign in Inspector
// Start is called once before the first execution of Update after the MonoBehaviour is created // Start is called once before the first execution of Update after the MonoBehaviour is created
void Start() void Start()
{ {
statemachine = GetComponent<StateMachine>(); statemachine = GetComponent<AppleMachine>();
animator = GetComponentInChildren<Animator>(); animator = GetComponentInChildren<Animator>();
} }

View File

@@ -221,7 +221,10 @@ namespace Core.Lifecycle
{ {
LogDebug($"Broadcasting ManagedAwake to {managedAwakeList.Count} components"); LogDebug($"Broadcasting ManagedAwake to {managedAwakeList.Count} components");
foreach (var component in managedAwakeList) // Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null) continue; if (component == null) continue;
@@ -337,7 +340,10 @@ namespace Core.Lifecycle
ProcessBatchedSceneComponents(); ProcessBatchedSceneComponents();
} }
foreach (var component in sceneReadyList) // Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(sceneReadyList);
foreach (var component in componentsCopy)
{ {
if (component == null) continue; if (component == null) continue;
@@ -364,7 +370,10 @@ namespace Core.Lifecycle
{ {
var saveData = new Dictionary<string, string>(); var saveData = new Dictionary<string, string>();
foreach (var component in managedAwakeList) // Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null || !component.AutoRegisterForSave) continue; if (component == null || !component.AutoRegisterForSave) continue;
@@ -396,7 +405,10 @@ namespace Core.Lifecycle
{ {
var saveData = new Dictionary<string, string>(); var saveData = new Dictionary<string, string>();
foreach (var component in managedAwakeList) // Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null || !component.AutoRegisterForSave) continue; if (component == null || !component.AutoRegisterForSave) continue;
@@ -429,7 +441,12 @@ namespace Core.Lifecycle
if (saveData == null) return; if (saveData == null) return;
int restoredCount = 0; int restoredCount = 0;
foreach (var component in managedAwakeList)
// Create a copy to avoid collection modification during iteration
// (components might destroy themselves during restoration)
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null || !component.AutoRegisterForSave) continue; if (component == null || !component.AutoRegisterForSave) continue;
@@ -461,7 +478,11 @@ namespace Core.Lifecycle
if (saveData == null) return; if (saveData == null) return;
int restoredCount = 0; int restoredCount = 0;
foreach (var component in managedAwakeList)
// Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null || !component.AutoRegisterForSave) continue; if (component == null || !component.AutoRegisterForSave) continue;
@@ -492,7 +513,10 @@ namespace Core.Lifecycle
{ {
LogDebug("Broadcasting GlobalLoadCompleted"); LogDebug("Broadcasting GlobalLoadCompleted");
foreach (var component in managedAwakeList) // Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null || !component.AutoRegisterForSave) continue; if (component == null || !component.AutoRegisterForSave) continue;
@@ -516,7 +540,10 @@ namespace Core.Lifecycle
{ {
LogDebug("Broadcasting GlobalSaveStarted"); LogDebug("Broadcasting GlobalSaveStarted");
foreach (var component in managedAwakeList) // Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{ {
if (component == null || !component.AutoRegisterForSave) continue; if (component == null || !component.AutoRegisterForSave) continue;

View File

@@ -1,4 +1,4 @@
using System.Collections; using System.Collections;
using AppleHills.Core.Settings; using AppleHills.Core.Settings;
using Core.Lifecycle; using Core.Lifecycle;
using Settings; using Settings;
@@ -36,6 +36,12 @@ namespace Core
protected override void OnManagedAwake() protected override void OnManagedAwake()
{ {
// Subscribe to SceneManagerService to enforce orientation on every scene load
if (SceneManagerService.Instance != null)
{
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
}
#if UNITY_EDITOR #if UNITY_EDITOR
// When playing in the editor, manually invoke orientation check for the currently active scene // When playing in the editor, manually invoke orientation check for the currently active scene
if (Application.isPlaying) if (Application.isPlaying)
@@ -47,12 +53,18 @@ namespace Core
protected override void OnSceneReady() protected override void OnSceneReady()
{ {
// Handle orientation when scene is ready // Handle orientation when scene is ready (initial scene)
// Note: This fires for the scene that just loaded, LifecycleManager tracks which scene // Note: This fires for the scene that just loaded, LifecycleManager tracks which scene
string sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; string sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
HandleSceneOrientation(sceneName); HandleSceneOrientation(sceneName);
} }
private void OnSceneLoadCompleted(string sceneName)
{
// Enforce orientation every time a scene is loaded via SceneManagerService
HandleSceneOrientation(sceneName);
}
private void HandleSceneOrientation(string sceneName) private void HandleSceneOrientation(string sceneName)
{ {
// Determine desired orientation for this scene // Determine desired orientation for this scene
@@ -95,6 +107,12 @@ namespace Core
protected override void OnDestroy() protected override void OnDestroy()
{ {
// Unsubscribe from events to prevent memory leaks
if (SceneManagerService.Instance != null)
{
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
}
base.OnDestroy(); // Important: call base base.OnDestroy(); // Important: call base
} }

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Interactions;
namespace AppleHills.Core.Settings namespace AppleHills.Core.Settings
{ {
@@ -88,5 +89,31 @@ namespace AppleHills.Core.Settings
} }
return null; return null;
} }
/// <summary>
/// Finds a pickup prefab by its itemData.itemId.
/// Searches through combination rules to find result prefabs.
/// Used to spawn dynamically created items during save/load.
/// </summary>
public GameObject FindPickupPrefabByItemId(string itemId)
{
if (string.IsNullOrEmpty(itemId) || combinationRules == null)
return null;
// Search through combination rules to find a result prefab with matching itemId
foreach (var rule in combinationRules)
{
if (rule.resultPrefab != null)
{
var pickup = rule.resultPrefab.GetComponent<Pickup>();
if (pickup != null && pickup.itemData != null && pickup.itemData.itemId == itemId)
{
return rule.resultPrefab;
}
}
}
return null;
}
} }
} }

View File

@@ -57,6 +57,7 @@ namespace AppleHills.Core.Settings
// Methods to query item configurations // Methods to query item configurations
CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2); CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2);
SlotItemConfig GetSlotItemConfig(PickupItemData slotItem); SlotItemConfig GetSlotItemConfig(PickupItemData slotItem);
GameObject FindPickupPrefabByItemId(string itemId);
} }
/// <summary> /// <summary>

View File

@@ -2,6 +2,7 @@ using UnityEngine;
using Pixelplacement; using Pixelplacement;
using System.Collections; using System.Collections;
using Core; using Core;
using Core.SaveLoad;
using UnityEngine.Audio; using UnityEngine.Audio;
public class PicnicBehaviour : MonoBehaviour public class PicnicBehaviour : MonoBehaviour
@@ -12,7 +13,7 @@ public class PicnicBehaviour : MonoBehaviour
public float getFlirtyMin = 1f; public float getFlirtyMin = 1f;
public float getFlirtyMax = 3f; public float getFlirtyMax = 3f;
private StateMachine stateMachine; private AppleMachine stateMachine;
private Animator animator; private Animator animator;
[Header("The FakeChocolate to destroy!")] [Header("The FakeChocolate to destroy!")]
@@ -32,7 +33,7 @@ public class PicnicBehaviour : MonoBehaviour
void Awake() void Awake()
{ {
stateMachine = GetComponent<StateMachine>(); stateMachine = GetComponent<AppleMachine>();
animator = GetComponent<Animator>(); animator = GetComponent<Animator>();
_audioSource = GetComponent<AppleAudioSource>(); _audioSource = GetComponent<AppleAudioSource>();
} }

View File

@@ -97,90 +97,7 @@ AnimationClip:
- time: 1.5833334 - time: 1.5833334
value: {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3} value: {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
attribute: m_Sprite attribute: m_Sprite
path: SoundBird path:
classID: 212
script: {fileID: 0}
flags: 2
- serializedVersion: 2
curve:
- time: 0
value: {fileID: -1035714051, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.033333335
value: {fileID: -740831527, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.05
value: {fileID: -648204482, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.11666667
value: {fileID: -960280295, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.13333334
value: {fileID: -1144832505, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.2
value: {fileID: -1860215682, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.25
value: {fileID: 519773293, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.26666668
value: {fileID: -1067281986, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.33333334
value: {fileID: -36811272, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.38333333
value: {fileID: -1592089404, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.41666666
value: {fileID: -1729322987, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.45
value: {fileID: -91858778, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.5
value: {fileID: -26124593, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.53333336
value: {fileID: 259088195, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.6
value: {fileID: 1746085375, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.6166667
value: {fileID: -182272111, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.68333334
value: {fileID: 1436667360, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.73333335
value: {fileID: 545467259, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.75
value: {fileID: 121392657, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.8
value: {fileID: 938631806, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.8333333
value: {fileID: 1943282875, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.8833333
value: {fileID: -1918772169, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.93333334
value: {fileID: -1252794517, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 0.96666664
value: {fileID: -927331073, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.0166667
value: {fileID: -1038168376, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.0833334
value: {fileID: 1855149249, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.1
value: {fileID: -2116798272, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.1666666
value: {fileID: 2078607702, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.1833333
value: {fileID: -633261939, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.2333333
value: {fileID: -86103801, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.2833333
value: {fileID: 1380056380, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.3166667
value: {fileID: 1797284751, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.3666667
value: {fileID: 2004539437, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.4166666
value: {fileID: 1984933759, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.45
value: {fileID: -89013944, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.5
value: {fileID: 1990407029, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.5166667
value: {fileID: 1094948637, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- time: 1.5833334
value: {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
attribute: m_Sprite
path: SoundBirdTakeoff/SoundBirdTakeOffAnim
classID: 212 classID: 212
script: {fileID: 0} script: {fileID: 0}
flags: 2 flags: 2
@@ -192,16 +109,7 @@ AnimationClip:
m_ClipBindingConstant: m_ClipBindingConstant:
genericBindings: genericBindings:
- serializedVersion: 2 - serializedVersion: 2
path: 1707885837 path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 631576921
attribute: 0 attribute: 0
script: {fileID: 0} script: {fileID: 0}
typeID: 212 typeID: 212
@@ -248,44 +156,6 @@ AnimationClip:
- {fileID: 1990407029, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3} - {fileID: 1990407029, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1094948637, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3} - {fileID: 1094948637, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3} - {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1035714051, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -740831527, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -648204482, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -960280295, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1144832505, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1860215682, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 519773293, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1067281986, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -36811272, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1592089404, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1729322987, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -91858778, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -26124593, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 259088195, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1746085375, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -182272111, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1436667360, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 545467259, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 121392657, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 938631806, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1943282875, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1918772169, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1252794517, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -927331073, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1038168376, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1855149249, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -2116798272, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 2078607702, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -633261939, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -86103801, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1380056380, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1797284751, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 2004539437, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1984933759, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -89013944, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1990407029, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: 1094948637, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
- {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
m_AnimationClipSettings: m_AnimationClipSettings:
serializedVersion: 2 serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0} m_AdditiveReferencePoseClip: {fileID: 0}

View File

@@ -1,4 +1,5 @@
using Core; using Core;
using Core.SaveLoad;
using Pixelplacement; using Pixelplacement;
using UnityEngine; using UnityEngine;
@@ -8,7 +9,7 @@ public class SoundGenerator : MonoBehaviour
[SerializeField] private Sprite exitSprite; [SerializeField] private Sprite exitSprite;
[SerializeField] private AudioClip enterSound; [SerializeField] private AudioClip enterSound;
[SerializeField] private AppleAudioSource audioSource; [SerializeField] private AppleAudioSource audioSource;
[SerializeField] private StateMachine soundBirdSMRef; [SerializeField] private AppleMachine soundBirdSMRef;
[SerializeField] private soundBird_CanFly soundbirdHearingCheck; [SerializeField] private soundBird_CanFly soundbirdHearingCheck;
private bool playerInside = false; private bool playerInside = false;
@@ -37,7 +38,7 @@ public class SoundGenerator : MonoBehaviour
{ {
audioSource.audioSource.PlayOneShot(enterSound); audioSource.audioSource.PlayOneShot(enterSound);
} }
if (soundBirdSMRef != null && soundBirdSMRef.currentState.name == "SoundBird" && soundbirdHearingCheck.canFly == true) if (soundBirdSMRef != null && soundBirdSMRef.currentState.name.ToLower().Contains("soundbird") && soundbirdHearingCheck.canFly == true)
{ {
soundBirdSMRef.ChangeState("SoundBirdTakeoff"); soundBirdSMRef.ChangeState("SoundBirdTakeoff");

View File

@@ -1,6 +1,7 @@
using UnityEngine; using UnityEngine;
using Unity.Cinemachine; using Unity.Cinemachine;
using System.Collections; using System.Collections;
using Core.SaveLoad;
using Pixelplacement; using Pixelplacement;
public class cameraSwitcher : MonoBehaviour public class cameraSwitcher : MonoBehaviour
@@ -12,7 +13,7 @@ public class cameraSwitcher : MonoBehaviour
[SerializeField] private float transitionDuration = 0.5f; // Duration of the transition [SerializeField] private float transitionDuration = 0.5f; // Duration of the transition
[SerializeField] private soundBird_FlyingBehaviour flyingBehaviour; [SerializeField] private soundBird_FlyingBehaviour flyingBehaviour;
[SerializeField] private soundBird_TakeOffBehaviour takeOffBehaviour; // New reference [SerializeField] private soundBird_TakeOffBehaviour takeOffBehaviour; // New reference
[SerializeField] private StateMachine birdStateMachine; [SerializeField] private AppleMachine birdStateMachine;
private int playerInsideCount = 0; private int playerInsideCount = 0;
private Coroutine zoomCoroutine; private Coroutine zoomCoroutine;
@@ -32,6 +33,9 @@ public class cameraSwitcher : MonoBehaviour
private void OnTriggerExit2D(Collider2D other) private void OnTriggerExit2D(Collider2D other)
{ {
if (!gameObject.activeInHierarchy)
return;
if (other.CompareTag("Player")) if (other.CompareTag("Player"))
{ {
playerInsideCount--; playerInsideCount--;

View File

@@ -1,3 +1,4 @@
using Core.SaveLoad;
using Pixelplacement; using Pixelplacement;
using Pixelplacement.TweenSystem; using Pixelplacement.TweenSystem;
using UnityEngine; using UnityEngine;
@@ -10,7 +11,7 @@ public class soundBird_FlyingBehaviour : MonoBehaviour
public float flightDelay; public float flightDelay;
public float cooldownTime; public float cooldownTime;
private StateMachine stateMachine; private AppleMachine stateMachine;
private Animator animator; private Animator animator;
private TweenBase objectTween; private TweenBase objectTween;
//private Coroutine cooldownCoroutine; //private Coroutine cooldownCoroutine;
@@ -21,7 +22,7 @@ public class soundBird_FlyingBehaviour : MonoBehaviour
void Awake() void Awake()
{ {
stateMachine = GetComponentInParent<StateMachine>(); stateMachine = GetComponentInParent<AppleMachine>();
animator = GetComponentInParent<Animator>(); animator = GetComponentInParent<Animator>();
} }

View File

@@ -1,3 +1,4 @@
using Core.SaveLoad;
using Pixelplacement; using Pixelplacement;
using Pixelplacement.TweenSystem; using Pixelplacement.TweenSystem;
using UnityEngine; using UnityEngine;
@@ -9,7 +10,7 @@ public class soundBird_LandingBehaviour1 : MonoBehaviour
public float flightDuration; public float flightDuration;
public float flightDelay; public float flightDelay;
public soundBird_FlyingBehaviour flyingBehaviour; public soundBird_FlyingBehaviour flyingBehaviour;
private StateMachine stateMachine; private AppleMachine stateMachine;
private Animator animator; private Animator animator;
private TweenBase objectTween; private TweenBase objectTween;
@@ -18,7 +19,7 @@ public class soundBird_LandingBehaviour1 : MonoBehaviour
void Awake() void Awake()
{ {
stateMachine = GetComponentInParent<StateMachine>(); stateMachine = GetComponentInParent<AppleMachine>();
animator = GetComponentInParent<Animator>(); animator = GetComponentInParent<Animator>();
} }
@@ -52,7 +53,7 @@ public class soundBird_LandingBehaviour1 : MonoBehaviour
if (stateMachine != null) if (stateMachine != null)
{ {
animator.SetBool("isScared", false); animator.SetBool("isScared", false);
stateMachine.ChangeState("SoundBird"); // Change to the desired state name stateMachine.ChangeState(0); // Change to the desired state name
} }
} }

View File

@@ -1,3 +1,4 @@
using Core.SaveLoad;
using Pixelplacement; using Pixelplacement;
using Pixelplacement.TweenSystem; using Pixelplacement.TweenSystem;
using UnityEngine; using UnityEngine;
@@ -9,7 +10,7 @@ public class soundBird_TakeOffBehaviour : MonoBehaviour
public Transform SoundBirdObject; public Transform SoundBirdObject;
public float flightDuration; public float flightDuration;
public float flightDelay; public float flightDelay;
private StateMachine stateMachine; private AppleMachine stateMachine;
private Animator animator; private Animator animator;
private TweenBase objectTween; private TweenBase objectTween;
public soundBird_FlyingBehaviour flyingBehaviour; public soundBird_FlyingBehaviour flyingBehaviour;
@@ -18,7 +19,7 @@ public class soundBird_TakeOffBehaviour : MonoBehaviour
void Awake() void Awake()
{ {
stateMachine = GetComponentInParent<StateMachine>(); stateMachine = GetComponentInParent<AppleMachine>();
animator = GetComponentInParent<Animator>(); animator = GetComponentInParent<Animator>();
} }
// Start is called once before the first execution of Update after the MonoBehaviour is created // Start is called once before the first execution of Update after the MonoBehaviour is created

View File

@@ -105,6 +105,9 @@ namespace Interactions
if (combinationResult == FollowerController.CombinationResult.Successful) if (combinationResult == FollowerController.CombinationResult.Successful)
{ {
// Mark this pickup as picked up (consumed in combination) to prevent restoration
IsPickedUp = true;
// Combination succeeded - original items destroyed, result picked up by TryCombineItems // Combination succeeded - original items destroyed, result picked up by TryCombineItems
FireCombinationEvent(resultItem, heldItemData); FireCombinationEvent(resultItem, heldItemData);
return true; return true;

View File

@@ -14,8 +14,9 @@ namespace Levels
public class LevelSwitch : InteractableBase public class LevelSwitch : InteractableBase
{ {
public LevelSwitchData switchData; public LevelSwitchData switchData;
private SpriteRenderer iconRenderer; private SpriteRenderer _iconRenderer;
private IInteractionSettings interactionSettings; private IInteractionSettings _interactionSettings;
private GameObject _menuObjectRef;
/// <summary> /// <summary>
/// Unity Awake callback. Sets up icon, interactable, and event handlers. /// Unity Awake callback. Sets up icon, interactable, and event handlers.
@@ -26,11 +27,11 @@ namespace Levels
Debug.Log($"[LevelSwitch] Awake called for {gameObject.name} in scene {gameObject.scene.name}"); Debug.Log($"[LevelSwitch] Awake called for {gameObject.name} in scene {gameObject.scene.name}");
if (iconRenderer == null) if (_iconRenderer == null)
iconRenderer = GetComponent<SpriteRenderer>(); _iconRenderer = GetComponent<SpriteRenderer>();
// Initialize settings reference // Initialize settings reference
interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>(); _interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
ApplySwitchData(); ApplySwitchData();
} }
@@ -51,8 +52,8 @@ namespace Levels
/// </summary> /// </summary>
void OnValidate() void OnValidate()
{ {
if (iconRenderer == null) if (_iconRenderer == null)
iconRenderer = GetComponent<SpriteRenderer>(); _iconRenderer = GetComponent<SpriteRenderer>();
ApplySwitchData(); ApplySwitchData();
} }
#endif #endif
@@ -64,8 +65,8 @@ namespace Levels
{ {
if (switchData != null) if (switchData != null)
{ {
if (iconRenderer != null) if (_iconRenderer != null)
iconRenderer.sprite = switchData.mapSprite; _iconRenderer.sprite = switchData.mapSprite;
gameObject.name = switchData.targetLevelSceneName; gameObject.name = switchData.targetLevelSceneName;
// Optionally update other fields, e.g. description // Optionally update other fields, e.g. description
} }
@@ -82,7 +83,7 @@ namespace Levels
return false; return false;
} }
var menuPrefab = interactionSettings?.LevelSwitchMenuPrefab; var menuPrefab = _interactionSettings?.LevelSwitchMenuPrefab;
if (menuPrefab == null) if (menuPrefab == null)
{ {
Debug.LogError("LevelSwitchMenu prefab not assigned in InteractionSettings!"); Debug.LogError("LevelSwitchMenu prefab not assigned in InteractionSettings!");
@@ -90,12 +91,12 @@ namespace Levels
} }
// Spawn the menu overlay // Spawn the menu overlay
var menuGo = Instantiate(menuPrefab); _menuObjectRef = Instantiate(menuPrefab);
var menu = menuGo.GetComponent<LevelSwitchMenu>(); var menu = _menuObjectRef.GetComponent<LevelSwitchMenu>();
if (menu == null) if (menu == null)
{ {
Debug.LogError("LevelSwitchMenu component missing on prefab!"); Debug.LogError("LevelSwitchMenu component missing on prefab!");
Destroy(menuGo); Destroy(_menuObjectRef);
return false; return false;
} }

View File

@@ -106,10 +106,9 @@ namespace Minigames.DivingForPictures
public override int ManagedAwakePriority => 190; public override int ManagedAwakePriority => 190;
public override bool AutoRegisterPausable => true; // Automatic GameManager registration public override bool AutoRegisterPausable => true; // Automatic GameManager registration
protected override void OnManagedAwake() protected override void Awake()
{ {
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>(); base.Awake();
_currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
if (_instance == null) if (_instance == null)
{ {
@@ -119,6 +118,12 @@ namespace Minigames.DivingForPictures
{ {
Destroy(gameObject); Destroy(gameObject);
} }
}
protected override void OnManagedAwake()
{
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
_currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
// Ensure any previous run state is reset when this manager awakes // Ensure any previous run state is reset when this manager awakes
_isGameOver = false; _isGameOver = false;
@@ -187,6 +192,8 @@ namespace Minigames.DivingForPictures
private void Update() private void Update()
{ {
if(_settings == null) return;
_timeSinceLastSpawn += Time.deltaTime; _timeSinceLastSpawn += Time.deltaTime;
// Gradually increase spawn probability over time // Gradually increase spawn probability over time

View File

@@ -611,12 +611,14 @@ public class FollowerController : ManagedBehaviour
newItem = Instantiate(matchingRule.resultPrefab, spawnPos, Quaternion.identity); newItem = Instantiate(matchingRule.resultPrefab, spawnPos, Quaternion.identity);
var resultPickup = newItem.GetComponent<Pickup>(); var resultPickup = newItem.GetComponent<Pickup>();
// Mark items as picked up before destroying (for save system) // Mark items as picked up before disabling (for save system)
pickupA.IsPickedUp = true; pickupA.IsPickedUp = true;
pickupB.IsPickedUp = true; pickupB.IsPickedUp = true;
Destroy(pickupA.gameObject); // Disable instead of destroying immediately so they can save their state
Destroy(pickupB.gameObject); // The save system will mark them as picked up and won't restore them
pickupA.gameObject.SetActive(false);
pickupB.gameObject.SetActive(false);
// Pickup the result (don't drop it!) // Pickup the result (don't drop it!)
TryPickupItem(newItem, resultPickup.itemData, dropItem: false); TryPickupItem(newItem, resultPickup.itemData, dropItem: false);
@@ -787,7 +789,8 @@ public class FollowerController : ManagedBehaviour
/// <summary> /// <summary>
/// Bilateral restoration: Follower tries to find and claim the held item. /// Bilateral restoration: Follower tries to find and claim the held item.
/// If pickup doesn't exist yet, it will try to claim us when it restores. /// If pickup doesn't exist in the scene (e.g., dynamically spawned combined item),
/// spawns it from the itemData.
/// </summary> /// </summary>
private void TryRestoreHeldItem(string heldItemSaveId, string itemDataId) private void TryRestoreHeldItem(string heldItemSaveId, string itemDataId)
{ {
@@ -797,10 +800,30 @@ public class FollowerController : ManagedBehaviour
return; return;
} }
// Try to find the pickup immediately // Try to find the pickup in the scene by SaveId
GameObject heldObject = ItemManager.Instance?.FindPickupBySaveId(heldItemSaveId); GameObject heldObject = ItemManager.Instance?.FindPickupBySaveId(heldItemSaveId);
if (heldObject == null) if (heldObject == null && !string.IsNullOrEmpty(itemDataId))
{
// Item not found in scene - it might be a dynamically spawned combined item
// Try to spawn it from the itemDataId
Logging.Debug($"[FollowerController] Held item not found in scene: {heldItemSaveId}, attempting to spawn from itemId: {itemDataId}");
GameObject prefab = _interactionSettings?.FindPickupPrefabByItemId(itemDataId);
if (prefab != null)
{
// Spawn the item (inactive, since it's being held)
heldObject = Instantiate(prefab, transform.position, Quaternion.identity);
heldObject.SetActive(false);
Logging.Debug($"[FollowerController] Successfully spawned combined item: {itemDataId}");
}
else
{
Logging.Warning($"[FollowerController] Could not find prefab for itemId: {itemDataId}");
return;
}
}
else if (heldObject == null)
{ {
Logging.Debug($"[FollowerController] Held item not found yet: {heldItemSaveId}, waiting for pickup to restore"); Logging.Debug($"[FollowerController] Held item not found yet: {heldItemSaveId}, waiting for pickup to restore");
return; // Pickup will find us when it restores return; // Pickup will find us when it restores
@@ -809,7 +832,9 @@ public class FollowerController : ManagedBehaviour
var pickup = heldObject.GetComponent<Pickup>(); var pickup = heldObject.GetComponent<Pickup>();
if (pickup == null) if (pickup == null)
{ {
Logging.Warning($"[FollowerController] Found object but no Pickup component: {heldItemSaveId}"); Logging.Warning($"[FollowerController] Found/spawned object but no Pickup component: {heldItemSaveId}");
if (heldObject != null)
Destroy(heldObject);
return; return;
} }

View File

@@ -87,15 +87,6 @@ namespace PuzzleS
} }
} }
void OnDisable()
{
if (_interactable != null)
{
_interactable.interactionStarted.RemoveListener(OnInteractionStarted);
_interactable.interactionComplete.RemoveListener(OnInteractionComplete);
}
}
protected override void OnDestroy() protected override void OnDestroy()
{ {
base.OnDestroy(); base.OnDestroy();
@@ -104,6 +95,12 @@ namespace PuzzleS
{ {
PuzzleManager.Instance.UnregisterStepBehaviour(this); PuzzleManager.Instance.UnregisterStepBehaviour(this);
} }
if (_interactable != null)
{
_interactable.interactionStarted.RemoveListener(OnInteractionStarted);
_interactable.interactionComplete.RemoveListener(OnInteractionComplete);
}
} }
/// <summary> /// <summary>

View File

@@ -1,18 +1,22 @@
using UnityEngine; using Core.SaveLoad;
using Pixelplacement; using Pixelplacement;
using UnityEngine;
public class AnneLiseBushBehaviour : MonoBehaviour namespace StateMachines.Quarry.AnneLise
{ {
public class AnneLiseBushBehaviour : MonoBehaviour
{
private StateMachine anneLiseBushStateMachine; private AppleMachine _anneLiseBushStateMachine;
// Start is called once before the first execution of Update after the MonoBehaviour is created // Start is called once before the first execution of Update after the MonoBehaviour is created
void Start() void Start()
{ {
anneLiseBushStateMachine = GetComponent<StateMachine>(); _anneLiseBushStateMachine = GetComponent<AppleMachine>();
} }
public void TakePhoto() public void TakePhoto()
{ {
anneLiseBushStateMachine.ChangeState("TakePhoto"); _anneLiseBushStateMachine.ChangeState("TakePhoto");
}
} }
} }

View File

@@ -15,19 +15,16 @@ namespace StateMachines.Quarry.AnneLise
public UnityEvent animFlash; public UnityEvent animFlash;
public UnityEvent animStart; public UnityEvent animStart;
void Start()
{
// Find references that are needed regardless of enter/restore
_playerCharacter = GameObject.FindWithTag("Player");
_playerTouchController = _playerCharacter.GetComponent<PlayerTouchController>();
}
/// <summary> /// <summary>
/// Called when entering this state during normal gameplay. /// Called when entering this state during normal gameplay.
/// Initiates player movement and triggers photo-taking sequence. /// Initiates player movement and triggers photo-taking sequence.
/// </summary> /// </summary>
public override void OnEnterState() public override void OnEnterState()
{ {
// Find references that are needed regardless of enter/restore
_playerCharacter = GameObject.FindWithTag("Player");
_playerTouchController = _playerCharacter.GetComponent<PlayerTouchController>();
// Subscribe to player arrival event // Subscribe to player arrival event
_playerTouchController.OnArrivedAtTarget += PlayerHasArrived; _playerTouchController.OnArrivedAtTarget += PlayerHasArrived;

View File

@@ -46,13 +46,12 @@ namespace UI
protected override void OnManagedAwake() protected override void OnManagedAwake()
{ {
// Component setup already done in Awake // Subscribe to scene-dependent events - must be in OnManagedAwake, not OnSceneReady
} // because PauseMenu is in DontDestroyOnLoad and OnSceneReady only fires once
if (SceneManagerService.Instance != null)
protected override void OnSceneReady()
{ {
// Subscribe to scene-dependent events
SceneManagerService.Instance.SceneLoadCompleted += SetPauseMenuByLevel; SceneManagerService.Instance.SceneLoadCompleted += SetPauseMenuByLevel;
}
// Also react to global UI hide/show events from the page controller // Also react to global UI hide/show events from the page controller
if (UIPageController.Instance != null) if (UIPageController.Instance != null)
@@ -67,6 +66,11 @@ namespace UI
Logging.Debug("[PauseMenu] Subscribed to SceneManagerService events"); Logging.Debug("[PauseMenu] Subscribed to SceneManagerService events");
} }
protected override void OnSceneReady()
{
// This only fires once for DontDestroyOnLoad objects, so we handle scene loads in OnManagedAwake
}
protected override void OnDestroy() protected override void OnDestroy()
{ {
base.OnDestroy(); base.OnDestroy();
@@ -89,17 +93,30 @@ namespace UI
/// <param name="levelName">The name of the level/scene</param> /// <param name="levelName">The name of the level/scene</param>
public void SetPauseMenuByLevel(string levelName) public void SetPauseMenuByLevel(string levelName)
{ {
HidePauseMenu(); // When a new scene loads, ensure pause menu is removed from UIPageController stack
// TODO: Implement level-based pause menu visibility logic if needed // and properly hidden, regardless of pause state
/*if (string.IsNullOrEmpty(levelName)) if (UIPageController.Instance != null && UIPageController.Instance.CurrentPage == this)
return; {
UIPageController.Instance.PopPage();
}
bool isStartingLevel = levelName.ToLower().Contains("startingscene"); // Ensure pause state is cleared
if (GameManager.Instance != null && GameManager.Instance.IsPaused)
{
EndPauseSideEffects();
}
if(isStartingLevel) // Hide the menu UI
HidePauseMenu(false); // Ensure menu is hidden when switching to a game level if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
if (canvasGroup != null)
{
canvasGroup.alpha = 0f;
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
}
gameObject.SetActive(false);
Logging.Debug($"[PauseMenu] Setting pause menu active: {!isStartingLevel} for scene: {levelName}");*/ Logging.Debug($"[PauseMenu] Cleaned up pause menu state for scene: {levelName}");
} }
/// <summary> /// <summary>
@@ -246,6 +263,18 @@ namespace UI
/// </summary> /// </summary>
public async void ExitToAppleHills() public async void ExitToAppleHills()
{ {
// Pop from UIPageController stack before switching scenes
if (UIPageController.Instance != null && UIPageController.Instance.CurrentPage == this)
{
UIPageController.Instance.PopPage();
}
// Ensure pause state is cleared
if (GameManager.Instance != null && GameManager.Instance.IsPaused)
{
EndPauseSideEffects();
}
// Replace with the actual scene name as set in Build Settings // Replace with the actual scene name as set in Build Settings
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%")); var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
await SceneManagerService.Instance.SwitchSceneAsync("AppleHillsOverworld", progress); await SceneManagerService.Instance.SwitchSceneAsync("AppleHillsOverworld", progress);

File diff suppressed because it is too large Load Diff