Compare commits
44 Commits
dfa42b2296
...
kill-json-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d647bb5707 | ||
|
|
dec7ced2d1 | ||
|
|
c4d356886f | ||
|
|
64d7f19b83 | ||
| ce21e8b02e | |||
| f44f8c5171 | |||
| 9772206362 | |||
|
|
3ebbecc277 | ||
|
|
c99aad49f3 | ||
| 3fe4c6afd9 | |||
| 9c61065947 | |||
|
|
7c09db641a | ||
|
|
e369660a8f | ||
| a6e3413499 | |||
| 7bb992acb8 | |||
|
|
cefa488a92 | ||
| 9344f06886 | |||
| af7e081c9a | |||
|
|
4a6ac7281f | ||
| 861797ba41 | |||
| 98883bd382 | |||
| 474941f421 | |||
|
|
75cd70a18a | ||
| e82ec90723 | |||
|
|
252cb99884 | ||
| 3f548c3ed4 | |||
|
|
0c9a388433 | ||
|
|
a80aed8eb7 | ||
|
|
5d0a9f999a | ||
|
|
eda7361702 | ||
|
|
2ec53629c6 | ||
|
|
0e55248698 | ||
|
|
4d7c48a681 | ||
|
|
6e466cd7aa | ||
| 29d01df3ce | |||
| de0a243b1e | |||
| fdfa4e0e09 | |||
|
|
2127bf37b2 | ||
| ea12766cf7 | |||
| 41c71f07fd | |||
| d2e79f058b | |||
| 1bcb63ffd0 | |||
| de2966fb1e | |||
| e27bb7bfb6 |
5
.github/copilot-instructions.md
vendored
5
.github/copilot-instructions.md
vendored
@@ -1,5 +0,0 @@
|
||||
You are an expert code architect and developer. YOu prioritize clean, efficient, and maintainable code.
|
||||
You priotize up-front though out planning before writing code.
|
||||
You will always present implementaiton plan first and always ask for permission to implement it.
|
||||
Never insert zero-width spaces or non-breaking spaces in my code.
|
||||
DOn't produce .MD documentation unless i ask you to.
|
||||
@@ -15,7 +15,7 @@ MonoBehaviour:
|
||||
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
|
||||
m_currentHash:
|
||||
serializedVersion: 2
|
||||
Hash: f08b6489862aaf7bfceb29f571e2ef6c
|
||||
Hash: 589e22fe6cd2fe0e25d89bd44a35bcbc
|
||||
m_OptimizeCatalogSize: 0
|
||||
m_BuildRemoteCatalog: 0
|
||||
m_CatalogRequestsTimeout: 0
|
||||
|
||||
8
Assets/AddressableAssetsData/iOS.meta
Normal file
8
Assets/AddressableAssetsData/iOS.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d60f8ff6bf46b494b80e210228c43e61
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -122,6 +122,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
|
||||
@@ -122,6 +122,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
|
||||
BIN
Assets/Art/UI/DR/ramasjang_icon.png
Normal file
BIN
Assets/Art/UI/DR/ramasjang_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
156
Assets/Art/UI/DR/ramasjang_icon.png.meta
Normal file
156
Assets/Art/UI/DR/ramasjang_icon.png.meta
Normal file
@@ -0,0 +1,156 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57224356af3d045dbbf8b420e13b4b10
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 2364528222304962155
|
||||
second: ramasjang_icon_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: iOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: ramasjang_icon_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 4
|
||||
y: 5
|
||||
width: 334
|
||||
height: 334
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: b668fdfe3ed70d020800000000000000
|
||||
internalID: 2364528222304962155
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
ramasjang_icon_0: 2364528222304962155
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -18,12 +18,10 @@ MonoBehaviour:
|
||||
- {fileID: 458265635552197097, guid: a77d1e8b2fa8aa945a6f39b312536e0d, type: 3}
|
||||
- {fileID: 552225285624929822, guid: e39992796d5459442be9967c77e27066, type: 3}
|
||||
- {fileID: 7644433920135100480, guid: 12d242e44fe80ab44af852254b7cab0f, type: 3}
|
||||
- {fileID: 1794231825201849485, guid: 6fb0d7fc6faad154b8c3e3cb7abb7c15, type: 3}
|
||||
- {fileID: 6399527186463168339, guid: ac41583865245bc4bb3de6c15929b9fc, type: 3}
|
||||
- {fileID: 2755712733105741372, guid: 70e6fca1164d9a140b271f4261f1f023, type: 3}
|
||||
- {fileID: 5034240524438268576, guid: adbb9bfd5489f3f4995966535ca5f24b, type: 3}
|
||||
- {fileID: 2326026072467672024, guid: c8d9eb8c3ca524b4eb67f6364b455b87, type: 3}
|
||||
- {fileID: 3528960956969533010, guid: 53eea3840d3cde34a9768b8773a3a7e8, type: 3}
|
||||
- {fileID: 9076822654798104907, guid: 4684df63af6398f4f9f624a35023f8d2, type: 3}
|
||||
- {fileID: 3863019143023165617, guid: 774e30e3f0b1d0d49bad0c2abf11038a, type: 3}
|
||||
- {fileID: 5034240524438268576, guid: b15ba9d3d508ef244b0eeb76404dc9de, type: 3}
|
||||
- {fileID: 7207007194116694737, guid: 7180ae585f0db8044ba048426f72d995, type: 3}
|
||||
|
||||
3
Assets/Editor/Lifecycle.meta
Normal file
3
Assets/Editor/Lifecycle.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5d626da49844592981ef14524e3a308
|
||||
timeCreated: 1762332131
|
||||
144
Assets/Editor/Lifecycle/EditorLifecycleBootstrap.cs
Normal file
144
Assets/Editor/Lifecycle/EditorLifecycleBootstrap.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Core.Lifecycle;
|
||||
using Core.SaveLoad;
|
||||
using AppleHills.Core.Settings;
|
||||
using Bootstrap;
|
||||
|
||||
namespace Editor.Lifecycle
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor-only bootstrap that ensures OnSceneReady is triggered when playing directly from a scene in Unity Editor.
|
||||
///
|
||||
/// PROBLEM: When you press Play in the editor without going through the scene manager:
|
||||
/// - CustomBoot runs and triggers OnBootCompletionTriggered (which broadcasts OnManagedAwake)
|
||||
/// - But BroadcastSceneReady is NEVER called for the initial scene
|
||||
/// - Components in the scene never receive their OnSceneReady() callback
|
||||
///
|
||||
/// SOLUTION: After boot completes, detect the active scene and broadcast OnSceneReady for it.
|
||||
/// This only runs in editor mode and mimics what SceneManagerService does during normal scene transitions.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public static class EditorLifecycleBootstrap
|
||||
{
|
||||
private static bool hasTriggeredInitialSceneReady = false;
|
||||
private static int framesSincePlayMode = 0;
|
||||
private const int MaxFramesToWait = 300; // 5 seconds at 60fps
|
||||
|
||||
static EditorLifecycleBootstrap()
|
||||
{
|
||||
// Subscribe to play mode state changes
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private static void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
// Reset flag when exiting play mode
|
||||
if (state == PlayModeStateChange.ExitingPlayMode || state == PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
hasTriggeredInitialSceneReady = false;
|
||||
framesSincePlayMode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// When we enter play mode, wait for boot to complete then trigger scene ready
|
||||
if (state == PlayModeStateChange.EnteredPlayMode)
|
||||
{
|
||||
hasTriggeredInitialSceneReady = false;
|
||||
framesSincePlayMode = 0;
|
||||
|
||||
// Use EditorApplication.update to poll until boot completes
|
||||
EditorApplication.update += WaitForBootAndTriggerSceneReady;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WaitForBootAndTriggerSceneReady()
|
||||
{
|
||||
framesSincePlayMode++;
|
||||
|
||||
// Safety timeout - if boot hasn't completed after 5 seconds, something is wrong
|
||||
if (framesSincePlayMode > MaxFramesToWait)
|
||||
{
|
||||
Debug.LogError($"[EditorLifecycleBootstrap] Timed out waiting for boot completion after {MaxFramesToWait} frames. " +
|
||||
"CustomBoot may have failed to initialize properly.");
|
||||
EditorApplication.update -= WaitForBootAndTriggerSceneReady;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if boot has completed
|
||||
if (!CustomBoot.Initialised)
|
||||
return;
|
||||
|
||||
// Check if LifecycleManager exists
|
||||
if (LifecycleManager.Instance == null)
|
||||
{
|
||||
Debug.LogWarning("[EditorLifecycleBootstrap] LifecycleManager instance not found. " +
|
||||
"Lifecycle may not be properly initialized.");
|
||||
EditorApplication.update -= WaitForBootAndTriggerSceneReady;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only trigger once per play session
|
||||
if (hasTriggeredInitialSceneReady)
|
||||
{
|
||||
EditorApplication.update -= WaitForBootAndTriggerSceneReady;
|
||||
return;
|
||||
}
|
||||
|
||||
hasTriggeredInitialSceneReady = true;
|
||||
EditorApplication.update -= WaitForBootAndTriggerSceneReady;
|
||||
|
||||
// Get the active scene
|
||||
Scene activeScene = SceneManager.GetActiveScene();
|
||||
|
||||
if (!activeScene.isLoaded)
|
||||
{
|
||||
Debug.LogWarning($"[EditorLifecycleBootstrap] Active scene '{activeScene.name}' is not loaded.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip bootstrap scene - it doesn't need scene ready
|
||||
// Note: BootstrapScene is the infrastructure scene, not a gameplay scene
|
||||
if (activeScene.name == "BootstrapScene" || activeScene.name == "Bootstrap")
|
||||
{
|
||||
Debug.Log($"[EditorLifecycleBootstrap] Skipping OnSceneReady for infrastructure scene: {activeScene.name}");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"<color=cyan>[EditorLifecycleBootstrap] Triggering lifecycle for initial scene: {activeScene.name}</color>");
|
||||
|
||||
// Broadcast scene ready for the initial scene
|
||||
// This mimics what SceneManagerService does during scene transitions (Phase 10)
|
||||
try
|
||||
{
|
||||
LifecycleManager.Instance.BroadcastSceneReady(activeScene.name);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[EditorLifecycleBootstrap] Error broadcasting SceneReady: {ex.Message}\n{ex.StackTrace}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Restore scene-specific data via SaveLoadManager
|
||||
// This mimics SceneManagerService Phase 11
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
||||
if (debugSettings.useSaveLoadSystem)
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.Log($"[EditorLifecycleBootstrap] Restoring scene data for: {activeScene.name}");
|
||||
SaveLoadManager.Instance.RestoreSceneData();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[EditorLifecycleBootstrap] Error restoring scene data: {ex.Message}\n{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
Assets/Editor/Lifecycle/EditorLifecycleBootstrap.cs.meta
Normal file
9
Assets/Editor/Lifecycle/EditorLifecycleBootstrap.cs.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f3e8a9c4d5b6e7f8a9b0c1d2e3f4a5b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Editor.Tools
|
||||
private string searchTypeName = "Select a Component...";
|
||||
private string replaceTypeName = "Select a Component...";
|
||||
private List<Type> allMonoBehaviourTypes = new List<Type>();
|
||||
private bool includeDerivedTypes = true;
|
||||
|
||||
[MenuItem("Tools/Component Search & Replace")]
|
||||
public static void ShowWindow()
|
||||
@@ -102,6 +103,15 @@ namespace Editor.Tools
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
// Include Derived Types checkbox
|
||||
includeDerivedTypes = EditorGUILayout.Toggle(
|
||||
new GUIContent("Include Derived Types",
|
||||
"When enabled, searches for the selected type and all types that inherit from it. " +
|
||||
"When disabled, searches only for the exact type."),
|
||||
includeDerivedTypes);
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
EditorGUI.BeginDisabledGroup(selectedSearchType == null);
|
||||
if (GUILayout.Button("Search Scene", GUILayout.Height(30)))
|
||||
{
|
||||
@@ -242,7 +252,20 @@ namespace Editor.Tools
|
||||
|
||||
foreach (var go in allObjects)
|
||||
{
|
||||
var component = go.GetComponent(selectedSearchType);
|
||||
Component component = null;
|
||||
|
||||
if (includeDerivedTypes)
|
||||
{
|
||||
// Search for the type and all derived types
|
||||
component = go.GetComponent(selectedSearchType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for exact type only
|
||||
var components = go.GetComponents<Component>();
|
||||
component = components.FirstOrDefault(c => c != null && c.GetType() == selectedSearchType);
|
||||
}
|
||||
|
||||
if (component != null)
|
||||
{
|
||||
foundComponents.Add(new ComponentInfo
|
||||
@@ -256,7 +279,8 @@ namespace Editor.Tools
|
||||
|
||||
foundComponents = foundComponents.OrderBy(c => c.hierarchyPath).ToList();
|
||||
|
||||
Debug.Log($"Found {foundComponents.Count} objects with component type '{selectedSearchType.Name}'");
|
||||
string searchMode = includeDerivedTypes ? "including derived types" : "exact type only";
|
||||
Debug.Log($"Found {foundComponents.Count} objects with component type '{selectedSearchType.Name}' ({searchMode})");
|
||||
Repaint();
|
||||
}
|
||||
|
||||
|
||||
31
Assets/Editor/Tools/DebugSaveIds.cs
Normal file
31
Assets/Editor/Tools/DebugSaveIds.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using Core.Lifecycle;
|
||||
|
||||
namespace Editor.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor utility to debug SaveIds for all ManagedBehaviours in the scene
|
||||
/// </summary>
|
||||
public class DebugSaveIds : EditorWindow
|
||||
{
|
||||
[MenuItem("Tools/Debug/Log All SaveIds")]
|
||||
public static void LogAllSaveIds()
|
||||
{
|
||||
var allManaged = FindObjectsByType<ManagedBehaviour>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
|
||||
Debug.Log($"=== Found {allManaged.Length} ManagedBehaviours ===");
|
||||
|
||||
foreach (var managed in allManaged)
|
||||
{
|
||||
if (managed.AutoRegisterForSave)
|
||||
{
|
||||
Debug.Log($"GameObject: {managed.gameObject.name} | Component: {managed.GetType().Name} | SaveID: {managed.SaveId}");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("=== End SaveIds ===");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Editor/Tools/DebugSaveIds.cs.meta
Normal file
3
Assets/Editor/Tools/DebugSaveIds.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a34fbba4efbb4acd85d79a99abf00a08
|
||||
timeCreated: 1762358959
|
||||
@@ -1978,11 +1978,11 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 1.85
|
||||
value: 0.09
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 5.14
|
||||
value: 3.44
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3484825090253933040, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
|
||||
@@ -248,7 +248,9 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 2bd397a60643eed45b586961ae6e3453, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::PulverAudioController
|
||||
audioSource: {fileID: 887004370483616855}
|
||||
combineAudio: {fileID: 8300000, guid: 768a16f348fe1d94c9cc267dc7ecf3b5, type: 3}
|
||||
itemManager: {fileID: 0}
|
||||
--- !u!82 &4467608046243604209
|
||||
AudioSource:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -105,7 +105,7 @@ GameObject:
|
||||
- component: {fileID: 3487003259787903584}
|
||||
- component: {fileID: 2277261512137882881}
|
||||
m_Layer: 10
|
||||
m_Name: LureSpotA
|
||||
m_Name: LureSpotA_Slot
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -260,9 +260,9 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: aaf36cd26cf74334e9c7db6c1b03b3fb, type: 2}
|
||||
iconRenderer: {fileID: 6258593095132504700}
|
||||
slottedItemRenderer: {fileID: 4110666412151536905}
|
||||
onItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
@@ -314,7 +314,6 @@ MonoBehaviour:
|
||||
onForbiddenItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
slottedItemRenderer: {fileID: 4110666412151536905}
|
||||
--- !u!114 &3487003259787903584
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -1069,7 +1069,7 @@ GameObject:
|
||||
- component: {fileID: 3093816592344978065}
|
||||
- component: {fileID: 8758136668472096799}
|
||||
m_Layer: 10
|
||||
m_Name: LureSpotB
|
||||
m_Name: LureSpotB_Slot
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -1168,9 +1168,9 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: f97b9e24d6dceb145b56426c1152ebeb, type: 2}
|
||||
iconRenderer: {fileID: 2343214996212089369}
|
||||
slottedItemRenderer: {fileID: 7990414055343410434}
|
||||
onItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
@@ -1234,7 +1234,6 @@ MonoBehaviour:
|
||||
onForbiddenItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
slottedItemRenderer: {fileID: 7990414055343410434}
|
||||
--- !u!114 &8758136668472096799
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -247,7 +247,7 @@ GameObject:
|
||||
- component: {fileID: 3169137887822749614}
|
||||
- component: {fileID: 8370367816617117734}
|
||||
m_Layer: 10
|
||||
m_Name: LureSpotC
|
||||
m_Name: LureSpotC_Slot
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -346,9 +346,9 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: c68dea945fecbf44094359769db04f31, type: 2}
|
||||
iconRenderer: {fileID: 2825253017896168654}
|
||||
slottedItemRenderer: {fileID: 3806274462998212361}
|
||||
onItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
@@ -412,7 +412,6 @@ MonoBehaviour:
|
||||
onForbiddenItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
slottedItemRenderer: {fileID: 3806274462998212361}
|
||||
--- !u!114 &6535246856440349519
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -44,10 +44,10 @@ GameObject:
|
||||
- component: {fileID: 5057760771402457000}
|
||||
- component: {fileID: 2433130051631076285}
|
||||
- component: {fileID: 7290110366808972859}
|
||||
- component: {fileID: 4831635791684479552}
|
||||
- component: {fileID: 9196152289301358918}
|
||||
- component: {fileID: 2596311128101197840}
|
||||
m_Layer: 10
|
||||
m_Name: SoundBird
|
||||
m_Name: SoundBird_Slot
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -201,9 +201,9 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: d28f5774afad9d14f823601707150700, type: 2}
|
||||
iconRenderer: {fileID: 8875860401447896107}
|
||||
slottedItemRenderer: {fileID: 6941190210788968874}
|
||||
onItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
@@ -231,7 +231,6 @@ MonoBehaviour:
|
||||
onForbiddenItemSlotted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
slottedItemRenderer: {fileID: 6941190210788968874}
|
||||
--- !u!114 &7290110366808972859
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -246,18 +245,6 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
luredBird: {fileID: 4624889622840393752}
|
||||
annaLiseSpot: {fileID: 22512726373136855}
|
||||
--- !u!114 &4831635791684479552
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 588897581313790951}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: eaefd3d5a2a864ca5b5d9ec5f2a7040f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!95 &9196152289301358918
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
@@ -280,6 +267,18 @@ Animator:
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!114 &2596311128101197840
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 588897581313790951}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 95e46aacea5b42888ee7881894193c11, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.AppleState
|
||||
--- !u!1 &4624889622840393752
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -166,7 +166,6 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: 0c6986639ca176a419c92f5a327d95ce, type: 2}
|
||||
iconRenderer: {fileID: 7494677664706785084}
|
||||
--- !u!1001 &8589202998731622905
|
||||
|
||||
@@ -140,6 +140,5 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: 43f22dbbb4c0eec4f8108d0f0eea43c2, type: 2}
|
||||
iconRenderer: {fileID: 4055726361761331703}
|
||||
|
||||
@@ -140,6 +140,5 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: a8baa800efa25a344a95b190cf349e2d, type: 2}
|
||||
iconRenderer: {fileID: 4774534086162962138}
|
||||
|
||||
@@ -140,6 +140,5 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: 560ba2059ce14dc4da580e2f43b2e65f, type: 2}
|
||||
iconRenderer: {fileID: 4986096986936361008}
|
||||
|
||||
@@ -140,6 +140,5 @@ MonoBehaviour:
|
||||
interactionComplete:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
itemData: {fileID: 11400000, guid: 3b1f3472171abc943bb099ce31d6fc7c, type: 2}
|
||||
iconRenderer: {fileID: 4266110216568578813}
|
||||
|
||||
267
Assets/Prefabs/Managers/CinematicSprites.prefab
Normal file
267
Assets/Prefabs/Managers/CinematicSprites.prefab
Normal file
@@ -0,0 +1,267 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3880639403919980708
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 491766053509356801}
|
||||
- component: {fileID: 8990835369174097178}
|
||||
- component: {fileID: 4081412022221009731}
|
||||
- component: {fileID: 7110521945075217718}
|
||||
- component: {fileID: 7238901747877844110}
|
||||
m_Layer: 5
|
||||
m_Name: CinematicSprites
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &491766053509356801
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3880639403919980708}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 5590617373016130179}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8990835369174097178
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3880639403919980708}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4081412022221009731
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3880639403919980708}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 21300000, guid: 521b8943618ee4941a59b55cba521053, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!95 &7110521945075217718
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3880639403919980708}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: e2a3b3586acd1ea4097d75c6f7d0cf0a, type: 2}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_AnimatePhysics: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!114 &7238901747877844110
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3880639403919980708}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5526348c1593f9b43987b0edcaccdd24, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: '::'
|
||||
holdDuration: 1
|
||||
radialProgressBar: {fileID: 7802237016353117620}
|
||||
--- !u!1 &4881325085870413093
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8394866771001925093}
|
||||
- component: {fileID: 6474291411781573184}
|
||||
- component: {fileID: 3495568374332906101}
|
||||
m_Layer: 5
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8394866771001925093
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4881325085870413093}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5590617373016130179}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.2, y: 0.2}
|
||||
m_AnchorMax: {x: 0.8, y: 0.8}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6474291411781573184
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4881325085870413093}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &3495568374332906101
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4881325085870413093}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -5941552768301239376, guid: 300528d856c15824989bade57a7e04e4, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &8647185569012928468
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5590617373016130179}
|
||||
- component: {fileID: 5038311757077579968}
|
||||
- component: {fileID: 7802237016353117620}
|
||||
m_Layer: 5
|
||||
m_Name: SkipProgress
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5590617373016130179
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8647185569012928468}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 8394866771001925093}
|
||||
m_Father: {fileID: 491766053509356801}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: -56, y: 64}
|
||||
m_SizeDelta: {x: 250, y: 250}
|
||||
m_Pivot: {x: 1, y: 0}
|
||||
--- !u!222 &5038311757077579968
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8647185569012928468}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &7802237016353117620
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8647185569012928468}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 2758595457390328306, guid: bcd3fab43168dbd43a286294c6cc7838, type: 3}
|
||||
m_Type: 3
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 0
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 774e30e3f0b1d0d49bad0c2abf11038a
|
||||
guid: 28ef853079fd9524f970703cd64bd0c0
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@@ -11,7 +11,6 @@ GameObject:
|
||||
- component: {fileID: 1965178107275650778}
|
||||
- component: {fileID: 2828019556092814789}
|
||||
- component: {fileID: 3751190220360366860}
|
||||
- component: {fileID: 803378854493527400}
|
||||
m_Layer: 0
|
||||
m_Name: SpilSlut
|
||||
m_TagString: Untagged
|
||||
@@ -93,7 +92,7 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 136.55
|
||||
m_fontSize: 136.85
|
||||
m_fontSizeBase: 72
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
@@ -137,95 +136,6 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!114 &803378854493527400
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 663813761358815781}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 86710e43de46f6f4bac7c8e50813a599, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.AspectRatioFitter
|
||||
m_AspectMode: 1
|
||||
m_AspectRatio: 12
|
||||
--- !u!1 &671326379795878693
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4498104668003212261}
|
||||
- component: {fileID: 1384216111310773312}
|
||||
- component: {fileID: 8822046367999630453}
|
||||
m_Layer: 5
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4498104668003212261
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 671326379795878693}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 538506048417711235}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.2, y: 0.2}
|
||||
m_AnchorMax: {x: 0.8, y: 0.8}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &1384216111310773312
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 671326379795878693}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8822046367999630453
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 671326379795878693}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -5941552768301239376, guid: 300528d856c15824989bade57a7e04e4, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &1519948061307491961
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -498,9 +408,9 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 754661265897109340}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 683.9956, y: -157.62965}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 640.62054, y: 0}
|
||||
m_SizeDelta: {x: 268, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &1768576830901014477
|
||||
@@ -642,8 +552,6 @@ RectTransform:
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4978134902377398530}
|
||||
- {fileID: 5494371867874695937}
|
||||
- {fileID: 5708275729410901669}
|
||||
m_Father: {fileID: 5006436358316225511}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -725,7 +633,6 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 5006436358316225511}
|
||||
- component: {fileID: 4093256939237236730}
|
||||
- component: {fileID: 291412605997816487}
|
||||
m_Layer: 0
|
||||
m_Name: CinematicsManager
|
||||
m_TagString: Untagged
|
||||
@@ -761,47 +668,10 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 4e3cd69fd77a22640aa40e691d8d6c26, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::CinematicsManager
|
||||
cinematicSpritesGameObject: {fileID: 9166576207668444836}
|
||||
cinematicBackground: {fileID: 3837694223035649714}
|
||||
cinematicSpritesGameObject: {fileID: 0}
|
||||
cinematicBackground: {fileID: 0}
|
||||
divingGameOverScreen: {fileID: 7927991410039509668}
|
||||
playableDirector: {fileID: 291412605997816487}
|
||||
--- !u!320 &291412605997816487
|
||||
PlayableDirector:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2755712733105741372}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_PlayableAsset: {fileID: 11400000, guid: 10f0c6cee53c1364198438ae185f38fe, type: 2}
|
||||
m_InitialState: 0
|
||||
m_WrapMode: 2
|
||||
m_DirectorUpdateMode: 2
|
||||
m_InitialTime: 0
|
||||
m_SceneBindings:
|
||||
- key: {fileID: -38993752814118673, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
value: {fileID: 2900690403017929526}
|
||||
- key: {fileID: 7845336411882145130, guid: 99c48feb9d744ba4eb579c3b631b9257, type: 2}
|
||||
value: {fileID: 2900690403017929526}
|
||||
- key: {fileID: -8222318252314758605, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
value: {fileID: 0}
|
||||
- key: {fileID: 7536617106820686252, guid: 10f0c6cee53c1364198438ae185f38fe, type: 2}
|
||||
value: {fileID: 0}
|
||||
- key: {fileID: 8636189198204744120, guid: 10f0c6cee53c1364198438ae185f38fe, type: 2}
|
||||
value: {fileID: 2900690403017929526}
|
||||
- key: {fileID: 139419469794405637, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
value: {fileID: 0}
|
||||
- key: {fileID: 8785081636201331406, guid: 400e13ef8f17b5841acd92120f67a092, type: 2}
|
||||
value: {fileID: 0}
|
||||
- key: {fileID: -446339716597930989, guid: 400e13ef8f17b5841acd92120f67a092, type: 2}
|
||||
value: {fileID: 2900690403017929526}
|
||||
- key: {fileID: -5410086080836277403, guid: 10f0c6cee53c1364198438ae185f38fe, type: 2}
|
||||
value: {fileID: 0}
|
||||
- key: {fileID: -427775867803860694, guid: 10f0c6cee53c1364198438ae185f38fe, type: 2}
|
||||
value: {fileID: 0}
|
||||
m_ExposedReferences:
|
||||
m_References: []
|
||||
playableDirector: {fileID: 0}
|
||||
--- !u!1 &3025814654250773583
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -938,158 +808,6 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &3669323127008070100
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 538506048417711235}
|
||||
- component: {fileID: 1082932495279705792}
|
||||
- component: {fileID: 2786577800096043956}
|
||||
m_Layer: 5
|
||||
m_Name: SkipProgress
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &538506048417711235
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3669323127008070100}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4498104668003212261}
|
||||
m_Father: {fileID: 5494371867874695937}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: -56, y: 64}
|
||||
m_SizeDelta: {x: 250, y: 250}
|
||||
m_Pivot: {x: 1, y: 0}
|
||||
--- !u!222 &1082932495279705792
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3669323127008070100}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2786577800096043956
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3669323127008070100}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 2758595457390328306, guid: bcd3fab43168dbd43a286294c6cc7838, type: 3}
|
||||
m_Type: 3
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 0
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &3837694223035649714
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4978134902377398530}
|
||||
- component: {fileID: 2314847656825276738}
|
||||
- component: {fileID: 923855569538630903}
|
||||
m_Layer: 5
|
||||
m_Name: CinematicBackground
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &4978134902377398530
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3837694223035649714}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 9195361253609918804}
|
||||
m_Father: {fileID: 592992386388815559}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -0.0025634766, y: -1380.1166}
|
||||
m_SizeDelta: {x: 1920, y: 1399.7874}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2314847656825276738
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3837694223035649714}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &923855569538630903
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3837694223035649714}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &3907121777593230662
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1255,15 +973,15 @@ RectTransform:
|
||||
m_GameObject: {fileID: 3935369085067290987}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_LocalScale: {x: 3, y: 3, z: 3}
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children: []
|
||||
m_Father: {fileID: 754661265897109340}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 174.99854, y: -157.62965}
|
||||
m_SizeDelta: {x: 150, y: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 270.45056, y: 0}
|
||||
m_SizeDelta: {x: 42, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2782310018074465201
|
||||
CanvasRenderer:
|
||||
@@ -1402,15 +1120,15 @@ RectTransform:
|
||||
m_GameObject: {fileID: 4068599104538777648}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_LocalScale: {x: 3, y: 3, z: 3}
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children: []
|
||||
m_Father: {fileID: 754661265897109340}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 1192.9927, y: -157.62965}
|
||||
m_SizeDelta: {x: 150, y: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 1010.7905, y: 0}
|
||||
m_SizeDelta: {x: 42, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8344156654954553365
|
||||
CanvasRenderer:
|
||||
@@ -1530,7 +1248,6 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 754661265897109340}
|
||||
- component: {fileID: 7750609879083104855}
|
||||
- component: {fileID: 5441545775684538830}
|
||||
m_Layer: 0
|
||||
m_Name: Buttons
|
||||
m_TagString: Untagged
|
||||
@@ -1557,8 +1274,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.10938991, y: 0.11800001}
|
||||
m_AnchorMax: {x: 0.94400007, y: 0.41016972}
|
||||
m_AnchoredPosition: {x: 0, y: 4}
|
||||
m_SizeDelta: {x: 0, y: -4}
|
||||
m_AnchoredPosition: {x: -0.00024414062, y: 0}
|
||||
m_SizeDelta: {x: -86.75, y: -20.246}
|
||||
m_Pivot: {x: 0.5, y: 0}
|
||||
--- !u!114 &7750609879083104855
|
||||
MonoBehaviour:
|
||||
@@ -1578,214 +1295,11 @@ MonoBehaviour:
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 4
|
||||
m_Spacing: 100
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_Spacing: 215.17
|
||||
m_ChildForceExpandWidth: 0
|
||||
m_ChildForceExpandHeight: 0
|
||||
m_ChildControlWidth: 1
|
||||
m_ChildControlHeight: 1
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &5441545775684538830
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8262879347725397662}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 86710e43de46f6f4bac7c8e50813a599, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.AspectRatioFitter
|
||||
m_AspectMode: 0
|
||||
m_AspectRatio: 4.3392572
|
||||
--- !u!1 &8938058918530086601
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 9195361253609918804}
|
||||
- component: {fileID: 6918160369029793220}
|
||||
- component: {fileID: 276527935528622190}
|
||||
m_Layer: 5
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &9195361253609918804
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8938058918530086601}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4978134902377398530}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 1733.7644}
|
||||
m_SizeDelta: {x: 1920, y: 2057.6729}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6918160369029793220
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8938058918530086601}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &276527935528622190
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8938058918530086601}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.79215693, g: 0.9294118, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &9166576207668444836
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5494371867874695937}
|
||||
- component: {fileID: 3902696341833554714}
|
||||
- component: {fileID: 8235080513953117507}
|
||||
- component: {fileID: 2900690403017929526}
|
||||
- component: {fileID: 3357796695825044110}
|
||||
m_Layer: 5
|
||||
m_Name: CinematicSprites
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &5494371867874695937
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9166576207668444836}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 538506048417711235}
|
||||
m_Father: {fileID: 592992386388815559}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3902696341833554714
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9166576207668444836}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8235080513953117507
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9166576207668444836}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 21300000, guid: 521b8943618ee4941a59b55cba521053, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!95 &2900690403017929526
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9166576207668444836}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: e2a3b3586acd1ea4097d75c6f7d0cf0a, type: 2}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_AnimatePhysics: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!114 &3357796695825044110
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9166576207668444836}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5526348c1593f9b43987b0edcaccdd24, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: '::'
|
||||
holdDuration: 1
|
||||
radialProgressBar: {fileID: 2786577800096043956}
|
||||
|
||||
1674
Assets/Prefabs/Managers/PlayerHUD.prefab
Normal file
1674
Assets/Prefabs/Managers/PlayerHUD.prefab
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Prefabs/Managers/PlayerHUD.prefab.meta
Normal file
7
Assets/Prefabs/Managers/PlayerHUD.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7180ae585f0db8044ba048426f72d995
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -221,12 +221,12 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2071071585578300598}
|
||||
- component: {fileID: 1454372124634854912}
|
||||
- component: {fileID: 4122067414526815177}
|
||||
- component: {fileID: 2314863751758196186}
|
||||
- component: {fileID: 2741639361616064442}
|
||||
- component: {fileID: 4903273501345439385}
|
||||
- component: {fileID: 1054459649399154791}
|
||||
- component: {fileID: 7319925080429004531}
|
||||
m_Layer: 10
|
||||
m_Name: Hidden
|
||||
m_TagString: Untagged
|
||||
@@ -252,18 +252,6 @@ Transform:
|
||||
- {fileID: 852327051512792946}
|
||||
m_Father: {fileID: 8259693476957892150}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1454372124634854912
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1011363502278351410}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: eaefd3d5a2a864ca5b5d9ec5f2a7040f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: PixelplacementAssembly::Pixelplacement.State
|
||||
--- !u!61 &4122067414526815177
|
||||
BoxCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -463,6 +451,18 @@ MonoBehaviour:
|
||||
audioSource: {fileID: 0}
|
||||
clipPriority: 0
|
||||
sourcePriority: 1
|
||||
--- !u!114 &7319925080429004531
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1011363502278351410}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 95e46aacea5b42888ee7881894193c11, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.AppleState
|
||||
--- !u!1 &1674229500073894281
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -777,11 +777,11 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 8259693476957892150}
|
||||
- component: {fileID: 2995561023563842343}
|
||||
- component: {fileID: 7053055077639234121}
|
||||
- component: {fileID: 578146208477020881}
|
||||
- component: {fileID: 1193493154550576580}
|
||||
- component: {fileID: 7652960462502122104}
|
||||
- component: {fileID: 989520896849684110}
|
||||
- component: {fileID: 5862718108034728596}
|
||||
m_Layer: 0
|
||||
m_Name: AnneLiseBaseBush
|
||||
m_TagString: Untagged
|
||||
@@ -818,42 +818,6 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 55938fb1577dd4ad3af7e994048c86f6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: PixelplacementAssembly::Pixelplacement.Initialization
|
||||
--- !u!114 &7053055077639234121
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5943355783477523754}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9e0b24e2f2ad54cc09940c320ed3cf4b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: PixelplacementAssembly::Pixelplacement.StateMachine
|
||||
defaultState: {fileID: 1011363502278351410}
|
||||
currentState: {fileID: 0}
|
||||
_unityEventsFolded: 0
|
||||
verbose: 0
|
||||
allowReentry: 0
|
||||
returnToDefaultOnDisable: 1
|
||||
OnStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnStateEntered:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnFirstStateEntered:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnFirstStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnLastStateEntered:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnLastStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!114 &578146208477020881
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1001,6 +965,43 @@ MonoBehaviour:
|
||||
audioSource: {fileID: 0}
|
||||
clipPriority: 0
|
||||
sourcePriority: 0
|
||||
--- !u!114 &5862718108034728596
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5943355783477523754}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 6f56763d30b94bf6873d395a6c116eb5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.AppleMachine
|
||||
defaultState: {fileID: 1011363502278351410}
|
||||
currentState: {fileID: 0}
|
||||
_unityEventsFolded: 0
|
||||
verbose: 0
|
||||
allowReentry: 0
|
||||
returnToDefaultOnDisable: 1
|
||||
OnStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnStateEntered:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnFirstStateEntered:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnFirstStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnLastStateEntered:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
OnLastStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
--- !u!1 &6948354193133336628
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -11,7 +11,7 @@ GameObject:
|
||||
- component: {fileID: 2326086342663433936}
|
||||
- component: {fileID: 243176356944356711}
|
||||
- component: {fileID: 6657093817085841540}
|
||||
- component: {fileID: 7932498922414502976}
|
||||
- component: {fileID: 2239999147194587249}
|
||||
m_Layer: 0
|
||||
m_Name: BirdEyes
|
||||
m_TagString: Untagged
|
||||
@@ -48,6 +48,8 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 13d59d3c42170824b8f92557822d9bf0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
correctItemIsIn: 0
|
||||
bushAnimator: {fileID: 0}
|
||||
--- !u!114 &6657093817085841540
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -60,7 +62,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 55938fb1577dd4ad3af7e994048c86f6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &7932498922414502976
|
||||
--- !u!114 &2239999147194587249
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -69,9 +71,9 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 1370564349707122423}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9e0b24e2f2ad54cc09940c320ed3cf4b, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 6f56763d30b94bf6873d395a6c116eb5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.AppleMachine
|
||||
defaultState: {fileID: 3532512445619884959}
|
||||
currentState: {fileID: 0}
|
||||
_unityEventsFolded: 0
|
||||
@@ -96,6 +98,7 @@ MonoBehaviour:
|
||||
OnLastStateExited:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
customSaveId:
|
||||
--- !u!1 &3532512445619884959
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -107,7 +110,7 @@ GameObject:
|
||||
- component: {fileID: 4477179922705334961}
|
||||
- component: {fileID: 3013218424693156287}
|
||||
- component: {fileID: 7343439013600968102}
|
||||
- component: {fileID: 3842054004304041864}
|
||||
- component: {fileID: 4451815010323250894}
|
||||
m_Layer: 0
|
||||
m_Name: BirdHiding
|
||||
m_TagString: Untagged
|
||||
@@ -150,6 +153,8 @@ SpriteRenderer:
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
@@ -171,6 +176,7 @@ SpriteRenderer:
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 2
|
||||
@@ -207,7 +213,7 @@ Animator:
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!114 &3842054004304041864
|
||||
--- !u!114 &4451815010323250894
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -216,9 +222,9 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 3532512445619884959}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: eaefd3d5a2a864ca5b5d9ec5f2a7040f, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 95e46aacea5b42888ee7881894193c11, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.AppleState
|
||||
--- !u!1 &8828658103663197825
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -230,7 +236,7 @@ GameObject:
|
||||
- component: {fileID: 7698905571408300091}
|
||||
- component: {fileID: 5210033153524231666}
|
||||
- component: {fileID: 4408373410605328204}
|
||||
- component: {fileID: 3873868413538144635}
|
||||
- component: {fileID: 2709364368411520279}
|
||||
m_Layer: 0
|
||||
m_Name: BirdSpawned
|
||||
m_TagString: Untagged
|
||||
@@ -273,6 +279,8 @@ SpriteRenderer:
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
@@ -294,6 +302,7 @@ SpriteRenderer:
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 2
|
||||
@@ -330,7 +339,7 @@ Animator:
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!114 &3873868413538144635
|
||||
--- !u!114 &2709364368411520279
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -339,6 +348,6 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 8828658103663197825}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: eaefd3d5a2a864ca5b5d9ec5f2a7040f, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 95e46aacea5b42888ee7881894193c11, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.AppleState
|
||||
|
||||
1687
Assets/Prefabs/Puzzles/Picnic.prefab
Normal file
1687
Assets/Prefabs/Puzzles/Picnic.prefab
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Prefabs/Puzzles/Picnic.prefab.meta
Normal file
7
Assets/Prefabs/Puzzles/Picnic.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97f767ded753d524086106f3c39a645f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -135,13 +135,13 @@ AnimatorStateMachine:
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -7925442279578022247}
|
||||
m_Position: {x: 400, y: 370, z: 0}
|
||||
m_Position: {x: 410, y: 370, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -892202757677891130}
|
||||
m_Position: {x: -20, y: 260, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 1937208649765278840}
|
||||
m_Position: {x: 489.1548, y: 156.18289, z: 0}
|
||||
m_Position: {x: 490, y: 150, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions: []
|
||||
|
||||
@@ -120,6 +120,42 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &879012544333199198
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8293076336493130222}
|
||||
m_Layer: 5
|
||||
m_Name: Rainbows
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8293076336493130222
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 879012544333199198}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4136733570236406132}
|
||||
m_Father: {fileID: 1315170081792486277}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &904161782565348054
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -166,7 +202,7 @@ RectTransform:
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 200}
|
||||
m_SizeDelta: {x: 1550, y: 700}
|
||||
m_SizeDelta: {x: 1550, y: 750}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!223 &4291423916360628965
|
||||
Canvas:
|
||||
@@ -252,7 +288,7 @@ MonoBehaviour:
|
||||
m_StartCorner: 0
|
||||
m_StartAxis: 0
|
||||
m_CellSize: {x: 350, y: 350}
|
||||
m_Spacing: {x: 50, y: 0}
|
||||
m_Spacing: {x: 50, y: 50}
|
||||
m_Constraint: 2
|
||||
m_ConstraintCount: 2
|
||||
--- !u!114 &7425566603516801919
|
||||
@@ -279,10 +315,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1315170081792486277}
|
||||
- component: {fileID: 6669614972729775195}
|
||||
- component: {fileID: 1702317823502492223}
|
||||
- component: {fileID: 2981106092574900430}
|
||||
- component: {fileID: 8074691980395114238}
|
||||
- component: {fileID: 1630362919770549177}
|
||||
m_Layer: 5
|
||||
m_Name: AppSwitcher
|
||||
m_TagString: Untagged
|
||||
@@ -302,8 +336,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 6108475066390421500}
|
||||
- {fileID: 1495118611075801417}
|
||||
- {fileID: 8293076336493130222}
|
||||
- {fileID: 808554455652734252}
|
||||
- {fileID: 2831878373711017175}
|
||||
m_Father: {fileID: 0}
|
||||
@@ -336,29 +369,6 @@ Canvas:
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!114 &1702317823502492223
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1498581815400593087}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.CanvasScaler
|
||||
m_UiScaleMode: 0
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 800, y: 600}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 1
|
||||
--- !u!114 &2981106092574900430
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -388,36 +398,14 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: bac6124b3ada8a048a0b87a729a22312, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: '::'
|
||||
iconIdle: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
|
||||
iconEstablish: {fileID: 4900000, guid: 975218623da47f8428c484d886554a6c, type: 3}
|
||||
rainbowEstablish: {fileID: 4900000, guid: 622be2ef9d5e27d45a9deaf7ed805f5f, type: 3}
|
||||
rainbowRemove: {fileID: 4900000, guid: 589505308c5daf449800f30dd4b92ce7, type: 3}
|
||||
rainbow: {fileID: 5382650426034128680}
|
||||
icon: {fileID: 6784053660381911346}
|
||||
PageName:
|
||||
transitionDuration: 0.3
|
||||
rainbowIn: {fileID: 0}
|
||||
rainbowOut: {fileID: 0}
|
||||
gameLayoutContainer: {fileID: 904161782565348054}
|
||||
exitButton: {fileID: 8427602740714176801}
|
||||
--- !u!95 &1630362919770549177
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1498581815400593087}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: fc380d833ededb441a23b106de60bedd, type: 2}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 2
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_AnimatePhysics: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
rectMask: {fileID: 7425566603516801919}
|
||||
slideDuration: 0.6
|
||||
--- !u!1 &2426870979657684456
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -658,6 +646,81 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &4404111907760364827
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4136733570236406132}
|
||||
- component: {fileID: 102352512179716898}
|
||||
- component: {fileID: 3911817807614671446}
|
||||
m_Layer: 5
|
||||
m_Name: BackgroundOverlay
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4136733570236406132
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4404111907760364827}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 8293076336493130222}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &102352512179716898
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4404111907760364827}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &3911817807614671446
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4404111907760364827}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 0.5019608}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &5189738780074141096
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -778,99 +841,6 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &5382650426034128680
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6108475066390421500}
|
||||
- component: {fileID: 2398693306920598044}
|
||||
- component: {fileID: 7920249735731934357}
|
||||
- component: {fileID: 3566391948883171773}
|
||||
m_Layer: 5
|
||||
m_Name: Rainbow
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6108475066390421500
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5382650426034128680}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1315170081792486277}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2398693306920598044
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5382650426034128680}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &7920249735731934357
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5382650426034128680}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Texture: {fileID: 0}
|
||||
m_UVRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: -1
|
||||
--- !u!114 &3566391948883171773
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5382650426034128680}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
|
||||
lottieFile: {fileID: 4900000, guid: 622be2ef9d5e27d45a9deaf7ed805f5f, type: 3}
|
||||
customResolution: 0
|
||||
resWidth: 250
|
||||
resHeight: 250
|
||||
stateName:
|
||||
resetAfterFinished: 0
|
||||
autoPlay: 0
|
||||
loop: 0
|
||||
--- !u!1 &5867455130109727138
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -991,156 +961,6 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &6784053660381911346
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1495118611075801417}
|
||||
- component: {fileID: 9118909078554628244}
|
||||
- component: {fileID: 8490254979303535795}
|
||||
- component: {fileID: 4316986085632541161}
|
||||
- component: {fileID: 6597789131808754055}
|
||||
m_Layer: 5
|
||||
m_Name: Icon
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1495118611075801417
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6784053660381911346}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1315170081792486277}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -50, y: -50}
|
||||
m_SizeDelta: {x: 200, y: 200}
|
||||
m_Pivot: {x: 1, y: 1}
|
||||
--- !u!222 &9118909078554628244
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6784053660381911346}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8490254979303535795
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6784053660381911346}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Texture: {fileID: 0}
|
||||
m_UVRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: -1
|
||||
--- !u!114 &4316986085632541161
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6784053660381911346}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
|
||||
lottieFile: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
|
||||
customResolution: 0
|
||||
resWidth: 250
|
||||
resHeight: 250
|
||||
stateName: Idle
|
||||
resetAfterFinished: 0
|
||||
autoPlay: 1
|
||||
loop: 1
|
||||
--- !u!114 &6597789131808754055
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6784053660381911346}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 8490254979303535795}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 8074691980395114238}
|
||||
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
|
||||
m_MethodName: OpenAppSwitcher
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!1 &7713997083397969887
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1513,6 +1333,7 @@ GameObject:
|
||||
- component: {fileID: 5972191288640444065}
|
||||
- component: {fileID: 236099612463072939}
|
||||
- component: {fileID: 447310668687539451}
|
||||
- component: {fileID: 6704345904811573523}
|
||||
m_Layer: 5
|
||||
m_Name: CloseUIButton
|
||||
m_TagString: Untagged
|
||||
@@ -1623,7 +1444,7 @@ MonoBehaviour:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 8074691980395114238}
|
||||
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
|
||||
m_MethodName: CloseAppSwitcher
|
||||
m_MethodName: OnBackPressed
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
@@ -1633,3 +1454,15 @@ MonoBehaviour:
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!114 &6704345904811573523
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8427602740714176801}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,9 @@ RectTransform:
|
||||
- {fileID: 5027301639700053608}
|
||||
- {fileID: 2081116343754364062}
|
||||
- {fileID: 4830022034953347571}
|
||||
- {fileID: 4247146273316450423}
|
||||
- {fileID: 7968396929263690413}
|
||||
- {fileID: 1477338421424306197}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
@@ -79,7 +81,7 @@ MonoBehaviour:
|
||||
boosterDisappearDuration: 0.5
|
||||
impulseSource: {fileID: 4448843358972162772}
|
||||
openingParticleSystem: {fileID: 0}
|
||||
albumIcon: {fileID: 0}
|
||||
albumIcon: {fileID: 2290549912955623947}
|
||||
--- !u!114 &4448843358972162772
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -214,6 +216,170 @@ MonoBehaviour:
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
curveHeight: 50
|
||||
--- !u!1 &2290549912955623947
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4247146273316450423}
|
||||
- component: {fileID: 5793188825053435727}
|
||||
- component: {fileID: 5726314423424208945}
|
||||
- component: {fileID: 299670167085314888}
|
||||
- component: {fileID: 6513785969721658917}
|
||||
m_Layer: 5
|
||||
m_Name: ScrapbookButton
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4247146273316450423
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2290549912955623947}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1.06667, y: 1.06667, z: 1.06667}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5228380266581535650}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 80.000015, y: 79.999985}
|
||||
m_SizeDelta: {x: 241, y: 239}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!222 &5793188825053435727
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2290549912955623947}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &5726314423424208945
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2290549912955623947}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -4354454609415314374, guid: 1ba1f8cf73f79214190f1432fe1e3bc6, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &299670167085314888
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2290549912955623947}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 5726314423424208945}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!114 &6513785969721658917
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2290549912955623947}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput
|
||||
--- !u!1 &2898816812112041854
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1477338421424306197}
|
||||
m_Layer: 0
|
||||
m_Name: GameObject (1)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1477338421424306197
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2898816812112041854}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -297.3595, y: -196.74738, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5228380266581535650}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &4303341275909682426
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -0,0 +1,483 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1439929750438628637
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1966378914653314124}
|
||||
- component: {fileID: 1175208421330333144}
|
||||
m_Layer: 0
|
||||
m_Name: MiniGameBoosterGiver
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1966378914653314124
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1439929750438628637}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 2499229096808986326}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1175208421330333144
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1439929750438628637}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7d8f3e9a2b4c5f6d1a8e9c0b3d4f5a6b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.MinigameBoosterGiver
|
||||
visualContainer: {fileID: 8617171489468030463}
|
||||
boosterImage: {fileID: 3680365639323743419}
|
||||
glowImage: {fileID: 4006246129058447062}
|
||||
continueButton: {fileID: 2988510625873934392}
|
||||
hoverAmount: 20
|
||||
hoverDuration: 1.5
|
||||
glowPulseMin: 0.9
|
||||
glowPulseMax: 1.1
|
||||
glowPulseDuration: 1.2
|
||||
targetBottomLeftOffset: {x: 100, y: 100}
|
||||
disappearDuration: 0.8
|
||||
disappearScale: 0.2
|
||||
--- !u!1 &2923535299741790846
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5109945643968698326}
|
||||
m_Layer: 0
|
||||
m_Name: BoosterContainer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5109945643968698326
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2923535299741790846}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4006246129058447062}
|
||||
- {fileID: 3680365639323743419}
|
||||
m_Father: {fileID: 2499229096808986326}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -300}
|
||||
m_SizeDelta: {x: 750, y: 760}
|
||||
m_Pivot: {x: 0.5, y: 1}
|
||||
--- !u!1 &4323719263405703996
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6841858894429745291}
|
||||
- component: {fileID: 1590188508543769496}
|
||||
- component: {fileID: 4489841151491567959}
|
||||
- component: {fileID: 2988510625873934392}
|
||||
m_Layer: 0
|
||||
m_Name: Button
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6841858894429745291
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4323719263405703996}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2499229096808986326}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0}
|
||||
m_AnchorMax: {x: 0.5, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 160}
|
||||
m_SizeDelta: {x: 250, y: 250}
|
||||
m_Pivot: {x: 0.5, y: 0}
|
||||
--- !u!222 &1590188508543769496
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4323719263405703996}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4489841151491567959
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4323719263405703996}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 2636902231072113825, guid: ee014bd71cac2bc4ab845f435726f383, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &2988510625873934392
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4323719263405703996}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 4489841151491567959}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &5931931042366245593
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4006246129058447062}
|
||||
- component: {fileID: 5796229481733252802}
|
||||
- component: {fileID: 6215049078676414306}
|
||||
m_Layer: 0
|
||||
m_Name: Glow
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4006246129058447062
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5931931042366245593}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5109945643968698326}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 800, y: 800}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5796229481733252802
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5931931042366245593}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &6215049078676414306
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5931931042366245593}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -8836962644236845764, guid: c5cc7367a37a7944abb3876352b0e0ff, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &8617171489468030463
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2499229096808986326}
|
||||
m_Layer: 0
|
||||
m_Name: VisualContainer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2499229096808986326
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8617171489468030463}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1338508664922812659}
|
||||
- {fileID: 6841858894429745291}
|
||||
- {fileID: 5109945643968698326}
|
||||
m_Father: {fileID: 1966378914653314124}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &8914844459546715980
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1338508664922812659}
|
||||
- component: {fileID: 4173866009683612467}
|
||||
- component: {fileID: 570826085774513514}
|
||||
m_Layer: 0
|
||||
m_Name: Background
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1338508664922812659
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8914844459546715980}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2499229096808986326}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4173866009683612467
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8914844459546715980}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &570826085774513514
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8914844459546715980}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 0.49411765}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &9035675646436554328
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3680365639323743419}
|
||||
- component: {fileID: 8906420622179058179}
|
||||
- component: {fileID: 3765065913677958559}
|
||||
m_Layer: 0
|
||||
m_Name: BoosterPack
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3680365639323743419
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9035675646436554328}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5109945643968698326}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 411, y: 729}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8906420622179058179
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9035675646436554328}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &3765065913677958559
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9035675646436554328}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 4365544765984126881, guid: 9dac643e78ad86e4988c11a92f9c7a6d, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a855ba60e86bf1e449197f1f5f9b9b73
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -285,8 +285,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 173}
|
||||
m_SizeDelta: {x: 600, y: 150}
|
||||
m_AnchoredPosition: {x: 0, y: 125}
|
||||
m_SizeDelta: {x: 600, y: 120}
|
||||
m_Pivot: {x: 0.5, y: 1}
|
||||
--- !u!222 &5545241165728741220
|
||||
CanvasRenderer:
|
||||
@@ -343,8 +343,8 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 150
|
||||
m_fontSizeBase: 150
|
||||
m_fontSize: 125
|
||||
m_fontSizeBase: 125
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
@@ -1053,6 +1053,10 @@ PrefabInstance:
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4925415087786595420, guid: 1d8cc8d9238eec34b8e600e7050e2979, type: 3}
|
||||
propertyPath: m_fontSize
|
||||
value: 54.45
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5378230129755544441, guid: 1d8cc8d9238eec34b8e600e7050e2979, type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
138
Assets/Prefabs/UI/IntroSequence.prefab
Normal file
138
Assets/Prefabs/UI/IntroSequence.prefab
Normal file
@@ -0,0 +1,138 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &5026598641267297246
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 499805009927302532}
|
||||
- component: {fileID: 8952193833593986238}
|
||||
- component: {fileID: 1768742023768591015}
|
||||
- component: {fileID: 4794855098771415437}
|
||||
- component: {fileID: 1827255458430098390}
|
||||
- component: {fileID: 1619383145738161903}
|
||||
m_Layer: 5
|
||||
m_Name: IntroSequence
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &499805009927302532
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5026598641267297246}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 1920, y: 1080}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &8952193833593986238
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5026598641267297246}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c119ffb87b2a16d4f925ff5d5ffd7092, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
shouldPlayIntro: 0
|
||||
--- !u!222 &1768742023768591015
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5026598641267297246}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4794855098771415437
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5026598641267297246}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!320 &1827255458430098390
|
||||
PlayableDirector:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5026598641267297246}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_PlayableAsset: {fileID: 11400000, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
m_InitialState: 0
|
||||
m_WrapMode: 2
|
||||
m_DirectorUpdateMode: 1
|
||||
m_InitialTime: 0
|
||||
m_SceneBindings:
|
||||
- key: {fileID: -38993752814118673, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
value: {fileID: 1619383145738161903}
|
||||
- key: {fileID: -8222318252314758605, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
value: {fileID: 0}
|
||||
- key: {fileID: 139419469794405637, guid: bf4679c9d0eb0994d9e0de37c045e99b, type: 2}
|
||||
value: {fileID: 0}
|
||||
m_ExposedReferences:
|
||||
m_References: []
|
||||
--- !u!95 &1619383145738161903
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5026598641267297246}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: 052a4fbd53390314ba2bb3878a81b01e, type: 2}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_AnimatePhysics: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
7
Assets/Prefabs/UI/IntroSequence.prefab.meta
Normal file
7
Assets/Prefabs/UI/IntroSequence.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1074dd38c3c50f4ca1454dbd60e44f6
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fb0d7fc6faad154b8c3e3cb7abb7c15
|
||||
guid: fe049e0d73eadd7479140c8e7bd10efe
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,50 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3863019143023165617
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 272997100784137721}
|
||||
- component: {fileID: 497632815361153787}
|
||||
m_Layer: 5
|
||||
m_Name: UIPageController
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &272997100784137721
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3863019143023165617}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &497632815361153787
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3863019143023165617}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b1ae6c1745e44e22a0fa9209ebe45ee3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::UI.Core.UIPageController
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -305,6 +305,7 @@ RectTransform:
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1224833349}
|
||||
- {fileID: 471921060}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
@@ -418,16 +419,16 @@ LineRenderer:
|
||||
m_SortingOrder: 0
|
||||
m_Positions:
|
||||
- {x: -0.15602553, y: 4.074945, z: 0}
|
||||
- {x: -0.1566351, y: 3.9736383, z: 0}
|
||||
- {x: -0.1572447, y: 3.8729858, z: 0}
|
||||
- {x: -0.1566351, y: 3.973638, z: 0}
|
||||
- {x: -0.1572447, y: 3.8729856, z: 0}
|
||||
- {x: -0.15785426, y: 3.7729874, z: 0}
|
||||
- {x: -0.15846384, y: 3.673644, z: 0}
|
||||
- {x: -0.15907341, y: 3.5749543, z: 0}
|
||||
- {x: -0.15968299, y: 3.4769197, z: 0}
|
||||
- {x: -0.15846384, y: 3.6736436, z: 0}
|
||||
- {x: -0.15907341, y: 3.574954, z: 0}
|
||||
- {x: -0.15968299, y: 3.4769192, z: 0}
|
||||
- {x: -0.16029257, y: 3.3795385, z: 0}
|
||||
- {x: -0.16090216, y: 3.2828126, z: 0}
|
||||
- {x: -0.16151173, y: 3.1867406, z: 0}
|
||||
- {x: -0.16212131, y: 3.0913231, z: 0}
|
||||
- {x: -0.16151173, y: 3.1867409, z: 0}
|
||||
- {x: -0.16212131, y: 3.0913236, z: 0}
|
||||
m_Parameters:
|
||||
serializedVersion: 3
|
||||
widthMultiplier: 1
|
||||
@@ -1098,6 +1099,112 @@ Animator:
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!1001 &471921059
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 116234201}
|
||||
m_Modifications:
|
||||
- target: {fileID: 1439929750438628637, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MiniGameBoosterGiver
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_AnchorMin.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8617171489468030463, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
--- !u!224 &471921060 stripped
|
||||
RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 1966378914653314124, guid: a855ba60e86bf1e449197f1f5f9b9b73, type: 3}
|
||||
m_PrefabInstance: {fileID: 471921059}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &730962732
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1455,7 +1562,7 @@ AudioSource:
|
||||
OutputAudioMixerGroup: {fileID: 3533147658878909314, guid: 727a7e4b6df4b0d47897f7d8ee7fa323, type: 2}
|
||||
m_audioClip: {fileID: 0}
|
||||
m_Resource: {fileID: 0}
|
||||
m_PlayOnAwake: 1
|
||||
m_PlayOnAwake: 0
|
||||
m_Volume: 1
|
||||
m_Pitch: 1
|
||||
Loop: 0
|
||||
@@ -1783,14 +1890,14 @@ LineRenderer:
|
||||
- {x: -0.15602553, y: 4.0749445, z: 0}
|
||||
- {x: -0.11662118, y: 3.879622, z: 0}
|
||||
- {x: -0.07721684, y: 3.7057445, z: 0}
|
||||
- {x: -0.03781248, y: 3.5533104, z: 0}
|
||||
- {x: 0.0015918687, y: 3.4223213, z: 0}
|
||||
- {x: 0.040996216, y: 3.312776, z: 0}
|
||||
- {x: 0.08040057, y: 3.2246757, z: 0}
|
||||
- {x: 0.11980491, y: 3.1580195, z: 0}
|
||||
- {x: 0.15920927, y: 3.1128078, z: 0}
|
||||
- {x: 0.1986136, y: 3.0890403, z: 0}
|
||||
- {x: 0.23801796, y: 3.0867171, z: 0}
|
||||
- {x: -0.03781248, y: 3.5533106, z: 0}
|
||||
- {x: 0.0015918687, y: 3.4223216, z: 0}
|
||||
- {x: 0.040996216, y: 3.3127766, z: 0}
|
||||
- {x: 0.08040057, y: 3.2246761, z: 0}
|
||||
- {x: 0.11980491, y: 3.15802, z: 0}
|
||||
- {x: 0.15920927, y: 3.1128082, z: 0}
|
||||
- {x: 0.1986136, y: 3.0890405, z: 0}
|
||||
- {x: 0.23801796, y: 3.0867176, z: 0}
|
||||
m_Parameters:
|
||||
serializedVersion: 3
|
||||
widthMultiplier: 1
|
||||
@@ -2503,14 +2610,14 @@ LineRenderer:
|
||||
- {x: -0.15602553, y: 4.0749445, z: 0}
|
||||
- {x: -0.18956745, y: 3.8764973, z: 0}
|
||||
- {x: -0.22310936, y: 3.7000232, z: 0}
|
||||
- {x: -0.25665125, y: 3.54552, z: 0}
|
||||
- {x: -0.29019317, y: 3.4129906, z: 0}
|
||||
- {x: -0.32373506, y: 3.302433, z: 0}
|
||||
- {x: -0.35727698, y: 3.213848, z: 0}
|
||||
- {x: -0.39081886, y: 3.1472354, z: 0}
|
||||
- {x: -0.4243608, y: 3.1025953, z: 0}
|
||||
- {x: -0.45790267, y: 3.0799277, z: 0}
|
||||
- {x: -0.4914446, y: 3.0792325, z: 0}
|
||||
- {x: -0.25665125, y: 3.5455203, z: 0}
|
||||
- {x: -0.29019317, y: 3.412991, z: 0}
|
||||
- {x: -0.32373506, y: 3.3024335, z: 0}
|
||||
- {x: -0.35727698, y: 3.2138484, z: 0}
|
||||
- {x: -0.39081886, y: 3.1472359, z: 0}
|
||||
- {x: -0.4243608, y: 3.1025958, z: 0}
|
||||
- {x: -0.45790267, y: 3.0799282, z: 0}
|
||||
- {x: -0.4914446, y: 3.079233, z: 0}
|
||||
m_Parameters:
|
||||
serializedVersion: 3
|
||||
widthMultiplier: 1
|
||||
@@ -3358,7 +3465,7 @@ Transform:
|
||||
m_GameObject: {fileID: 2106431001}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -0.165, y: 2.697517, z: 0}
|
||||
m_LocalPosition: {x: -0.165, y: 2.6975174, z: 0}
|
||||
m_LocalScale: {x: 0.57574, y: 0.57574, z: 0.57574}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
@@ -3526,6 +3633,18 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Tutorial
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4267886887244421663, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||
propertyPath: introVO
|
||||
value:
|
||||
objectReference: {fileID: 8300000, guid: fca641cdc8dcd074483fad3db1cbe24c, type: 3}
|
||||
- target: {fileID: 4267886887244421663, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||
propertyPath: playTutorial
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4267886887244421663, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||
propertyPath: bottleAudioPlayer
|
||||
value:
|
||||
objectReference: {fileID: 747976408}
|
||||
- target: {fileID: 8452897808363562605, guid: a4dd78ff48942854ebb4c65025a8dc36, type: 3}
|
||||
propertyPath: m_Sprite
|
||||
value:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,82 @@
|
||||
using Core.Lifecycle;
|
||||
using Core.SaveLoad;
|
||||
using UnityEngine;
|
||||
using Pixelplacement;
|
||||
|
||||
public class BirdEyesBehavior : MonoBehaviour
|
||||
public class BirdEyesBehavior : ManagedBehaviour
|
||||
{
|
||||
private StateMachine statemachine;
|
||||
private Animator animator;
|
||||
// Animator Hashes
|
||||
private static readonly int RightGuess = Animator.StringToHash("RightGuess");
|
||||
private static readonly int WrongGuess = Animator.StringToHash("WrongGuess");
|
||||
private static readonly int NoGuess = Animator.StringToHash("NoGuess");
|
||||
private static readonly int Wolterisout = Animator.StringToHash("wolterisout");
|
||||
|
||||
private AppleMachine _statemachine;
|
||||
private Animator _animator;
|
||||
public bool correctItemIsIn;
|
||||
[SerializeField] private Animator bushAnimator; // Assign in Inspector
|
||||
|
||||
// Save state
|
||||
private bool _wolterisoutTriggered;
|
||||
|
||||
// Enable save/load participation
|
||||
public override bool AutoRegisterForSave => true;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
statemachine = GetComponent<StateMachine>();
|
||||
animator = GetComponentInChildren<Animator>();
|
||||
_statemachine = GetComponent<AppleMachine>();
|
||||
_animator = GetComponentInChildren<Animator>();
|
||||
}
|
||||
|
||||
public void CorrectItem()
|
||||
{
|
||||
correctItemIsIn = true;
|
||||
animator.SetTrigger("RightGuess");
|
||||
_animator.SetTrigger(RightGuess);
|
||||
BirdReveal();
|
||||
}
|
||||
|
||||
public void IncorrectItem()
|
||||
{
|
||||
correctItemIsIn = false;
|
||||
animator.SetTrigger("WrongGuess");
|
||||
_animator.SetTrigger(WrongGuess);
|
||||
}
|
||||
|
||||
public void NoItem()
|
||||
{
|
||||
animator.SetTrigger("NoGuess");
|
||||
_animator.SetTrigger(NoGuess);
|
||||
}
|
||||
|
||||
public void BirdReveal()
|
||||
{
|
||||
if (bushAnimator != null)
|
||||
{
|
||||
bushAnimator.SetTrigger("wolterisout");
|
||||
statemachine.ChangeState("BirdSpawned");
|
||||
return;
|
||||
bushAnimator.SetTrigger(Wolterisout);
|
||||
_wolterisoutTriggered = true;
|
||||
}
|
||||
statemachine.ChangeState ("BirdSpawned");
|
||||
_statemachine.ChangeState("BirdSpawned");
|
||||
}
|
||||
|
||||
protected override void OnSceneRestoreRequested(string serializedData)
|
||||
{
|
||||
base.OnSceneRestoreRequested(serializedData);
|
||||
|
||||
if (!string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
if (bool.TryParse(serializedData, out bool wasTriggered))
|
||||
{
|
||||
_wolterisoutTriggered = wasTriggered;
|
||||
|
||||
// If it was triggered before, set it again on restore
|
||||
if (_wolterisoutTriggered && bushAnimator != null)
|
||||
{
|
||||
bushAnimator.SetTrigger(Wolterisout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override string OnSceneSaveRequested()
|
||||
{
|
||||
return _wolterisoutTriggered.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
"OptimizedRope",
|
||||
"AudioSourceEvents",
|
||||
"NewAssembly",
|
||||
"SkiaSharp.Unity",
|
||||
"SkiaSharp.Editor",
|
||||
"SkiaSharp",
|
||||
"Unity.Cinemachine"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AppleHills.Core.Settings;
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Bootstrap
|
||||
{
|
||||
/// <summary>
|
||||
/// Service that provides notification and management of boot completion status.
|
||||
/// Allows systems to subscribe to boot completion events, register initialization actions with priorities,
|
||||
/// or await boot completion asynchronously.
|
||||
/// </summary>
|
||||
public static class BootCompletionService
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates if the boot process has completed
|
||||
/// </summary>
|
||||
public static bool IsBootComplete { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when boot completes
|
||||
/// </summary>
|
||||
public static event Action OnBootComplete;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an initialization action with priority
|
||||
/// </summary>
|
||||
private class InitializationAction
|
||||
{
|
||||
public Action Action { get; }
|
||||
public int Priority { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public InitializationAction(Action action, int priority, string name)
|
||||
{
|
||||
Action = action;
|
||||
Priority = priority;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
// List of initialization actions to be executed once boot completes
|
||||
private static List<InitializationAction> _initializationActions = new List<InitializationAction>();
|
||||
|
||||
// TaskCompletionSource for async await pattern
|
||||
private static TaskCompletionSource<bool> _bootCompletionTask = new TaskCompletionSource<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Called by CustomBoot when the boot process is complete
|
||||
/// </summary>
|
||||
internal static void HandleBootCompleted()
|
||||
{
|
||||
if (IsBootComplete)
|
||||
return;
|
||||
|
||||
IsBootComplete = true;
|
||||
|
||||
LogDebugMessage("Boot process completed, executing initialization actions");
|
||||
|
||||
// Execute initialization actions in priority order (lower number = higher priority)
|
||||
ExecuteInitializationActions();
|
||||
|
||||
// Trigger the event
|
||||
OnBootComplete?.Invoke();
|
||||
|
||||
// Complete the task for async waiters
|
||||
_bootCompletionTask.TrySetResult(true);
|
||||
|
||||
LogDebugMessage("All boot completion handlers executed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an action to be executed when boot completes.
|
||||
/// Lower priority numbers run first.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute</param>
|
||||
/// <param name="priority">Priority (lower numbers run first)</param>
|
||||
/// <param name="name">Name for debugging</param>
|
||||
public static void RegisterInitAction(Action action, int priority = 100, string name = null)
|
||||
{
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = $"Action_{_initializationActions.Count}";
|
||||
|
||||
var initAction = new InitializationAction(action, priority, name);
|
||||
|
||||
if (IsBootComplete)
|
||||
{
|
||||
// If boot is already complete, execute immediately
|
||||
LogDebugMessage($"Executing late registration: {name} (Priority: {priority})");
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebugMessage($"Error executing init action '{name}': {ex}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise add to the queue
|
||||
_initializationActions.Add(initAction);
|
||||
LogDebugMessage($"Registered init action: {name} (Priority: {priority})");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait asynchronously for boot completion
|
||||
/// </summary>
|
||||
/// <returns>Task that completes when boot is complete</returns>
|
||||
public static Task WaitForBootCompletionAsync()
|
||||
{
|
||||
if (IsBootComplete)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return _bootCompletionTask.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute all registered initialization actions in priority order
|
||||
/// </summary>
|
||||
private static void ExecuteInitializationActions()
|
||||
{
|
||||
// Sort by priority (lowest first)
|
||||
var sortedActions = _initializationActions
|
||||
.OrderBy(a => a.Priority)
|
||||
.ToList();
|
||||
|
||||
foreach (var action in sortedActions)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogDebugMessage($"Executing: {action.Name} (Priority: {action.Priority})");
|
||||
action.Action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebugMessage($"Error executing init action '{action.Name}': {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the list after execution
|
||||
_initializationActions.Clear();
|
||||
}
|
||||
|
||||
private static void LogDebugMessage(string message)
|
||||
{
|
||||
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity <=
|
||||
LogVerbosity.Debug)
|
||||
{
|
||||
Logging.Debug($"[BootCompletionService] {message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa0228cf33a64515bc166b7a9bc8c0b9
|
||||
timeCreated: 1760606319
|
||||
@@ -1,18 +1,18 @@
|
||||
using System;
|
||||
using System;
|
||||
using AppleHills.Core.Settings;
|
||||
using UnityEngine;
|
||||
using UI;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Cinematics;
|
||||
using UnityEngine.Serialization;
|
||||
using Core.SaveLoad;
|
||||
|
||||
namespace Bootstrap
|
||||
{
|
||||
/// <summary>
|
||||
/// Controller for the boot scene that coordinates bootstrap initialization with loading screen
|
||||
/// </summary>
|
||||
public class BootSceneController : MonoBehaviour
|
||||
public class BootSceneController : ManagedBehaviour
|
||||
{
|
||||
[SerializeField] private string mainSceneName = "AppleHillsOverworld";
|
||||
[SerializeField] private float minDelayAfterBoot = 0.5f; // Small delay after boot to ensure smooth transition
|
||||
@@ -30,36 +30,39 @@ namespace Bootstrap
|
||||
private float _sceneLoadingProgress = 0f;
|
||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||
|
||||
private void Start()
|
||||
// Run very early - need to set up loading screen before other systems initialize
|
||||
public override int ManagedAwakePriority => 5;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
LogDebugMessage("Boot scene started");
|
||||
base.Awake(); // Register with LifecycleManager
|
||||
|
||||
// Ensure the initial loading screen exists
|
||||
LogDebugMessage("BootSceneController.Awake() - Initializing loading screen DURING bootstrap");
|
||||
|
||||
// Validate loading screen exists
|
||||
if (initialLoadingScreen == null)
|
||||
{
|
||||
Debug.LogError("[BootSceneController] No InitialLoadingScreen assigned! Please assign it in the inspector.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Subscribe to the loading screen completion event
|
||||
initialLoadingScreen.OnLoadingScreenFullyHidden += OnInitialLoadingComplete;
|
||||
|
||||
// Show the loading screen immediately with our combined progress provider
|
||||
// This needs to happen DURING bootstrap to show progress
|
||||
initialLoadingScreen.ShowLoadingScreen(GetCombinedProgress);
|
||||
|
||||
// Subscribe to boot progress events
|
||||
// Subscribe to loading screen completion event
|
||||
initialLoadingScreen.OnLoadingScreenFullyHidden += OnInitialLoadingComplete;
|
||||
|
||||
// Subscribe to boot progress for real-time updates during bootstrap
|
||||
CustomBoot.OnBootProgressChanged += OnBootProgressChanged;
|
||||
|
||||
// Register our boot completion handler with the BootCompletionService
|
||||
// This will execute either immediately if boot is already complete,
|
||||
// or when the boot process completes
|
||||
BootCompletionService.RegisterInitAction(
|
||||
OnBootCompleted,
|
||||
50, // Higher priority (lower number)
|
||||
"BootSceneController.OnBootCompleted"
|
||||
);
|
||||
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity;
|
||||
#if UNITY_EDITOR
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().bootstrapLogVerbosity;
|
||||
#elif DEVELOPMENT_BUILD
|
||||
_logVerbosity = LogVerbosity.Debug;
|
||||
#elif RELEASE_BUILD
|
||||
_logVerbosity = LogVerbosity.Warning;
|
||||
#endif
|
||||
|
||||
// In debug mode, log additional information
|
||||
if (debugMode)
|
||||
@@ -67,6 +70,32 @@ namespace Bootstrap
|
||||
InvokeRepeating(nameof(LogDebugInfo), 0.1f, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
LogDebugMessage("BootSceneController.OnManagedAwake() - Boot is GUARANTEED complete, starting scene loading");
|
||||
|
||||
// Boot is GUARANTEED complete at this point - that's the whole point of OnManagedAwake!
|
||||
// No need to subscribe to OnBootCompleted or check CustomBoot.Initialised
|
||||
_bootComplete = true;
|
||||
_currentPhase = LoadingPhase.SceneLoading;
|
||||
|
||||
// Start loading the main scene after a small delay
|
||||
// This prevents jerky transitions if boot happens very quickly
|
||||
Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
|
||||
// Manual cleanup for events
|
||||
if (initialLoadingScreen != null)
|
||||
{
|
||||
initialLoadingScreen.OnLoadingScreenFullyHidden -= OnInitialLoadingComplete;
|
||||
}
|
||||
CustomBoot.OnBootProgressChanged -= OnBootProgressChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the initial loading screen is fully hidden
|
||||
@@ -79,10 +108,12 @@ namespace Bootstrap
|
||||
if (CinematicsManager.Instance != null)
|
||||
{
|
||||
LogDebugMessage("Attempting to play intro cinematic");
|
||||
|
||||
|
||||
// Use LoadAndPlayCinematic to play the intro sequence
|
||||
CinematicsManager.Instance.LoadAndPlayCinematic("IntroSequence");
|
||||
|
||||
CinematicsManager.Instance.LoadAndPlayCinematic("IntroSequence", false);
|
||||
CinematicsManager.Instance.ChangeCinematicBackgroundColour(new Color(0f, 0f, 0f, 1f));
|
||||
//PlayerHudManager.Instance.ResizeCinematicPlayer();
|
||||
|
||||
// Immediately unload the StartingScene - no need to wait for cinematic to finish
|
||||
// since CinematicsManager is bootstrapped and won't be unloaded
|
||||
UnloadStartingScene();
|
||||
@@ -94,23 +125,6 @@ namespace Bootstrap
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// Clean up event subscriptions
|
||||
CustomBoot.OnBootCompleted -= OnBootCompleted;
|
||||
CustomBoot.OnBootProgressChanged -= OnBootProgressChanged;
|
||||
|
||||
if (initialLoadingScreen != null)
|
||||
{
|
||||
initialLoadingScreen.OnLoadingScreenFullyHidden -= OnInitialLoadingComplete;
|
||||
}
|
||||
|
||||
if (debugMode)
|
||||
{
|
||||
CancelInvoke(nameof(LogDebugInfo));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Progress provider that combines bootstrap and scene loading progress
|
||||
/// </summary>
|
||||
@@ -145,19 +159,7 @@ namespace Bootstrap
|
||||
$"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}");
|
||||
}
|
||||
|
||||
private void OnBootCompleted()
|
||||
{
|
||||
// Unsubscribe to prevent duplicate calls
|
||||
CustomBoot.OnBootCompleted -= OnBootCompleted;
|
||||
|
||||
LogDebugMessage("Boot process completed");
|
||||
_bootComplete = true;
|
||||
|
||||
// After a small delay, start loading the main menu
|
||||
// This prevents jerky transitions if boot happens very quickly
|
||||
Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot);
|
||||
}
|
||||
|
||||
|
||||
private void StartLoadingMainMenu()
|
||||
{
|
||||
if (_hasStartedLoading)
|
||||
@@ -207,6 +209,17 @@ namespace Bootstrap
|
||||
// Ensure progress is complete
|
||||
_sceneLoadingProgress = 1f;
|
||||
|
||||
// CRITICAL: Broadcast lifecycle events so components get their OnSceneReady callbacks
|
||||
LogDebugMessage($"Broadcasting OnSceneReady for: {mainSceneName}");
|
||||
LifecycleManager.Instance?.BroadcastSceneReady(mainSceneName);
|
||||
|
||||
// Restore scene data for the main menu
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
LogDebugMessage($"Restoring scene data for: {mainSceneName}");
|
||||
SaveLoadManager.Instance.RestoreSceneData();
|
||||
}
|
||||
|
||||
// Step 2: Scene is fully loaded, now hide the loading screen
|
||||
// This will trigger OnInitialLoadingComplete via the event when animation completes
|
||||
initialLoadingScreen.HideLoadingScreen();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using AppleHills.Core.Settings;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
@@ -39,6 +40,10 @@ namespace Bootstrap
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
|
||||
private static void Initialise()
|
||||
{
|
||||
// Create LifecycleManager FIRST - before any bootstrap logic
|
||||
// This ensures it exists when boot completes
|
||||
LifecycleManager.CreateInstance();
|
||||
|
||||
//We should always clean up after Addressables, so let's take care of that immediately
|
||||
Application.quitting += ApplicationOnUnloading;
|
||||
|
||||
@@ -97,12 +102,14 @@ namespace Bootstrap
|
||||
OnBootProgressChanged?.Invoke(1f);
|
||||
OnBootCompleted?.Invoke();
|
||||
|
||||
// Notify the BootCompletionService that boot is complete
|
||||
// Notify the LifecycleManager that boot is complete
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// Direct call to boot completion service
|
||||
LogDebugMessage("Calling BootCompletionService.HandleBootCompleted()");
|
||||
BootCompletionService.HandleBootCompleted();
|
||||
LogDebugMessage("Calling LifecycleManager.OnBootCompletionTriggered()");
|
||||
if (LifecycleManager.Instance != null)
|
||||
{
|
||||
LifecycleManager.Instance.OnBootCompletionTriggered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,12 +124,14 @@ namespace Bootstrap
|
||||
OnBootProgressChanged?.Invoke(1f);
|
||||
OnBootCompleted?.Invoke();
|
||||
|
||||
// Notify the BootCompletionService that boot is complete
|
||||
// Notify the LifecycleManager that boot is complete
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// Direct call to boot completion service
|
||||
LogDebugMessage("Calling BootCompletionService.HandleBootCompleted()");
|
||||
BootCompletionService.HandleBootCompleted();
|
||||
LogDebugMessage("Calling LifecycleManager.OnBootCompletionTriggered()");
|
||||
if (LifecycleManager.Instance != null)
|
||||
{
|
||||
LifecycleManager.Instance.OnBootCompletionTriggered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
@@ -14,7 +14,7 @@ namespace Cinematics
|
||||
/// <summary>
|
||||
/// Handles loading, playing and unloading cinematics
|
||||
/// </summary>
|
||||
public class CinematicsManager : MonoBehaviour
|
||||
public class CinematicsManager : ManagedBehaviour
|
||||
{
|
||||
public event System.Action OnCinematicStarted;
|
||||
public event System.Action OnCinematicStopped;
|
||||
@@ -37,20 +37,21 @@ namespace Cinematics
|
||||
|
||||
public PlayableDirector playableDirector;
|
||||
|
||||
private void Awake()
|
||||
public override int ManagedAwakePriority => 170; // Cinematic systems
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// Initialize any dependencies that require other services to be ready
|
||||
// For example, subscribe to SceneManagerService events if needed
|
||||
Logging.Debug("[CinematicsManager] Post-boot initialization complete");
|
||||
Logging.Debug("[CinematicsManager] Initialized");
|
||||
}
|
||||
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
@@ -80,28 +81,30 @@ namespace Cinematics
|
||||
// Initialize PlayableDirector if not set
|
||||
if (playableDirector == null)
|
||||
{
|
||||
playableDirector = GetComponent<PlayableDirector>();
|
||||
playableDirector = PlayerHudManager.Instance.playableDirector;
|
||||
|
||||
// If still null, try to add the component
|
||||
if (playableDirector == null)
|
||||
{
|
||||
playableDirector = gameObject.AddComponent<PlayableDirector>();
|
||||
Debug.Log("[CinematicsManager] Added missing PlayableDirector component");
|
||||
Logging.Debug("[CinematicsManager] Could not find Playable Director on the PlayerHudManager");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize _cinematicSprites if not set
|
||||
if (_cinematicSprites == null)
|
||||
{
|
||||
// First try to find in children
|
||||
_cinematicSprites = GetComponentInChildren<Image>(true);
|
||||
// First try to find in children in the PlayerHud
|
||||
_cinematicSprites = PlayerHudManager.Instance.cinematicSprites;
|
||||
|
||||
// If still null, create a new UI Image for cinematics
|
||||
// If still null, return error
|
||||
if (_cinematicSprites == null)
|
||||
{
|
||||
Debug.LogWarning("[CinematicsManager] No Image found for cinematics display. Cinematics may not display correctly.");
|
||||
Logging.Warning("[CinematicsManager] No Image found for cinematics display. Cinematics may not display correctly.");
|
||||
}
|
||||
}
|
||||
|
||||
cinematicSpritesGameObject = PlayerHudManager.Instance.currentCinematicPlayer;
|
||||
cinematicBackground = PlayerHudManager.Instance.CinematicBackground;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -117,6 +120,7 @@ namespace Cinematics
|
||||
_cinematicSprites.enabled = true;
|
||||
cinematicSpritesGameObject.SetActive(true);
|
||||
}
|
||||
cinematicBackground.SetActive(true);
|
||||
|
||||
playableDirector.stopped += OnPlayableDirectorStopped;
|
||||
playableDirector.Play(assetToPlay);
|
||||
@@ -141,8 +145,10 @@ namespace Cinematics
|
||||
/// <summary>
|
||||
/// Loads a playable from an asset path and plays it as a cinematic
|
||||
/// </summary>
|
||||
public PlayableDirector LoadAndPlayCinematic(string key)
|
||||
public PlayableDirector LoadAndPlayCinematic(string key, bool playPortraitMode)
|
||||
{
|
||||
InitializeComponents();
|
||||
|
||||
// Load the asset via addressables
|
||||
var handle = Addressables.LoadAssetAsync<PlayableAsset>(key);
|
||||
var result = handle.WaitForCompletion();
|
||||
@@ -152,6 +158,7 @@ namespace Cinematics
|
||||
|
||||
Logging.Debug($"[CinematicsManager] Loaded addressable cinematic: {key}");
|
||||
|
||||
PlayerHudManager.Instance.SetPortraitMode(playPortraitMode);
|
||||
return PlayCinematic(result);
|
||||
}
|
||||
|
||||
@@ -197,11 +204,14 @@ namespace Cinematics
|
||||
|
||||
public void ShowCinematicBackground(bool shouldBeActive)
|
||||
{
|
||||
cinematicBackground.SetActive(shouldBeActive);
|
||||
cinematicBackground.SetActive(shouldBeActive);
|
||||
}
|
||||
|
||||
public void ShowGameOverScreen()
|
||||
{
|
||||
{
|
||||
// Diagnostic: log time and call stack to track when/why game over is triggered
|
||||
Logging.Debug($"[CinematicsManager] ShowGameOverScreen called at time={Time.time:F2}");
|
||||
|
||||
if (divingGameOverScreen != null && UIPageController.Instance != null)
|
||||
{
|
||||
UIPageController.Instance.PushPage(divingGameOverScreen);
|
||||
@@ -217,5 +227,12 @@ namespace Cinematics
|
||||
Logging.Warning("[CinematicsManager] DivingGameOverScreen reference is not set!");
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeCinematicBackgroundColour(Color clr)
|
||||
{
|
||||
PlayerHudManager.Instance.cinematicBackgroundSprites.color = clr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cinematics
|
||||
{
|
||||
public class SkipCinematic : MonoBehaviour, ITouchInputConsumer
|
||||
public class SkipCinematic : ManagedBehaviour, ITouchInputConsumer
|
||||
{
|
||||
[Header("Configuration")]
|
||||
[SerializeField] private float holdDuration = 2.0f;
|
||||
@@ -17,39 +17,28 @@ namespace Cinematics
|
||||
private bool _skipPerformed;
|
||||
private bool _initialized = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
public override int ManagedAwakePriority => 180; // Cinematic UI
|
||||
|
||||
void Start()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// Reset the progress bar
|
||||
if (radialProgressBar != null)
|
||||
{
|
||||
radialProgressBar.fillAmount = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
// Clean up subscriptions regardless of initialization state
|
||||
UnsubscribeFromCinematicsEvents();
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Safe initialization of manager dependencies after boot is complete
|
||||
if (_initialized)
|
||||
return;
|
||||
|
||||
_initialized = true;
|
||||
|
||||
// Subscribe to CinematicsManager events now that boot is complete
|
||||
SubscribeToCinematicsEvents();
|
||||
|
||||
Logging.Debug("[SkipCinematic] Post-boot initialization complete");
|
||||
Logging.Debug("[SkipCinematic] Initialized");
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
|
||||
// Clean up subscriptions
|
||||
UnsubscribeFromCinematicsEvents();
|
||||
}
|
||||
|
||||
private void SubscribeToCinematicsEvents()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using AppleHills.Core.Interfaces;
|
||||
using AppleHills.Core.Settings;
|
||||
using Bootstrap;
|
||||
using Core.Lifecycle;
|
||||
using Core.Settings;
|
||||
using Input;
|
||||
using UnityEngine;
|
||||
@@ -12,7 +12,7 @@ namespace Core
|
||||
/// <summary>
|
||||
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
|
||||
/// </summary>
|
||||
public class GameManager : MonoBehaviour
|
||||
public class GameManager : ManagedBehaviour
|
||||
{
|
||||
// Singleton implementation
|
||||
private static GameManager _instance;
|
||||
@@ -34,33 +34,33 @@ namespace Core
|
||||
public event Action OnGamePaused;
|
||||
public event Action OnGameResumed;
|
||||
|
||||
void Awake()
|
||||
// ManagedBehaviour configuration
|
||||
public override int ManagedAwakePriority => 10; // Core infrastructure - runs early
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
|
||||
// Create settings providers if it doesn't exist
|
||||
|
||||
// Create settings providers - must happen in Awake so other managers can access settings in their ManagedAwake
|
||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
||||
|
||||
// Load all settings synchronously during Awake
|
||||
// Load all settings synchronously - critical infrastructure for other managers
|
||||
InitializeSettings();
|
||||
InitializeDeveloperSettings();
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
|
||||
// DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
// Load verbosity settings early
|
||||
_settingsLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().settingsLogVerbosity;
|
||||
_managerLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().gameManagerLogVerbosity;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// For post-boot correct initialization order
|
||||
// Settings are already initialized in Awake()
|
||||
// This is available for future initialization that depends on other managers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Interactions;
|
||||
using Bootstrap;
|
||||
using Core.Lifecycle;
|
||||
using Core.SaveLoad;
|
||||
|
||||
namespace Core
|
||||
@@ -11,7 +11,7 @@ namespace Core
|
||||
/// Central registry for pickups and item slots.
|
||||
/// Mirrors the singleton pattern used by PuzzleManager.
|
||||
/// </summary>
|
||||
public class ItemManager : MonoBehaviour
|
||||
public class ItemManager : ManagedBehaviour
|
||||
{
|
||||
private static ItemManager _instance;
|
||||
|
||||
@@ -48,35 +48,32 @@ namespace Core
|
||||
// Args: first item data, second item data, result item data
|
||||
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
|
||||
|
||||
void Awake()
|
||||
public override int ManagedAwakePriority => 75; // Item registry
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// Subscribe to scene load completed so we can clear registrations when scenes change
|
||||
SceneManagerService.Instance.SceneLoadStarted += OnSceneLoadStarted;
|
||||
|
||||
Logging.Debug("[ItemManager] Subscribed to SceneManagerService events");
|
||||
Logging.Debug("[ItemManager] Initialized");
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
|
||||
protected override void OnSceneReady()
|
||||
{
|
||||
// Unsubscribe from SceneManagerService
|
||||
if (SceneManagerService.Instance != null)
|
||||
SceneManagerService.Instance.SceneLoadStarted -= OnSceneLoadStarted;
|
||||
|
||||
// Ensure we clean up any subscriptions from registered items when the manager is destroyed
|
||||
// Replaces SceneLoadStarted subscription for clearing registrations
|
||||
ClearAllRegistrations();
|
||||
}
|
||||
|
||||
private void OnSceneLoadStarted(string sceneName)
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
// Clear all registrations when a new scene is loaded, so no stale references persist
|
||||
base.OnDestroy();
|
||||
|
||||
// Ensure we clean up any subscriptions from registered items when the manager is destroyed
|
||||
ClearAllRegistrations();
|
||||
}
|
||||
|
||||
@@ -269,7 +266,7 @@ namespace Core
|
||||
// Search through all registered pickups
|
||||
foreach (var pickup in _pickups)
|
||||
{
|
||||
if (pickup is SaveableInteractable saveable && saveable.GetSaveId() == saveId)
|
||||
if (pickup is SaveableInteractable saveable && saveable.SaveId == saveId)
|
||||
{
|
||||
return pickup.gameObject;
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Core/Lifecycle.meta
Normal file
3
Assets/Scripts/Core/Lifecycle.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06a2c07342e5422eae1eb613f614ed61
|
||||
timeCreated: 1762206473
|
||||
48
Assets/Scripts/Core/Lifecycle/LifecycleEnums.cs
Normal file
48
Assets/Scripts/Core/Lifecycle/LifecycleEnums.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace Core.Lifecycle
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the different lifecycle phases that can be broadcast by the LifecycleManager.
|
||||
/// All ManagedBehaviours participate in all lifecycle phases by default.
|
||||
/// </summary>
|
||||
public enum LifecyclePhase
|
||||
{
|
||||
/// <summary>
|
||||
/// Called once per component after bootstrap completes.
|
||||
/// Guaranteed to be called after all bootstrap resources are loaded.
|
||||
/// For late-registered components, called immediately upon registration.
|
||||
/// </summary>
|
||||
ManagedAwake,
|
||||
|
||||
/// <summary>
|
||||
/// Called before a scene is unloaded.
|
||||
/// Only called for components in the scene being unloaded.
|
||||
/// </summary>
|
||||
SceneUnloading,
|
||||
|
||||
/// <summary>
|
||||
/// Called after a scene has finished loading.
|
||||
/// Only called for components in the scene being loaded.
|
||||
/// </summary>
|
||||
SceneReady,
|
||||
|
||||
/// <summary>
|
||||
/// Called before scene unloads to save data via SaveLoadManager.
|
||||
/// Integrates with existing SaveLoadManager save system.
|
||||
/// </summary>
|
||||
SaveRequested,
|
||||
|
||||
/// <summary>
|
||||
/// Called after scene loads to restore data via SaveLoadManager.
|
||||
/// Integrates with existing SaveLoadManager restore system.
|
||||
/// </summary>
|
||||
RestoreRequested,
|
||||
|
||||
/// <summary>
|
||||
/// Called during OnDestroy before component is destroyed.
|
||||
/// Use for custom cleanup logic.
|
||||
/// Most cleanup is automatic (managed events, auto-registrations).
|
||||
/// </summary>
|
||||
ManagedDestroy
|
||||
}
|
||||
}
|
||||
|
||||
2
Assets/Scripts/Core/Lifecycle/LifecycleEnums.cs.meta
Normal file
2
Assets/Scripts/Core/Lifecycle/LifecycleEnums.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f5f0f19f08240d4d9863b6be6a3cf03
|
||||
665
Assets/Scripts/Core/Lifecycle/LifecycleManager.cs
Normal file
665
Assets/Scripts/Core/Lifecycle/LifecycleManager.cs
Normal file
@@ -0,0 +1,665 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Core.Lifecycle
|
||||
{
|
||||
/// <summary>
|
||||
/// Central orchestrator for ManagedBehaviour lifecycle events.
|
||||
/// Singleton that broadcasts lifecycle events in priority-ordered manner.
|
||||
/// </summary>
|
||||
public class LifecycleManager : MonoBehaviour
|
||||
{
|
||||
#region Singleton
|
||||
|
||||
private static LifecycleManager _instance;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance of the LifecycleManager.
|
||||
/// Created by CustomBoot.Initialise() before bootstrap begins.
|
||||
/// </summary>
|
||||
public static LifecycleManager Instance => _instance;
|
||||
|
||||
/// <summary>
|
||||
/// Create LifecycleManager instance. Called by CustomBoot.Initialise() before bootstrap begins.
|
||||
/// </summary>
|
||||
public static void CreateInstance()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
Logging.Warning("[LifecycleManager] Instance already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
var go = new GameObject("LifecycleManager");
|
||||
_instance = go.AddComponent<LifecycleManager>();
|
||||
DontDestroyOnLoad(go);
|
||||
|
||||
Logging.Debug("[LifecycleManager] Instance created");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle Lists
|
||||
|
||||
private List<ManagedBehaviour> managedAwakeList = new List<ManagedBehaviour>();
|
||||
private List<ManagedBehaviour> sceneUnloadingList = new List<ManagedBehaviour>();
|
||||
private List<ManagedBehaviour> sceneReadyList = new List<ManagedBehaviour>();
|
||||
private List<ManagedBehaviour> saveRequestedList = new List<ManagedBehaviour>();
|
||||
private List<ManagedBehaviour> restoreRequestedList = new List<ManagedBehaviour>();
|
||||
private List<ManagedBehaviour> destroyList = new List<ManagedBehaviour>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tracking Dictionaries
|
||||
|
||||
private Dictionary<ManagedBehaviour, string> componentScenes = new Dictionary<ManagedBehaviour, string>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region State Flags
|
||||
|
||||
private bool isBootComplete = false;
|
||||
private string currentSceneReady = "";
|
||||
|
||||
// Scene loading state tracking
|
||||
private bool isLoadingScene = false;
|
||||
private string sceneBeingLoaded = "";
|
||||
private List<ManagedBehaviour> pendingSceneComponents = new List<ManagedBehaviour>();
|
||||
|
||||
[SerializeField] private bool enableDebugLogging = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity Lifecycle
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Instance should already be set by CreateInstance() called from CustomBoot
|
||||
// This Awake is backup in case LifecycleManager was manually added to a scene
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
LogDebug("LifecycleManager initialized via Awake (fallback)");
|
||||
}
|
||||
else if (_instance != this)
|
||||
{
|
||||
Logging.Warning("[LifecycleManager] Duplicate instance detected. Destroying.");
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (_instance == this)
|
||||
{
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Registration
|
||||
|
||||
/// <summary>
|
||||
/// Register a ManagedBehaviour with the lifecycle system.
|
||||
/// Called automatically from ManagedBehaviour.Awake().
|
||||
/// All components participate in all lifecycle hooks.
|
||||
/// </summary>
|
||||
public void Register(ManagedBehaviour component)
|
||||
{
|
||||
if (component == null)
|
||||
{
|
||||
Logging.Warning("[LifecycleManager] Attempted to register null component");
|
||||
return;
|
||||
}
|
||||
|
||||
var sceneName = component.gameObject.scene.name;
|
||||
|
||||
// Track which scene this component belongs to
|
||||
componentScenes[component] = sceneName;
|
||||
|
||||
// ALWAYS add to managedAwakeList - this is the master list used for save/load
|
||||
InsertSorted(managedAwakeList, component, component.ManagedAwakePriority);
|
||||
|
||||
// Handle ManagedAwake timing based on boot state
|
||||
if (isBootComplete)
|
||||
{
|
||||
// Check if we're currently loading a scene
|
||||
if (isLoadingScene && sceneName == sceneBeingLoaded)
|
||||
{
|
||||
// Batch this component - will be processed in priority order when scene load completes
|
||||
pendingSceneComponents.Add(component);
|
||||
LogDebug($"Batched component for scene load: {component.gameObject.name} (Scene: {sceneName})");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Truly late registration (component enabled after scene is ready)
|
||||
// Call OnManagedAwake immediately since boot already completed
|
||||
LogDebug($"Late registration: Calling OnManagedAwake immediately for {component.gameObject.name}");
|
||||
try
|
||||
{
|
||||
component.InvokeManagedAwake();
|
||||
HandleAutoRegistrations(component);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for {component.gameObject.name}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// If boot not complete, component stays in list and will be processed by BroadcastManagedAwake()
|
||||
|
||||
// Register for all scene lifecycle hooks
|
||||
InsertSorted(sceneUnloadingList, component, component.SceneUnloadingPriority);
|
||||
InsertSorted(sceneReadyList, component, component.SceneReadyPriority);
|
||||
InsertSorted(saveRequestedList, component, component.SavePriority);
|
||||
InsertSorted(restoreRequestedList, component, component.RestorePriority);
|
||||
InsertSorted(destroyList, component, component.DestroyPriority);
|
||||
|
||||
// If this scene is already ready (and we're not in loading mode), call OnSceneReady immediately
|
||||
if (!isLoadingScene && currentSceneReady == sceneName)
|
||||
{
|
||||
LogDebug($"Late registration: Calling OnSceneReady immediately for {component.gameObject.name}");
|
||||
try
|
||||
{
|
||||
component.InvokeSceneReady();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Error in OnSceneReady for {component.gameObject.name}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Registered {component.gameObject.name} (Scene: {sceneName})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregister a ManagedBehaviour from the lifecycle system.
|
||||
/// Called automatically from ManagedBehaviour.OnDestroy().
|
||||
/// </summary>
|
||||
public void Unregister(ManagedBehaviour component)
|
||||
{
|
||||
if (component == null)
|
||||
return;
|
||||
|
||||
managedAwakeList.Remove(component);
|
||||
sceneUnloadingList.Remove(component);
|
||||
sceneReadyList.Remove(component);
|
||||
saveRequestedList.Remove(component);
|
||||
restoreRequestedList.Remove(component);
|
||||
destroyList.Remove(component);
|
||||
|
||||
componentScenes.Remove(component);
|
||||
|
||||
LogDebug($"Unregistered {component.gameObject.name}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Broadcast Methods
|
||||
|
||||
/// <summary>
|
||||
/// Called by CustomBoot when boot completes.
|
||||
/// Broadcasts ManagedAwake to all registered components.
|
||||
/// </summary>
|
||||
public void OnBootCompletionTriggered()
|
||||
{
|
||||
if (isBootComplete)
|
||||
return;
|
||||
|
||||
LogDebug("=== Boot Completion Triggered ===");
|
||||
BroadcastManagedAwake();
|
||||
isBootComplete = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast OnManagedAwake to all registered components (priority ordered).
|
||||
/// </summary>
|
||||
private void BroadcastManagedAwake()
|
||||
{
|
||||
LogDebug($"Broadcasting ManagedAwake to {managedAwakeList.Count} components");
|
||||
|
||||
// Create a copy to avoid collection modification during iteration
|
||||
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
|
||||
|
||||
foreach (var component in componentsCopy)
|
||||
{
|
||||
if (component == null) continue;
|
||||
|
||||
try
|
||||
{
|
||||
component.InvokeManagedAwake();
|
||||
HandleAutoRegistrations(component);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for {component.gameObject.name}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: We do NOT clear managedAwakeList here!
|
||||
// This list is reused for save/load broadcasts and must persist for the lifetime of the game.
|
||||
// Components are added during registration and removed during Unregister (OnDestroy).
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins scene loading mode for the specified scene.
|
||||
/// Components that register during this time will be batched and processed in priority order.
|
||||
/// Call this BEFORE starting to load a scene.
|
||||
/// </summary>
|
||||
public void BeginSceneLoad(string sceneName)
|
||||
{
|
||||
isLoadingScene = true;
|
||||
sceneBeingLoaded = sceneName;
|
||||
pendingSceneComponents.Clear();
|
||||
LogDebug($"Began scene loading mode for: {sceneName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes all batched components from the scene load in priority order.
|
||||
/// Called automatically by BroadcastSceneReady.
|
||||
/// </summary>
|
||||
private void ProcessBatchedSceneComponents()
|
||||
{
|
||||
if (pendingSceneComponents.Count == 0)
|
||||
{
|
||||
isLoadingScene = false;
|
||||
sceneBeingLoaded = "";
|
||||
return;
|
||||
}
|
||||
|
||||
LogDebug($"Processing {pendingSceneComponents.Count} batched components for scene: {sceneBeingLoaded}");
|
||||
|
||||
// Sort by ManagedAwake priority (lower values first)
|
||||
pendingSceneComponents.Sort((a, b) => a.ManagedAwakePriority.CompareTo(b.ManagedAwakePriority));
|
||||
|
||||
// Call OnManagedAwake in priority order
|
||||
foreach (var component in pendingSceneComponents)
|
||||
{
|
||||
if (component == null) continue;
|
||||
|
||||
try
|
||||
{
|
||||
component.InvokeManagedAwake();
|
||||
HandleAutoRegistrations(component);
|
||||
LogDebug($"Processed batched component: {component.gameObject.name} (Priority: {component.ManagedAwakePriority})");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Error in OnManagedAwake for batched component {component.gameObject.name}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear state
|
||||
pendingSceneComponents.Clear();
|
||||
isLoadingScene = false;
|
||||
sceneBeingLoaded = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast OnSceneUnloading to components in the specified scene (reverse priority order).
|
||||
/// </summary>
|
||||
public void BroadcastSceneUnloading(string sceneName)
|
||||
{
|
||||
LogDebug($"Broadcasting SceneUnloading for scene: {sceneName}");
|
||||
|
||||
// Iterate backwards (high priority → low priority)
|
||||
for (int i = sceneUnloadingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var component = sceneUnloadingList[i];
|
||||
if (component == null) continue;
|
||||
|
||||
if (componentScenes.TryGetValue(component, out string compScene) && compScene == sceneName)
|
||||
{
|
||||
try
|
||||
{
|
||||
component.InvokeSceneUnloading();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Error in OnSceneUnloading for {component.gameObject.name}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast OnSceneReady to components in the specified scene (priority order).
|
||||
/// If scene loading mode is active, processes batched components first.
|
||||
/// </summary>
|
||||
public void BroadcastSceneReady(string sceneName)
|
||||
{
|
||||
LogDebug($"Broadcasting SceneReady for scene: {sceneName}");
|
||||
currentSceneReady = sceneName;
|
||||
|
||||
// If we were in scene loading mode for this scene, process batched components first
|
||||
if (isLoadingScene && sceneBeingLoaded == sceneName)
|
||||
{
|
||||
ProcessBatchedSceneComponents();
|
||||
}
|
||||
|
||||
// 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 (componentScenes.TryGetValue(component, out string compScene) && compScene == sceneName)
|
||||
{
|
||||
try
|
||||
{
|
||||
component.InvokeSceneReady();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Error in OnSceneReady for {component.gameObject.name}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts scene save request to all registered components that opt-in.
|
||||
/// Collects and returns serialized data from components that return non-null values.
|
||||
/// Called by SaveLoadManager during scene transitions.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> BroadcastSceneSaveRequested()
|
||||
{
|
||||
var saveData = new Dictionary<string, string>();
|
||||
|
||||
// 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;
|
||||
|
||||
try
|
||||
{
|
||||
string serializedData = component.InvokeSceneSaveRequested();
|
||||
if (!string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
string saveId = component.SaveId;
|
||||
saveData[saveId] = serializedData;
|
||||
LogDebug($"Collected scene save data from: {saveId} (Type: {component.GetType().Name})");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during scene save for {component.SaveId}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Collected scene save data from {saveData.Count} components");
|
||||
return saveData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts global save request to all registered components that opt-in.
|
||||
/// Collects and returns serialized data from components that return non-null values.
|
||||
/// Called by SaveLoadManager when writing save file to disk (quit, manual save).
|
||||
/// </summary>
|
||||
public Dictionary<string, string> BroadcastGlobalSaveRequested()
|
||||
{
|
||||
var saveData = new Dictionary<string, string>();
|
||||
|
||||
// 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;
|
||||
|
||||
try
|
||||
{
|
||||
string serializedData = component.InvokeGlobalSaveRequested();
|
||||
if (!string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
saveData[component.SaveId] = serializedData;
|
||||
LogDebug($"Collected global save data from: {component.SaveId}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during global save for {component.SaveId}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Collected global save data from {saveData.Count} components");
|
||||
return saveData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts scene restore request to all registered components that opt-in.
|
||||
/// Distributes serialized data to matching components by SaveId.
|
||||
/// Called by SaveLoadManager during scene load.
|
||||
/// </summary>
|
||||
public void BroadcastSceneRestoreRequested(Dictionary<string, string> saveData)
|
||||
{
|
||||
if (saveData == null) return;
|
||||
|
||||
int restoredCount = 0;
|
||||
|
||||
// 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 (saveData.TryGetValue(component.SaveId, out string serializedData))
|
||||
{
|
||||
try
|
||||
{
|
||||
component.InvokeSceneRestoreRequested(serializedData);
|
||||
restoredCount++;
|
||||
LogDebug($"Restored scene data to: {component.SaveId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during scene restore for {component.SaveId}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Restored scene data to {restoredCount} components");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts scene restore completed event to all registered components.
|
||||
/// Called AFTER all OnSceneRestoreRequested calls complete.
|
||||
/// </summary>
|
||||
public void BroadcastSceneRestoreCompleted()
|
||||
{
|
||||
LogDebug("Broadcasting SceneRestoreCompleted");
|
||||
|
||||
// Create a copy to avoid collection modification during iteration
|
||||
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
|
||||
|
||||
foreach (var component in componentsCopy)
|
||||
{
|
||||
if (component == null) continue;
|
||||
|
||||
try
|
||||
{
|
||||
component.InvokeSceneRestoreCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during scene restore completed for {component.SaveId}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug("SceneRestoreCompleted broadcast complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts global restore request to all registered components that opt-in.
|
||||
/// Distributes serialized data to matching components by SaveId.
|
||||
/// Called by SaveLoadManager during initial boot load.
|
||||
/// </summary>
|
||||
public void BroadcastGlobalRestoreRequested(Dictionary<string, string> saveData)
|
||||
{
|
||||
if (saveData == null) return;
|
||||
|
||||
int restoredCount = 0;
|
||||
|
||||
// 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 (saveData.TryGetValue(component.SaveId, out string serializedData))
|
||||
{
|
||||
try
|
||||
{
|
||||
component.InvokeGlobalRestoreRequested(serializedData);
|
||||
restoredCount++;
|
||||
LogDebug($"Restored global data to: {component.SaveId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during global restore for {component.SaveId}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Restored global data to {restoredCount} components");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts global load completed event to all registered components that opt-in.
|
||||
/// Called ONCE after save file is successfully loaded on game boot.
|
||||
/// NOT called during scene transitions.
|
||||
/// </summary>
|
||||
public void BroadcastGlobalLoadCompleted()
|
||||
{
|
||||
LogDebug("Broadcasting GlobalLoadCompleted");
|
||||
|
||||
// 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;
|
||||
|
||||
try
|
||||
{
|
||||
component.InvokeGlobalLoadCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during global load for {component.name}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts global save started event to all registered components that opt-in.
|
||||
/// Called ONCE before save file is written to disk.
|
||||
/// NOT called during scene transitions.
|
||||
/// </summary>
|
||||
public void BroadcastGlobalSaveStarted()
|
||||
{
|
||||
LogDebug("Broadcasting GlobalSaveStarted");
|
||||
|
||||
// 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;
|
||||
|
||||
try
|
||||
{
|
||||
component.InvokeGlobalSaveStarted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LifecycleManager] Exception during global save for {component.name}: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auto-Registration
|
||||
|
||||
/// <summary>
|
||||
/// Handle automatic registration with GameManager.
|
||||
/// </summary>
|
||||
private void HandleAutoRegistrations(ManagedBehaviour component)
|
||||
{
|
||||
|
||||
// Auto-register IPausable
|
||||
if (component.AutoRegisterPausable && component is AppleHills.Core.Interfaces.IPausable pausable)
|
||||
{
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.RegisterPausableComponent(pausable);
|
||||
LogDebug($"Auto-registered IPausable: {component.gameObject.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Insert component into list maintaining sorted order by priority.
|
||||
/// Uses binary search for efficient insertion.
|
||||
/// </summary>
|
||||
private void InsertSorted(List<ManagedBehaviour> list, ManagedBehaviour component, int priority)
|
||||
{
|
||||
// Simple linear insertion for now (can optimize with binary search later if needed)
|
||||
int index = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
int existingPriority = GetPriorityForList(list[i], list);
|
||||
if (priority < existingPriority)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
index = i + 1;
|
||||
}
|
||||
|
||||
list.Insert(index, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the priority value for a component based on which list it's in.
|
||||
/// </summary>
|
||||
private int GetPriorityForList(ManagedBehaviour component, List<ManagedBehaviour> list)
|
||||
{
|
||||
if (list == managedAwakeList) return component.ManagedAwakePriority;
|
||||
if (list == sceneUnloadingList) return component.SceneUnloadingPriority;
|
||||
if (list == sceneReadyList) return component.SceneReadyPriority;
|
||||
if (list == saveRequestedList) return component.SavePriority;
|
||||
if (list == restoreRequestedList) return component.RestorePriority;
|
||||
if (list == destroyList) return component.DestroyPriority;
|
||||
return 100;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log debug message if debug logging is enabled.
|
||||
/// </summary>
|
||||
private void LogDebug(string message)
|
||||
{
|
||||
if (enableDebugLogging)
|
||||
{
|
||||
Logging.Debug($"[LifecycleManager] {message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
2
Assets/Scripts/Core/Lifecycle/LifecycleManager.cs.meta
Normal file
2
Assets/Scripts/Core/Lifecycle/LifecycleManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db6d4743867a3a44381d511cea39218d
|
||||
316
Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs
Normal file
316
Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Core.Lifecycle
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all managed behaviours with deterministic lifecycle hooks.
|
||||
/// Automatically registers with LifecycleManager and provides ordered lifecycle callbacks.
|
||||
/// </summary>
|
||||
public abstract class ManagedBehaviour : MonoBehaviour
|
||||
{
|
||||
#region Priority Properties
|
||||
|
||||
/// <summary>
|
||||
/// Priority for OnManagedAwake (lower values execute first).
|
||||
/// Default: 100
|
||||
/// </summary>
|
||||
public virtual int ManagedAwakePriority => 100;
|
||||
|
||||
/// <summary>
|
||||
/// Priority for OnSceneUnloading (executed in reverse: higher values execute first).
|
||||
/// Default: 100
|
||||
/// </summary>
|
||||
public virtual int SceneUnloadingPriority => 100;
|
||||
|
||||
/// <summary>
|
||||
/// Priority for OnSceneReady (lower values execute first).
|
||||
/// Default: 100
|
||||
/// </summary>
|
||||
public virtual int SceneReadyPriority => 100;
|
||||
|
||||
/// <summary>
|
||||
/// Priority for OnSaveRequested (executed in reverse: higher values execute first).
|
||||
/// Default: 100
|
||||
/// </summary>
|
||||
public virtual int SavePriority => 100;
|
||||
|
||||
/// <summary>
|
||||
/// Priority for OnRestoreRequested (lower values execute first).
|
||||
/// Default: 100
|
||||
/// </summary>
|
||||
public virtual int RestorePriority => 100;
|
||||
|
||||
/// <summary>
|
||||
/// Priority for OnManagedDestroy (executed in reverse: higher values execute first).
|
||||
/// Default: 100
|
||||
/// </summary>
|
||||
public virtual int DestroyPriority => 100;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Configuration Properties
|
||||
|
||||
/// <summary>
|
||||
/// If true and component implements IPausable, automatically registers with GameManager.
|
||||
/// Default: false
|
||||
/// </summary>
|
||||
public virtual bool AutoRegisterPausable => false;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this component participates in the save/load system.
|
||||
/// Components should override OnSaveRequested() and OnRestoreRequested().
|
||||
/// Default: false
|
||||
/// </summary>
|
||||
public virtual bool AutoRegisterForSave => false;
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier for this component in the save system.
|
||||
/// Default: "SceneName/GameObjectName/ComponentType"
|
||||
/// Override ONLY for special cases (e.g., singletons like "PlayerController", or custom IDs).
|
||||
/// </summary>
|
||||
public virtual string SaveId
|
||||
{
|
||||
get
|
||||
{
|
||||
string sceneName = gameObject.scene.IsValid() ? gameObject.scene.name : "UnknownScene";
|
||||
string componentType = GetType().Name;
|
||||
return $"{sceneName}/{gameObject.name}/{componentType}";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Accessors (for LifecycleManager)
|
||||
|
||||
// Public wrappers to invoke protected lifecycle methods
|
||||
public void InvokeManagedAwake() => OnManagedAwake();
|
||||
public void InvokeSceneUnloading() => OnSceneUnloading();
|
||||
public void InvokeSceneReady() => OnSceneReady();
|
||||
public string InvokeSceneSaveRequested() => OnSceneSaveRequested();
|
||||
public void InvokeSceneRestoreRequested(string data) => OnSceneRestoreRequested(data);
|
||||
public void InvokeSceneRestoreCompleted() => OnSceneRestoreCompleted();
|
||||
public string InvokeGlobalSaveRequested() => OnGlobalSaveRequested();
|
||||
public void InvokeGlobalRestoreRequested(string data) => OnGlobalRestoreRequested(data);
|
||||
public void InvokeManagedDestroy() => OnManagedDestroy();
|
||||
public void InvokeGlobalLoadCompleted() => OnGlobalLoadCompleted();
|
||||
public void InvokeGlobalSaveStarted() => OnGlobalSaveStarted();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool _isRegistered;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// Unity Awake - automatically registers with LifecycleManager.
|
||||
/// IMPORTANT: Derived classes that override Awake MUST call base.Awake()
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (LifecycleManager.Instance != null)
|
||||
{
|
||||
LifecycleManager.Instance.Register(this);
|
||||
_isRegistered = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[ManagedBehaviour] LifecycleManager not found for {gameObject.name}. Component will not receive lifecycle callbacks.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity OnDestroy - automatically unregisters and cleans up.
|
||||
/// IMPORTANT: Derived classes that override OnDestroy MUST call base.OnDestroy()
|
||||
/// </summary>
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (!_isRegistered)
|
||||
return;
|
||||
|
||||
// Unregister from LifecycleManager
|
||||
if (LifecycleManager.Instance != null)
|
||||
{
|
||||
LifecycleManager.Instance.Unregister(this);
|
||||
}
|
||||
|
||||
|
||||
// Auto-unregister from GameManager if auto-registered
|
||||
if (AutoRegisterPausable && this is AppleHills.Core.Interfaces.IPausable pausable)
|
||||
{
|
||||
GameManager.Instance?.UnregisterPausableComponent(pausable);
|
||||
}
|
||||
|
||||
_isRegistered = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Managed Lifecycle Hooks
|
||||
|
||||
/// <summary>
|
||||
/// Called once per component after bootstrap completes.
|
||||
/// GUARANTEE: Bootstrap resources are available, all managers are initialized.
|
||||
/// For boot-time components: Called during LifecycleManager.BroadcastManagedAwake (priority ordered).
|
||||
/// For late-registered components: Called immediately upon registration (bootstrap already complete).
|
||||
/// Replaces the old Awake + InitializePostBoot pattern.
|
||||
/// </summary>
|
||||
protected virtual void OnManagedAwake()
|
||||
{
|
||||
// Override in derived classes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called before the scene this component belongs to is unloaded.
|
||||
/// Called in REVERSE priority order (higher values execute first).
|
||||
/// Use for scene-specific cleanup.
|
||||
/// </summary>
|
||||
protected virtual void OnSceneUnloading()
|
||||
{
|
||||
// Override in derived classes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after the scene this component belongs to has finished loading.
|
||||
/// Called in priority order (lower values execute first).
|
||||
/// Use for scene-specific initialization.
|
||||
/// </summary>
|
||||
protected virtual void OnSceneReady()
|
||||
{
|
||||
// Override in derived classes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called during scene transitions to save scene-specific state.
|
||||
/// Return serialized data (e.g., JsonUtility.ToJson(myData)).
|
||||
/// Return null if component has no scene-specific state to save.
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called BEFORE scene unload during scene transitions
|
||||
/// - Frequency: Every scene transition
|
||||
/// - Use for: Level progress, object positions, puzzle states
|
||||
/// </summary>
|
||||
protected virtual string OnSceneSaveRequested()
|
||||
{
|
||||
return null; // Default: no data to save
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called during scene transitions to restore scene-specific state.
|
||||
/// Receives previously serialized data (from OnSceneSaveRequested).
|
||||
///
|
||||
/// IMPORTANT: This method MUST be synchronous. Do not use coroutines or async/await.
|
||||
/// OnSceneRestoreCompleted is called immediately after all restore calls complete,
|
||||
/// so any async operations would still be running when it fires.
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called AFTER scene load, during OnSceneReady phase
|
||||
/// - Frequency: Every scene transition
|
||||
/// - Use for: Restoring level progress, object positions, puzzle states
|
||||
/// </summary>
|
||||
protected virtual void OnSceneRestoreRequested(string serializedData)
|
||||
{
|
||||
// Default: no-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after all scene restore operations complete.
|
||||
/// Does NOT receive data - use OnSceneRestoreRequested for that.
|
||||
///
|
||||
/// GUARANTEE:
|
||||
/// - ALWAYS called after scene load, whether there's save data or not
|
||||
/// - All OnSceneRestoreRequested() calls have RETURNED (but async operations may still be running)
|
||||
/// - Safe for synchronous restore operations (JSON deserialization, setting fields, etc.)
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called AFTER all OnSceneRestoreRequested calls complete (or immediately if no save data exists)
|
||||
/// - Frequency: Every scene transition
|
||||
/// - Use for: Post-restore initialization, first-time initialization, triggering events after state is restored
|
||||
///
|
||||
/// COMMON PATTERN:
|
||||
/// Use this to perform actions that depend on whether data was restored or not.
|
||||
/// Example: Play one-time audio only if it hasn't been played before (_hasPlayed == false).
|
||||
/// </summary>
|
||||
protected virtual void OnSceneRestoreCompleted()
|
||||
{
|
||||
// Default: no-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called once on game boot to restore global persistent state.
|
||||
/// Receives data that was saved via OnGlobalSaveRequested.
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called ONCE on game boot after save file is read
|
||||
/// - NOT called during scene transitions
|
||||
/// - Use for: Player inventory, unlocked features, card collections
|
||||
/// </summary>
|
||||
protected virtual void OnGlobalRestoreRequested(string serializedData)
|
||||
{
|
||||
// Default: no-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called once before game save file is written to disk.
|
||||
/// Return serialized data for global persistent state.
|
||||
/// Return null if component has no global state to save.
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called ONCE before save file is written (on quit, manual save, etc.)
|
||||
/// - NOT called during scene transitions
|
||||
/// - Use for: Player inventory, unlocked features, card collections
|
||||
/// </summary>
|
||||
protected virtual string OnGlobalSaveRequested()
|
||||
{
|
||||
return null; // Default: no data to save
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called once when game save data is initially loaded from disk.
|
||||
/// Use for global managers that need to react to load completion.
|
||||
/// Does NOT receive data - use OnGlobalRestoreRequested for that.
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called ONCE on game boot after all restore operations complete
|
||||
/// - NOT called during scene transitions
|
||||
/// - Use for: Triggering UI updates, broadcasting load events
|
||||
/// </summary>
|
||||
protected virtual void OnGlobalLoadCompleted()
|
||||
{
|
||||
// Default: no-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called once before save file is written to disk.
|
||||
/// Use for global managers that need to perform cleanup before save.
|
||||
/// Does NOT return data - use OnGlobalSaveRequested for that.
|
||||
///
|
||||
/// TIMING:
|
||||
/// - Called ONCE before save file is written
|
||||
/// - NOT called during scene transitions
|
||||
/// - Use for: Final validation, cleanup operations
|
||||
/// </summary>
|
||||
protected virtual void OnGlobalSaveStarted()
|
||||
{
|
||||
// Default: no-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called during OnDestroy before component is destroyed.
|
||||
/// Called in REVERSE priority order (higher values execute first).
|
||||
/// NOTE: Most cleanup is automatic (managed events, auto-registrations).
|
||||
/// Only override if you need custom cleanup logic.
|
||||
/// </summary>
|
||||
protected virtual void OnManagedDestroy()
|
||||
{
|
||||
// Override in derived classes
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
2
Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs.meta
Normal file
2
Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af776ef1493d6e543aa3cbe2601f4ef2
|
||||
@@ -1,7 +1,7 @@
|
||||
using UnityEngine;
|
||||
using AppleHills.Data.CardSystem;
|
||||
using Cinematics;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Data.CardSystem;
|
||||
using Input;
|
||||
using PuzzleS;
|
||||
@@ -12,7 +12,7 @@ namespace AppleHills.Core
|
||||
/// Provides quick access to frequently used game objects, components, and manager instances.
|
||||
/// References are cached for performance and automatically invalidated on scene changes.
|
||||
/// </summary>
|
||||
public class QuickAccess : MonoBehaviour
|
||||
public class QuickAccess : ManagedBehaviour
|
||||
{
|
||||
#region Singleton Setup
|
||||
private static QuickAccess _instance;
|
||||
@@ -24,6 +24,9 @@ namespace AppleHills.Core
|
||||
|
||||
#endregion Singleton Setup
|
||||
|
||||
// Very early initialization - QuickAccess should be available immediately
|
||||
public override int ManagedAwakePriority => 5;
|
||||
|
||||
#region Manager Instances
|
||||
|
||||
// Core Managers
|
||||
@@ -46,7 +49,6 @@ namespace AppleHills.Core
|
||||
private PlayerTouchController _playerController;
|
||||
private FollowerController _followerController;
|
||||
private Camera _mainCamera;
|
||||
private bool _initialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the player GameObject. Finds it if not already cached.
|
||||
@@ -125,31 +127,31 @@ namespace AppleHills.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialization and Scene Management
|
||||
#region Lifecycle Methods
|
||||
|
||||
private void Awake()
|
||||
private new void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
if (!_initialized)
|
||||
{
|
||||
// Subscribe to scene changes
|
||||
if (SceneManager != null)
|
||||
{
|
||||
SceneManager.SceneLoadCompleted += OnSceneLoadCompleted;
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle scene changes by clearing cached references.
|
||||
/// </summary>
|
||||
private void OnSceneLoadCompleted(string sceneName)
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// QuickAccess has minimal initialization
|
||||
}
|
||||
|
||||
protected override void OnSceneUnloading()
|
||||
{
|
||||
// Clear references BEFORE scene unloads for better cleanup timing
|
||||
ClearReferences();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Reference Management
|
||||
|
||||
/// <summary>
|
||||
/// Clear all cached references.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using UnityEngine;
|
||||
using Pixelplacement;
|
||||
using Bootstrap;
|
||||
|
||||
namespace Core.SaveLoad
|
||||
{
|
||||
@@ -82,18 +81,15 @@ namespace Core.SaveLoad
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Register with save system (no validation needed - we auto-generate ID)
|
||||
BootCompletionService.RegisterInitAction(() =>
|
||||
// Direct registration - SaveLoadManager guaranteed available (priority 25)
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.RegisterParticipant(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[SaveableStateMachine] SaveLoadManager.Instance is null, cannot register '{name}'", this);
|
||||
}
|
||||
});
|
||||
SaveLoadManager.Instance.RegisterParticipant(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[AppleMachine] SaveLoadManager not available for '{name}'");
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
@@ -102,7 +98,7 @@ namespace Core.SaveLoad
|
||||
// Optional: Log the auto-generated ID in verbose mode
|
||||
if (verbose && string.IsNullOrEmpty(customSaveId))
|
||||
{
|
||||
Debug.Log($"[SaveableStateMachine] '{name}' will use auto-generated Save ID: {GetSaveId()}", this);
|
||||
Logging.Debug($"[SaveableStateMachine] '{name}' will use auto-generated Save ID: {GetSaveId()}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -127,9 +123,8 @@ namespace Core.SaveLoad
|
||||
return $"{sceneName}/{customSaveId}";
|
||||
}
|
||||
|
||||
// Auto-generate from hierarchy path
|
||||
string hierarchyPath = GetHierarchyPath();
|
||||
return $"{sceneName}/StateMachine_{hierarchyPath}";
|
||||
// Match ManagedBehaviour convention: SceneName/GameObjectName/ComponentType
|
||||
return $"{sceneName}/{gameObject.name}/AppleMachine";
|
||||
}
|
||||
|
||||
private string GetSceneName()
|
||||
@@ -137,19 +132,6 @@ namespace Core.SaveLoad
|
||||
return gameObject.scene.name;
|
||||
}
|
||||
|
||||
private string GetHierarchyPath()
|
||||
{
|
||||
string path = gameObject.name;
|
||||
Transform parent = transform.parent;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
path = parent.name + "/" + path;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public string SerializeState()
|
||||
{
|
||||
@@ -176,7 +158,7 @@ namespace Core.SaveLoad
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
Debug.LogWarning($"[SaveableStateMachine] No data to restore for '{name}'", this);
|
||||
Logging.Warning($"[SaveableStateMachine] No data to restore for '{name}'");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -189,7 +171,7 @@ namespace Core.SaveLoad
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
Debug.LogWarning($"[SaveableStateMachine] No state name in save data for '{name}'", this);
|
||||
Logging.Warning($"[SaveableStateMachine] No state name in save data for '{name}'");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -215,7 +197,7 @@ namespace Core.SaveLoad
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
Debug.Log($"[SaveableStateMachine] Restored '{name}' to state: {saveData.stateName}", this);
|
||||
Logging.Debug($"[SaveableStateMachine] Restored '{name}' to state: {saveData.stateName}");
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
@@ -233,14 +215,14 @@ namespace Core.SaveLoad
|
||||
[ContextMenu("Log Save ID")]
|
||||
private void LogSaveId()
|
||||
{
|
||||
Debug.Log($"Save ID: {GetSaveId()}", this);
|
||||
Logging.Debug($"Save ID: {GetSaveId()}");
|
||||
}
|
||||
|
||||
[ContextMenu("Test Serialize")]
|
||||
private void TestSerialize()
|
||||
{
|
||||
string serialized = SerializeState();
|
||||
Debug.Log($"Serialized state: {serialized}", this);
|
||||
Logging.Debug($"Serialized state: {serialized}");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using AppleHills.Core.Settings;
|
||||
using Bootstrap;
|
||||
using Core.Lifecycle;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Core.SaveLoad
|
||||
{
|
||||
/// <summary>
|
||||
/// Save/Load manager that follows the project's bootstrap pattern.
|
||||
/// Save/Load manager that follows the project's lifecycle pattern.
|
||||
/// - Singleton instance
|
||||
/// - Registers a post-boot init action with BootCompletionService
|
||||
/// - Inherits from ManagedBehaviour for lifecycle integration
|
||||
/// - Manages participant registration for save/load operations
|
||||
/// - Exposes simple async Save/Load methods
|
||||
/// - Fires events on completion
|
||||
/// </summary>
|
||||
public class SaveLoadManager : MonoBehaviour
|
||||
public class SaveLoadManager : ManagedBehaviour
|
||||
{
|
||||
private static SaveLoadManager _instance;
|
||||
public static SaveLoadManager Instance => _instance;
|
||||
@@ -43,24 +43,49 @@ namespace Core.SaveLoad
|
||||
public event Action<string> OnLoadCompleted;
|
||||
public event Action OnParticipantStatesRestored;
|
||||
|
||||
void Awake()
|
||||
// ManagedBehaviour configuration
|
||||
public override int ManagedAwakePriority => 20; // After GameManager and SceneManagerService
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
|
||||
// Initialize critical state immediately
|
||||
IsSaveDataLoaded = false;
|
||||
IsRestoringState = false;
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
OnSceneLoadCompleted("RestoreInEditor");
|
||||
#endif
|
||||
Logging.Debug("[SaveLoadManager] Initialized");
|
||||
|
||||
// Load save data if save system is enabled (depends on settings from GameManager)
|
||||
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().useSaveLoadSystem)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSceneReady()
|
||||
{
|
||||
// SaveableInteractables now auto-register via ManagedBehaviour lifecycle
|
||||
// No need to discover and register them manually
|
||||
}
|
||||
|
||||
protected override string OnSceneSaveRequested()
|
||||
{
|
||||
// SaveLoadManager orchestrates saves, doesn't participate in them
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override string OnGlobalSaveRequested()
|
||||
{
|
||||
// SaveLoadManager orchestrates saves, doesn't participate in them
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
@@ -70,30 +95,14 @@ namespace Core.SaveLoad
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
Logging.Debug("[SaveLoadManager] Post-boot initialization complete");
|
||||
|
||||
// Subscribe to scene lifecycle events if SceneManagerService is available
|
||||
if (SceneManagerService.Instance != null)
|
||||
{
|
||||
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
|
||||
SceneManagerService.Instance.SceneUnloadStarted += OnSceneUnloadStarted;
|
||||
Logging.Debug("[SaveLoadManager] Subscribed to SceneManagerService events");
|
||||
}
|
||||
}
|
||||
// ...existing code...
|
||||
|
||||
void OnDestroy()
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy(); // Important: call base to unregister from LifecycleManager
|
||||
|
||||
if (_instance == this)
|
||||
{
|
||||
// Unsubscribe from scene events
|
||||
if (SceneManagerService.Instance != null)
|
||||
{
|
||||
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
||||
SceneManagerService.Instance.SceneUnloadStarted -= OnSceneUnloadStarted;
|
||||
}
|
||||
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
@@ -173,40 +182,93 @@ namespace Core.SaveLoad
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scene Lifecycle
|
||||
#region Unlocked Minigames Management
|
||||
|
||||
private void OnSceneLoadCompleted(string sceneName)
|
||||
/// <summary>
|
||||
/// Marks a minigame as unlocked in the global save data.
|
||||
/// This is separate from scene-specific participant states and persists across all saves.
|
||||
/// </summary>
|
||||
/// <param name="minigameName">The name/identifier of the minigame (typically scene name)</param>
|
||||
public void UnlockMinigame(string minigameName)
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Scene '{sceneName}' loaded. Discovering inactive SaveableInteractables...");
|
||||
|
||||
// Find ONLY INACTIVE SaveableInteractables (active ones will register themselves via Start())
|
||||
var inactiveSaveables = FindObjectsByType(
|
||||
typeof(Interactions.SaveableInteractable),
|
||||
FindObjectsInactive.Include,
|
||||
FindObjectsSortMode.None
|
||||
);
|
||||
|
||||
int registeredCount = 0;
|
||||
foreach (var obj in inactiveSaveables)
|
||||
if (string.IsNullOrEmpty(minigameName))
|
||||
{
|
||||
var saveable = obj as Interactions.SaveableInteractable;
|
||||
if (saveable != null && !saveable.gameObject.activeInHierarchy)
|
||||
{
|
||||
// Only register if it's actually inactive
|
||||
RegisterParticipant(saveable);
|
||||
registeredCount++;
|
||||
}
|
||||
Logging.Warning("[SaveLoadManager] Attempted to unlock minigame with null or empty name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSaveData == null)
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] Cannot unlock minigame - no save data loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSaveData.unlockedMinigames == null)
|
||||
{
|
||||
currentSaveData.unlockedMinigames = new System.Collections.Generic.List<string>();
|
||||
}
|
||||
|
||||
if (!currentSaveData.unlockedMinigames.Contains(minigameName))
|
||||
{
|
||||
currentSaveData.unlockedMinigames.Add(minigameName);
|
||||
Logging.Debug($"[SaveLoadManager] Unlocked minigame: {minigameName}");
|
||||
}
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Discovered and registered {registeredCount} inactive SaveableInteractables");
|
||||
}
|
||||
|
||||
private void OnSceneUnloadStarted(string sceneName)
|
||||
/// <summary>
|
||||
/// Checks if a minigame has been unlocked.
|
||||
/// </summary>
|
||||
/// <param name="minigameName">The name/identifier of the minigame</param>
|
||||
/// <returns>True if the minigame is unlocked, false otherwise</returns>
|
||||
public bool IsMinigameUnlocked(string minigameName)
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Scene '{sceneName}' unloading. Note: Participants should unregister themselves.");
|
||||
|
||||
// We don't force-clear here because participants should manage their own lifecycle
|
||||
// This allows for proper cleanup in OnDestroy
|
||||
if (string.IsNullOrEmpty(minigameName))
|
||||
return false;
|
||||
|
||||
if (currentSaveData == null || currentSaveData.unlockedMinigames == null)
|
||||
return false;
|
||||
|
||||
return currentSaveData.unlockedMinigames.Contains(minigameName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only list of all unlocked minigames.
|
||||
/// </summary>
|
||||
public System.Collections.Generic.IReadOnlyList<string> GetUnlockedMinigames()
|
||||
{
|
||||
if (currentSaveData == null || currentSaveData.unlockedMinigames == null)
|
||||
return new System.Collections.Generic.List<string>();
|
||||
|
||||
return currentSaveData.unlockedMinigames.AsReadOnly();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all save data for a specific level/scene.
|
||||
/// Removes all participant states that belong to the specified scene.
|
||||
/// Useful for "restart level" functionality to wipe progress.
|
||||
/// </summary>
|
||||
/// <param name="sceneName">The name of the scene to clear data for</param>
|
||||
public void ClearLevelData(string sceneName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sceneName))
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] Cannot clear level data - scene name is null or empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSaveData == null || currentSaveData.participantStates == null)
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] Cannot clear level data - no save data loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// SaveId format is "SceneName/ObjectName/ComponentType"
|
||||
// Remove all entries that start with "sceneName/"
|
||||
string scenePrefix = $"{sceneName}/";
|
||||
int removedCount = currentSaveData.participantStates.RemoveAll(entry =>
|
||||
entry.saveId.StartsWith(scenePrefix));
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Cleared {removedCount} save entries for level: {sceneName}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -254,8 +316,31 @@ namespace Core.SaveLoad
|
||||
return;
|
||||
|
||||
IsRestoringState = true;
|
||||
int restoredCount = 0;
|
||||
|
||||
// Build dictionary for efficient lookup
|
||||
var saveDataDict = new Dictionary<string, string>();
|
||||
foreach (var entry in currentSaveData.participantStates)
|
||||
{
|
||||
saveDataDict[entry.saveId] = entry.serializedState;
|
||||
}
|
||||
|
||||
// NEW: Restore GLOBAL data via LifecycleManager (called ONCE on boot)
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastGlobalRestoreRequested(saveDataDict);
|
||||
Logging.Debug($"[SaveLoadManager] Broadcast GLOBAL restore to LifecycleManager");
|
||||
}
|
||||
|
||||
// NEW: Restore SCENE data via LifecycleManager (for currently loaded scenes)
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreRequested(saveDataDict);
|
||||
Logging.Debug($"[SaveLoadManager] Broadcast SCENE restore to LifecycleManager");
|
||||
}
|
||||
|
||||
// EXISTING: Restore ISaveParticipants (backward compatibility)
|
||||
int restoredCount = 0;
|
||||
|
||||
// Clear pending queue at the start
|
||||
pendingParticipants.Clear();
|
||||
|
||||
@@ -266,19 +351,17 @@ namespace Core.SaveLoad
|
||||
string saveId = kvp.Key;
|
||||
ISaveParticipant participant = kvp.Value;
|
||||
|
||||
// Find the participant state in the list
|
||||
var entry = currentSaveData.participantStates.Find(e => e.saveId == saveId);
|
||||
if (entry != null && !string.IsNullOrEmpty(entry.serializedState))
|
||||
if (saveDataDict.TryGetValue(saveId, out string serializedState))
|
||||
{
|
||||
try
|
||||
{
|
||||
participant.RestoreState(entry.serializedState);
|
||||
participant.RestoreState(serializedState);
|
||||
restoredCount++;
|
||||
Logging.Debug($"[SaveLoadManager] Restored state for participant: {saveId}");
|
||||
Logging.Debug($"[SaveLoadManager] Restored ISaveParticipant: {saveId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Exception while restoring state for '{saveId}': {ex}");
|
||||
Logging.Warning($"[SaveLoadManager] Exception while restoring '{saveId}': {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -324,7 +407,7 @@ namespace Core.SaveLoad
|
||||
pendingParticipants.Clear();
|
||||
IsRestoringState = false;
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Restored state for {restoredCount} participants + {totalPendingRestored} pending participants");
|
||||
Logging.Debug($"[SaveLoadManager] Restored {restoredCount} ISaveParticipants + {totalPendingRestored} pending participants");
|
||||
OnParticipantStatesRestored?.Invoke();
|
||||
}
|
||||
|
||||
@@ -335,6 +418,126 @@ namespace Core.SaveLoad
|
||||
return Path.Combine(DefaultSaveFolder, $"save_{slot}.json");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves scene-specific data during scene transitions.
|
||||
/// This updates the in-memory save data but does NOT write to disk.
|
||||
/// Call Save() to persist to disk.
|
||||
/// </summary>
|
||||
public void SaveSceneData()
|
||||
{
|
||||
if (currentSaveData == null)
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] Cannot save scene data - no save data loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.Debug("[SaveLoadManager] Saving scene-specific data...");
|
||||
|
||||
// Build a dictionary of all data to save
|
||||
var allSceneData = new Dictionary<string, string>();
|
||||
|
||||
// Collect scene data from ManagedBehaviours via LifecycleManager
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
var sceneData = Lifecycle.LifecycleManager.Instance.BroadcastSceneSaveRequested();
|
||||
foreach (var kvp in sceneData)
|
||||
{
|
||||
allSceneData[kvp.Key] = kvp.Value;
|
||||
}
|
||||
Logging.Debug($"[SaveLoadManager] Collected {sceneData.Count} ManagedBehaviour scene states");
|
||||
}
|
||||
|
||||
// Collect data from ISaveParticipants (all currently registered, identified by SaveId)
|
||||
foreach (var kvp in participants.ToList())
|
||||
{
|
||||
string saveId = kvp.Key;
|
||||
ISaveParticipant participant = kvp.Value;
|
||||
|
||||
try
|
||||
{
|
||||
string serializedState = participant.SerializeState();
|
||||
allSceneData[saveId] = serializedState;
|
||||
Logging.Debug($"[SaveLoadManager] Captured state for ISaveParticipant: {saveId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Exception while serializing ISaveParticipant '{saveId}': {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// Update existing entries or add new ones (matches SaveAsync() pattern)
|
||||
if (currentSaveData.participantStates != null)
|
||||
{
|
||||
int updatedCount = 0;
|
||||
|
||||
foreach (var kvp in allSceneData)
|
||||
{
|
||||
var existingEntry = currentSaveData.participantStates.Find(e => e.saveId == kvp.Key);
|
||||
if (existingEntry != null)
|
||||
{
|
||||
// Update existing entry in place
|
||||
existingEntry.serializedState = kvp.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new entry
|
||||
currentSaveData.participantStates.Add(new ParticipantStateEntry
|
||||
{
|
||||
saveId = kvp.Key,
|
||||
serializedState = kvp.Value
|
||||
});
|
||||
}
|
||||
updatedCount++;
|
||||
}
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Updated {updatedCount} scene data entries in memory");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] participantStates list is null, cannot save scene data");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores scene-specific data after scene load.
|
||||
/// Distributes data to components in the newly loaded scene.
|
||||
/// </summary>
|
||||
public void RestoreSceneData()
|
||||
{
|
||||
if (Lifecycle.LifecycleManager.Instance == null)
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] LifecycleManager not available for scene restore");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSaveData == null || currentSaveData.participantStates == null)
|
||||
{
|
||||
Logging.Debug("[SaveLoadManager] No scene data to restore (first visit or no save data)");
|
||||
|
||||
// Still broadcast restore completed so components can initialize properly
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreCompleted();
|
||||
Logging.Debug($"[SaveLoadManager] Scene restore completed (no data)");
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.Debug("[SaveLoadManager] Restoring scene-specific data...");
|
||||
|
||||
// Build dictionary for efficient lookup
|
||||
var saveDataDict = new Dictionary<string, string>();
|
||||
foreach (var entry in currentSaveData.participantStates)
|
||||
{
|
||||
saveDataDict[entry.saveId] = entry.serializedState;
|
||||
}
|
||||
|
||||
// Restore scene data via LifecycleManager
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreRequested(saveDataDict);
|
||||
Logging.Debug($"[SaveLoadManager] Broadcast scene restore to LifecycleManager");
|
||||
|
||||
// Broadcast scene restore completed - ALWAYS called, whether there's data or not
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreCompleted();
|
||||
Logging.Debug($"[SaveLoadManager] Scene restore completed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entry point to save to a named slot. Starts an async coroutine that writes to disk.
|
||||
/// Fires OnSaveCompleted when finished.
|
||||
@@ -391,14 +594,44 @@ namespace Core.SaveLoad
|
||||
{
|
||||
currentSaveData.participantStates = new List<ParticipantStateEntry>();
|
||||
}
|
||||
else
|
||||
// NOTE: We do NOT clear participantStates here!
|
||||
// We preserve data from all scenes and update/add as needed.
|
||||
// This allows Level A data to persist when saving from Level B.
|
||||
|
||||
int savedCount = 0;
|
||||
|
||||
// NEW: Broadcast global save started event (ONCE)
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
currentSaveData.participantStates.Clear();
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastGlobalSaveStarted();
|
||||
}
|
||||
|
||||
// Capture state from all registered participants directly into the list
|
||||
// Create a snapshot to avoid collection modification during iteration
|
||||
int savedCount = 0;
|
||||
// Build a dictionary of all new data to save
|
||||
var allNewData = new Dictionary<string, string>();
|
||||
|
||||
// NEW: Collect GLOBAL data from ManagedBehaviours via LifecycleManager
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
var globalData = Lifecycle.LifecycleManager.Instance.BroadcastGlobalSaveRequested();
|
||||
foreach (var kvp in globalData)
|
||||
{
|
||||
allNewData[kvp.Key] = kvp.Value;
|
||||
}
|
||||
Logging.Debug($"[SaveLoadManager] Collected {globalData.Count} GLOBAL save states");
|
||||
}
|
||||
|
||||
// NEW: Collect SCENE data from all loaded scenes
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
var sceneData = Lifecycle.LifecycleManager.Instance.BroadcastSceneSaveRequested();
|
||||
foreach (var kvp in sceneData)
|
||||
{
|
||||
allNewData[kvp.Key] = kvp.Value;
|
||||
}
|
||||
Logging.Debug($"[SaveLoadManager] Collected {sceneData.Count} SCENE save states");
|
||||
}
|
||||
|
||||
// EXISTING: Collect data from ISaveParticipants (backward compatibility)
|
||||
foreach (var kvp in participants.ToList())
|
||||
{
|
||||
string saveId = kvp.Key;
|
||||
@@ -407,13 +640,8 @@ namespace Core.SaveLoad
|
||||
try
|
||||
{
|
||||
string serializedState = participant.SerializeState();
|
||||
currentSaveData.participantStates.Add(new ParticipantStateEntry
|
||||
{
|
||||
saveId = saveId,
|
||||
serializedState = serializedState
|
||||
});
|
||||
savedCount++;
|
||||
Logging.Debug($"[SaveLoadManager] Captured state for participant: {saveId}");
|
||||
allNewData[saveId] = serializedState;
|
||||
Logging.Debug($"[SaveLoadManager] Captured state for ISaveParticipant: {saveId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -421,7 +649,28 @@ namespace Core.SaveLoad
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Captured state from {savedCount} participants");
|
||||
// Update existing entries or add new ones (preserves data from unloaded scenes)
|
||||
foreach (var kvp in allNewData)
|
||||
{
|
||||
var existingEntry = currentSaveData.participantStates.Find(e => e.saveId == kvp.Key);
|
||||
if (existingEntry != null)
|
||||
{
|
||||
// Update existing entry
|
||||
existingEntry.serializedState = kvp.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new entry
|
||||
currentSaveData.participantStates.Add(new ParticipantStateEntry
|
||||
{
|
||||
saveId = kvp.Key,
|
||||
serializedState = kvp.Value
|
||||
});
|
||||
}
|
||||
savedCount++;
|
||||
}
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Captured state from {savedCount} total participants");
|
||||
|
||||
|
||||
json = JsonUtility.ToJson(currentSaveData, true);
|
||||
@@ -468,7 +717,7 @@ namespace Core.SaveLoad
|
||||
{
|
||||
IsSaving = false;
|
||||
OnSaveCompleted?.Invoke(slot);
|
||||
Debug.Log($"[SaveLoadManager] Save completed for slot '{slot}'");
|
||||
Logging.Debug($"[SaveLoadManager] Save completed for slot '{slot}'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +789,12 @@ namespace Core.SaveLoad
|
||||
// Restore state for any already-registered participants
|
||||
RestoreAllParticipantStates();
|
||||
|
||||
// NEW: Broadcast global load completed event (ONCE, on boot)
|
||||
if (Lifecycle.LifecycleManager.Instance != null)
|
||||
{
|
||||
Lifecycle.LifecycleManager.Instance.BroadcastGlobalLoadCompleted();
|
||||
}
|
||||
|
||||
OnLoadCompleted?.Invoke(slot);
|
||||
Logging.Debug($"[SaveLoadManager] Load completed for slot '{slot}'");
|
||||
}
|
||||
|
||||
148
Assets/Scripts/Core/SaveablePlayableDirector.cs
Normal file
148
Assets/Scripts/Core/SaveablePlayableDirector.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using Core.Lifecycle;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Saveable data for PlayableDirector state
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class PlayableDirectorSaveData
|
||||
{
|
||||
public bool wasPlayed; // Has the timeline been played?
|
||||
public bool wasCompleted; // Did it complete playback?
|
||||
public double playbackTime; // Current playback position
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes a PlayableDirector (Timeline) saveable.
|
||||
/// On load, if the timeline was completed, it seeks to the end to ensure
|
||||
/// all timeline-activated objects are in their final state.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(PlayableDirector))]
|
||||
public class SaveablePlayableDirector : ManagedBehaviour
|
||||
{
|
||||
private PlayableDirector _director;
|
||||
private bool _hasPlayed = false;
|
||||
private bool _hasCompleted = false;
|
||||
|
||||
// Enable save/load participation
|
||||
public override bool AutoRegisterForSave => true;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_director = GetComponent<PlayableDirector>();
|
||||
if (_director != null)
|
||||
{
|
||||
_director.stopped += OnDirectorStopped;
|
||||
_director.played += OnDirectorPlayed;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
|
||||
if (_director != null)
|
||||
{
|
||||
_director.stopped -= OnDirectorStopped;
|
||||
_director.played -= OnDirectorPlayed;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDirectorPlayed(PlayableDirector director)
|
||||
{
|
||||
_hasPlayed = true;
|
||||
}
|
||||
|
||||
private void OnDirectorStopped(PlayableDirector director)
|
||||
{
|
||||
_hasCompleted = true;
|
||||
}
|
||||
|
||||
#region Save/Load Implementation
|
||||
|
||||
protected override string OnSceneSaveRequested()
|
||||
{
|
||||
var saveData = new PlayableDirectorSaveData
|
||||
{
|
||||
wasPlayed = _hasPlayed,
|
||||
wasCompleted = _hasCompleted,
|
||||
playbackTime = _director != null ? _director.time : 0
|
||||
};
|
||||
|
||||
return JsonUtility.ToJson(saveData);
|
||||
}
|
||||
|
||||
protected override void OnSceneRestoreRequested(string serializedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
Logging.Warning($"[SaveablePlayableDirector] No save data to restore for {gameObject.name}");
|
||||
return;
|
||||
}
|
||||
|
||||
var saveData = JsonUtility.FromJson<PlayableDirectorSaveData>(serializedData);
|
||||
if (saveData == null || _director == null)
|
||||
return;
|
||||
|
||||
_hasPlayed = saveData.wasPlayed;
|
||||
_hasCompleted = saveData.wasCompleted;
|
||||
|
||||
if (_hasCompleted)
|
||||
{
|
||||
// Seek to the end of the timeline to apply all final states
|
||||
// This ensures objects activated/deactivated by the timeline are in correct state
|
||||
_director.time = _director.duration;
|
||||
_director.Evaluate(); // Force evaluation to apply the state
|
||||
|
||||
Logging.Debug($"[SaveablePlayableDirector] Restored completed timeline '{gameObject.name}' - seeked to end");
|
||||
}
|
||||
else if (_hasPlayed && saveData.playbackTime > 0)
|
||||
{
|
||||
// If it was playing but not completed, restore the playback position
|
||||
_director.time = saveData.playbackTime;
|
||||
_director.Evaluate();
|
||||
|
||||
Logging.Debug($"[SaveablePlayableDirector] Restored timeline '{gameObject.name}' at time {saveData.playbackTime}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Timeline hasn't been played yet, ensure it's at the start
|
||||
_director.time = 0;
|
||||
_director.Evaluate();
|
||||
|
||||
Logging.Debug($"[SaveablePlayableDirector] Timeline '{gameObject.name}' not yet played - at start");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
|
||||
/// <summary>
|
||||
/// Check if this timeline has been played
|
||||
/// </summary>
|
||||
public bool HasPlayed => _hasPlayed;
|
||||
|
||||
/// <summary>
|
||||
/// Check if this timeline completed playback
|
||||
/// </summary>
|
||||
public bool HasCompleted => _hasCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// Manually mark the timeline as completed (useful for triggering completion via code)
|
||||
/// </summary>
|
||||
public void MarkAsCompleted()
|
||||
{
|
||||
_hasCompleted = true;
|
||||
_hasPlayed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Core/SaveablePlayableDirector.cs.meta
Normal file
3
Assets/Scripts/Core/SaveablePlayableDirector.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5c5614fc04140cb81e5bda7451f7b14
|
||||
timeCreated: 1762360145
|
||||
@@ -2,17 +2,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using AppleHills.Core.Settings;
|
||||
using Core.Lifecycle;
|
||||
using Core.SaveLoad;
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Bootstrap;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton service for loading and unloading Unity scenes asynchronously, with events for progress and completion.
|
||||
/// </summary>
|
||||
public class SceneManagerService : MonoBehaviour
|
||||
public class SceneManagerService : ManagedBehaviour
|
||||
{
|
||||
private LoadingScreenController _loadingScreen;
|
||||
private static SceneManagerService _instance;
|
||||
@@ -23,29 +24,39 @@ namespace Core
|
||||
public static SceneManagerService Instance => _instance;
|
||||
|
||||
// Events for scene lifecycle
|
||||
// NOTE: Most components should use lifecycle hooks (OnSceneReady, OnSceneUnloading)
|
||||
// instead of subscribing to these events. Events are primarily for orchestration.
|
||||
|
||||
/// <summary>
|
||||
/// Fired when a scene starts loading. Used by loading screen orchestration.
|
||||
/// </summary>
|
||||
public event Action<string> SceneLoadStarted;
|
||||
public event Action<string, float> SceneLoadProgress;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when a scene finishes loading.
|
||||
/// Used by loading screen orchestration and cross-scene components (e.g., PauseMenu).
|
||||
/// For component initialization, use OnSceneReady() lifecycle hook instead.
|
||||
/// </summary>
|
||||
public event Action<string> SceneLoadCompleted;
|
||||
public event Action<string> SceneUnloadStarted;
|
||||
public event Action<string, float> SceneUnloadProgress;
|
||||
public event Action<string> SceneUnloadCompleted;
|
||||
|
||||
private readonly Dictionary<string, AsyncOperation> _activeLoads = new();
|
||||
private readonly Dictionary<string, AsyncOperation> _activeUnloads = new();
|
||||
private LogVerbosity _logVerbosity = LogVerbosity.Debug;
|
||||
private const string BootstrapSceneName = "BootstrapScene";
|
||||
|
||||
void Awake()
|
||||
// ManagedBehaviour configuration
|
||||
public override int ManagedAwakePriority => 15; // Core infrastructure, after GameManager
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
// DontDestroyOnLoad(gameObject);
|
||||
|
||||
// Initialize current scene tracking immediately in Awake
|
||||
// Initialize current scene tracking - critical for scene management
|
||||
InitializeCurrentSceneTracking();
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
|
||||
// Ensure BootstrapScene is loaded at startup
|
||||
var bootstrap = SceneManager.GetSceneByName(BootstrapSceneName);
|
||||
if (!bootstrap.isLoaded)
|
||||
@@ -54,9 +65,17 @@ namespace Core
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// Set up loading screen reference and events
|
||||
// This must happen in ManagedAwake because LoadingScreenController instance needs to be set first
|
||||
_loadingScreen = LoadingScreenController.Instance;
|
||||
SetupLoadingScreenEvents();
|
||||
|
||||
// Load verbosity settings
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
||||
|
||||
LogDebugMessage($"SceneManagerService initialized, current scene is: {CurrentGameplayScene}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,17 +108,6 @@ namespace Core
|
||||
LogDebugMessage($"No valid active scene, defaulting to: {CurrentGameplayScene}");
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Set up loading screen reference and events after boot is complete
|
||||
_loadingScreen = LoadingScreenController.Instance;
|
||||
|
||||
// Set up loading screen event handlers if available
|
||||
SetupLoadingScreenEvents();
|
||||
|
||||
LogDebugMessage($"Post-boot initialization complete, current scene is: {CurrentGameplayScene}");
|
||||
}
|
||||
|
||||
private void SetupLoadingScreenEvents()
|
||||
{
|
||||
@@ -122,7 +130,6 @@ namespace Core
|
||||
while (!op.isDone)
|
||||
{
|
||||
progress?.Report(op.progress);
|
||||
SceneLoadProgress?.Invoke(sceneName, op.progress);
|
||||
await Task.Yield();
|
||||
}
|
||||
_activeLoads.Remove(sceneName);
|
||||
@@ -142,17 +149,15 @@ namespace Core
|
||||
Logging.Warning($"[SceneManagerService] Attempted to unload scene '{sceneName}', but it is not loaded.");
|
||||
return;
|
||||
}
|
||||
SceneUnloadStarted?.Invoke(sceneName);
|
||||
|
||||
var op = SceneManager.UnloadSceneAsync(sceneName);
|
||||
_activeUnloads[sceneName] = op;
|
||||
while (!op.isDone)
|
||||
{
|
||||
progress?.Report(op.progress);
|
||||
SceneUnloadProgress?.Invoke(sceneName, op.progress);
|
||||
await Task.Yield();
|
||||
}
|
||||
_activeUnloads.Remove(sceneName);
|
||||
SceneUnloadCompleted?.Invoke(sceneName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -230,7 +235,6 @@ namespace Core
|
||||
var op = SceneManager.UnloadSceneAsync(name);
|
||||
_activeUnloads[name] = op;
|
||||
ops.Add(op);
|
||||
SceneUnloadStarted?.Invoke(name);
|
||||
}
|
||||
|
||||
while (done < total)
|
||||
@@ -251,7 +255,6 @@ namespace Core
|
||||
foreach (var name in sceneNames)
|
||||
{
|
||||
_activeUnloads.Remove(name);
|
||||
SceneUnloadCompleted?.Invoke(name);
|
||||
}
|
||||
|
||||
// Hide loading screen after all scenes are unloaded
|
||||
@@ -280,9 +283,9 @@ namespace Core
|
||||
// Tracks the currently loaded gameplay scene (not persistent/bootstrapper)
|
||||
public string CurrentGameplayScene { get; set; } = "AppleHillsOverworld";
|
||||
|
||||
public async Task ReloadCurrentScene(IProgress<float> progress = null, bool autoHideLoadingScreen = true)
|
||||
public async Task ReloadCurrentScene(IProgress<float> progress = null, bool autoHideLoadingScreen = true, bool skipSave = false)
|
||||
{
|
||||
await SwitchSceneAsync(CurrentGameplayScene, progress, autoHideLoadingScreen);
|
||||
await SwitchSceneAsync(CurrentGameplayScene, progress, autoHideLoadingScreen, skipSave);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -291,15 +294,45 @@ namespace Core
|
||||
/// <param name="newSceneName">Name of the scene to load</param>
|
||||
/// <param name="progress">Optional progress reporter</param>
|
||||
/// <param name="autoHideLoadingScreen">Whether to automatically hide the loading screen when complete. If false, caller must hide it manually.</param>
|
||||
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null, bool autoHideLoadingScreen = true)
|
||||
/// <param name="skipSave">If true, skips saving scene data during transition. Useful for level restart to prevent re-saving cleared data.</param>
|
||||
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null, bool autoHideLoadingScreen = true, bool skipSave = false)
|
||||
{
|
||||
// Show loading screen at the start (whether using auto-hide or not)
|
||||
if (_loadingScreen != null && !_loadingScreen.IsActive)
|
||||
string oldSceneName = CurrentGameplayScene;
|
||||
|
||||
// PHASE 1: Show loading screen at the start
|
||||
// Use explicit progress provider to combine unload + load progress
|
||||
if (_loadingScreen != null)
|
||||
{
|
||||
_loadingScreen.ShowLoadingScreen();
|
||||
_loadingScreen.ShowLoadingScreen(() => GetAggregateLoadProgress());
|
||||
}
|
||||
|
||||
// Remove all AstarPath (A* Pathfinder) singletons before loading the new scene
|
||||
// PHASE 2: Broadcast scene unloading - notify components to cleanup
|
||||
LogDebugMessage($"Broadcasting OnSceneUnloading for: {oldSceneName}");
|
||||
LifecycleManager.Instance?.BroadcastSceneUnloading(oldSceneName);
|
||||
|
||||
// PHASE 3: Save scene-specific data via SaveLoadManager (unless skipSave is true)
|
||||
if (!skipSave && SaveLoadManager.Instance != null)
|
||||
{
|
||||
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
||||
if (debugSettings.useSaveLoadSystem)
|
||||
{
|
||||
LogDebugMessage($"Saving scene data for: {oldSceneName}");
|
||||
SaveLoadManager.Instance.SaveSceneData();
|
||||
}
|
||||
}
|
||||
else if (skipSave)
|
||||
{
|
||||
LogDebugMessage($"Skipping save for: {oldSceneName} (skipSave=true)");
|
||||
}
|
||||
|
||||
// PHASE 4: Clear PuzzleManager state before scene transition
|
||||
if (PuzzleS.PuzzleManager.Instance != null)
|
||||
{
|
||||
LogDebugMessage($"Clearing puzzle state before scene transition");
|
||||
PuzzleS.PuzzleManager.Instance.ClearPuzzleState();
|
||||
}
|
||||
|
||||
// PHASE 5: Remove all AstarPath (A* Pathfinder) singletons before loading the new scene
|
||||
var astarPaths = FindObjectsByType<AstarPath>(FindObjectsSortMode.None);
|
||||
foreach (var astar in astarPaths)
|
||||
{
|
||||
@@ -308,31 +341,57 @@ namespace Core
|
||||
else
|
||||
DestroyImmediate(astar.gameObject);
|
||||
}
|
||||
// Unload previous gameplay scene (if not BootstrapScene and not same as new)
|
||||
if (!string.IsNullOrEmpty(CurrentGameplayScene)&& CurrentGameplayScene != BootstrapSceneName)
|
||||
|
||||
// PHASE 6: Unload previous gameplay scene (Unity will call OnDestroy → OnManagedDestroy)
|
||||
if (!string.IsNullOrEmpty(oldSceneName) && oldSceneName != BootstrapSceneName)
|
||||
{
|
||||
var prevScene = SceneManager.GetSceneByName(CurrentGameplayScene);
|
||||
var prevScene = SceneManager.GetSceneByName(oldSceneName);
|
||||
if (prevScene.isLoaded)
|
||||
{
|
||||
await UnloadSceneAsync(CurrentGameplayScene);
|
||||
await UnloadSceneAsync(oldSceneName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[SceneManagerService] Previous scene '{CurrentGameplayScene}' is not loaded, skipping unload.");
|
||||
Logging.Warning($"[SceneManagerService] Previous scene '{oldSceneName}' is not loaded, skipping unload.");
|
||||
}
|
||||
}
|
||||
// Ensure BootstrapScene is loaded before loading new scene
|
||||
|
||||
// PHASE 7: Ensure BootstrapScene is loaded before loading new scene
|
||||
var bootstrap = SceneManager.GetSceneByName(BootstrapSceneName);
|
||||
if (!bootstrap.isLoaded)
|
||||
{
|
||||
SceneManager.LoadScene(BootstrapSceneName, LoadSceneMode.Additive);
|
||||
}
|
||||
// Load new gameplay scene
|
||||
|
||||
// PHASE 8: Begin scene loading mode - enables priority-ordered component initialization
|
||||
LogDebugMessage($"Beginning scene load for: {newSceneName}");
|
||||
LifecycleManager.Instance?.BeginSceneLoad(newSceneName);
|
||||
|
||||
// PHASE 9: Load new gameplay scene
|
||||
await LoadSceneAsync(newSceneName, progress);
|
||||
// Update tracker
|
||||
CurrentGameplayScene = newSceneName;
|
||||
|
||||
// Only hide the loading screen if autoHideLoadingScreen is true
|
||||
// PHASE 10: Broadcast scene ready - processes batched components in priority order, then calls OnSceneReady
|
||||
LogDebugMessage($"Broadcasting OnSceneReady for: {newSceneName}");
|
||||
LifecycleManager.Instance?.BroadcastSceneReady(newSceneName);
|
||||
|
||||
// PHASE 11: Restore scene-specific data via SaveLoadManager
|
||||
if (!skipSave && SaveLoadManager.Instance != null)
|
||||
{
|
||||
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
||||
if (debugSettings.useSaveLoadSystem)
|
||||
{
|
||||
LogDebugMessage($"Restoring scene data for: {newSceneName}");
|
||||
SaveLoadManager.Instance.RestoreSceneData();
|
||||
}
|
||||
}
|
||||
else if (skipSave)
|
||||
{
|
||||
SaveLoadManager.Instance.RestoreSceneData();
|
||||
LogDebugMessage($"Skipping restore for: {newSceneName} (skipSave=true)");
|
||||
}
|
||||
|
||||
// PHASE 12: Only hide the loading screen if autoHideLoadingScreen is true
|
||||
if (autoHideLoadingScreen && _loadingScreen != null)
|
||||
{
|
||||
_loadingScreen.HideLoadingScreen();
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using AppleHills.Core.Settings;
|
||||
using Bootstrap;
|
||||
using Input;
|
||||
using Core.Lifecycle;
|
||||
using Settings;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public class SceneOrientationEnforcer : MonoBehaviour
|
||||
public class SceneOrientationEnforcer : ManagedBehaviour
|
||||
{
|
||||
// Singleton instance
|
||||
private static SceneOrientationEnforcer _instance;
|
||||
@@ -20,40 +18,56 @@ namespace Core
|
||||
public GameObject orientationPromptPrefab;
|
||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||
|
||||
void Awake()
|
||||
// ManagedBehaviour configuration
|
||||
public override int ManagedAwakePriority => 70; // Platform-specific utility
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
// Load verbosity settings early (GameManager sets up settings in its Awake)
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
||||
|
||||
LogDebugMessage("Initialized");
|
||||
}
|
||||
|
||||
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
|
||||
// When playing in the editor, manually invoke OnSceneLoaded for the currently active scene
|
||||
// When playing in the editor, manually invoke orientation check for the currently active scene
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single);
|
||||
HandleSceneOrientation(SceneManager.GetActiveScene().name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Start()
|
||||
protected override void OnSceneReady()
|
||||
{
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Initialize any dependencies that require other services to be ready
|
||||
LogDebugMessage("Post-boot initialization complete");
|
||||
|
||||
// Subscribe to sceneLoaded event
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
// Handle orientation when scene is ready (initial scene)
|
||||
// Note: This fires for the scene that just loaded, LifecycleManager tracks which scene
|
||||
string sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
|
||||
HandleSceneOrientation(sceneName);
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
private void OnSceneLoadCompleted(string sceneName)
|
||||
{
|
||||
// Enforce orientation every time a scene is loaded via SceneManagerService
|
||||
HandleSceneOrientation(sceneName);
|
||||
}
|
||||
|
||||
private void HandleSceneOrientation(string sceneName)
|
||||
{
|
||||
// Determine desired orientation for this scene
|
||||
string sceneName = scene.name;
|
||||
ScreenOrientationRequirement requirement = ScreenOrientationRequirement.NotApplicable;
|
||||
|
||||
if (sceneName.ToLower().Contains("bootstrap"))
|
||||
@@ -91,9 +105,15 @@ namespace Core
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
// Unsubscribe from events to prevent memory leaks
|
||||
if (SceneManagerService.Instance != null)
|
||||
{
|
||||
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
||||
}
|
||||
|
||||
base.OnDestroy(); // Important: call base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Interactions;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
@@ -88,5 +89,31 @@ namespace AppleHills.Core.Settings
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AppleHills.Core.Settings
|
||||
// Methods to query item configurations
|
||||
CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2);
|
||||
SlotItemConfig GetSlotItemConfig(PickupItemData slotItem);
|
||||
GameObject FindPickupPrefabByItemId(string itemId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Pathfinding;
|
||||
|
||||
// TODO: Remove movement based logic
|
||||
public class AnneLiseBehaviour : MonoBehaviour
|
||||
{
|
||||
[SerializeField] public float moveSpeed;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
// TODO: Remove this
|
||||
public class LureSpot : MonoBehaviour
|
||||
{
|
||||
[SerializeField] public GameObject luredBird;
|
||||
|
||||
@@ -2,6 +2,7 @@ using UnityEngine;
|
||||
using Pixelplacement;
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
public class PicnicBehaviour : MonoBehaviour
|
||||
@@ -12,7 +13,7 @@ public class PicnicBehaviour : MonoBehaviour
|
||||
public float getFlirtyMin = 1f;
|
||||
public float getFlirtyMax = 3f;
|
||||
|
||||
private StateMachine stateMachine;
|
||||
private AppleMachine stateMachine;
|
||||
private Animator animator;
|
||||
|
||||
[Header("The FakeChocolate to destroy!")]
|
||||
@@ -32,7 +33,7 @@ public class PicnicBehaviour : MonoBehaviour
|
||||
|
||||
void Awake()
|
||||
{
|
||||
stateMachine = GetComponent<StateMachine>();
|
||||
stateMachine = GetComponent<AppleMachine>();
|
||||
animator = GetComponent<Animator>();
|
||||
_audioSource = GetComponent<AppleAudioSource>();
|
||||
}
|
||||
|
||||
@@ -97,90 +97,7 @@ AnimationClip:
|
||||
- time: 1.5833334
|
||||
value: {fileID: -1414182512, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
|
||||
attribute: m_Sprite
|
||||
path: SoundBird
|
||||
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
|
||||
path:
|
||||
classID: 212
|
||||
script: {fileID: 0}
|
||||
flags: 2
|
||||
@@ -192,16 +109,7 @@ AnimationClip:
|
||||
m_ClipBindingConstant:
|
||||
genericBindings:
|
||||
- serializedVersion: 2
|
||||
path: 1707885837
|
||||
attribute: 0
|
||||
script: {fileID: 0}
|
||||
typeID: 212
|
||||
customType: 23
|
||||
isPPtrCurve: 1
|
||||
isIntCurve: 0
|
||||
isSerializeReferenceCurve: 0
|
||||
- serializedVersion: 2
|
||||
path: 631576921
|
||||
path: 0
|
||||
attribute: 0
|
||||
script: {fileID: 0}
|
||||
typeID: 212
|
||||
@@ -248,44 +156,6 @@ AnimationClip:
|
||||
- {fileID: 1990407029, guid: 9d1670b18fc5fa8459596f1ddd4a4bd7, type: 3}
|
||||
- {fileID: 1094948637, 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:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Pixelplacement;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -8,7 +9,7 @@ public class SoundGenerator : MonoBehaviour
|
||||
[SerializeField] private Sprite exitSprite;
|
||||
[SerializeField] private AudioClip enterSound;
|
||||
[SerializeField] private AppleAudioSource audioSource;
|
||||
[SerializeField] private StateMachine soundBirdSMRef;
|
||||
[SerializeField] private AppleMachine soundBirdSMRef;
|
||||
[SerializeField] private soundBird_CanFly soundbirdHearingCheck;
|
||||
|
||||
private bool playerInside = false;
|
||||
@@ -37,7 +38,7 @@ public class SoundGenerator : MonoBehaviour
|
||||
{
|
||||
audioSource.audioSource.PlayOneShot(enterSound);
|
||||
}
|
||||
if (soundBirdSMRef != null && soundBirdSMRef.currentState.name == "SoundBird" && soundbirdHearingCheck.canFly == true)
|
||||
if (soundBirdSMRef != null && soundBirdSMRef.currentState.name.ToLower().Contains("soundbird_slot") && soundbirdHearingCheck.canFly == true)
|
||||
{
|
||||
soundBirdSMRef.ChangeState("SoundBirdTakeoff");
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using UnityEngine;
|
||||
using Unity.Cinemachine;
|
||||
using System.Collections;
|
||||
using Core.SaveLoad;
|
||||
using Pixelplacement;
|
||||
|
||||
public class cameraSwitcher : MonoBehaviour
|
||||
@@ -12,7 +13,7 @@ public class cameraSwitcher : MonoBehaviour
|
||||
[SerializeField] private float transitionDuration = 0.5f; // Duration of the transition
|
||||
[SerializeField] private soundBird_FlyingBehaviour flyingBehaviour;
|
||||
[SerializeField] private soundBird_TakeOffBehaviour takeOffBehaviour; // New reference
|
||||
[SerializeField] private StateMachine birdStateMachine;
|
||||
[SerializeField] private AppleMachine birdStateMachine;
|
||||
|
||||
private int playerInsideCount = 0;
|
||||
private Coroutine zoomCoroutine;
|
||||
@@ -32,6 +33,9 @@ public class cameraSwitcher : MonoBehaviour
|
||||
|
||||
private void OnTriggerExit2D(Collider2D other)
|
||||
{
|
||||
if (!gameObject.activeInHierarchy)
|
||||
return;
|
||||
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
playerInsideCount--;
|
||||
|
||||
@@ -1,23 +1,52 @@
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
using Core.Lifecycle;
|
||||
|
||||
public class soundBird_CanFly : MonoBehaviour
|
||||
[System.Serializable]
|
||||
public class SoundBirdSaveData
|
||||
{
|
||||
public bool canFly;
|
||||
}
|
||||
|
||||
public class soundBird_CanFly : ManagedBehaviour
|
||||
{
|
||||
public bool canFly = true;
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Enable save/load participation
|
||||
public override bool AutoRegisterForSave => true;
|
||||
|
||||
public void birdCanHear(bool canhear)
|
||||
{
|
||||
if (canhear)
|
||||
canFly = canhear;
|
||||
}
|
||||
|
||||
#region Save/Load Implementation
|
||||
|
||||
protected override string OnSceneSaveRequested()
|
||||
{
|
||||
var saveData = new SoundBirdSaveData
|
||||
{
|
||||
canFly = true;
|
||||
canFly = this.canFly
|
||||
};
|
||||
|
||||
return JsonUtility.ToJson(saveData);
|
||||
}
|
||||
|
||||
protected override void OnSceneRestoreRequested(string serializedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
Logging.Warning($"[soundBird_CanFly] No save data to restore for {gameObject.name}");
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
var saveData = JsonUtility.FromJson<SoundBirdSaveData>(serializedData);
|
||||
if (saveData != null)
|
||||
{
|
||||
canFly = false;
|
||||
canFly = saveData.canFly;
|
||||
Logging.Debug($"[soundBird_CanFly] Restored canFly state: {canFly}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Core.SaveLoad;
|
||||
using Pixelplacement;
|
||||
using Pixelplacement.TweenSystem;
|
||||
using UnityEngine;
|
||||
@@ -10,7 +11,7 @@ public class soundBird_FlyingBehaviour : MonoBehaviour
|
||||
public float flightDelay;
|
||||
public float cooldownTime;
|
||||
|
||||
private StateMachine stateMachine;
|
||||
private AppleMachine stateMachine;
|
||||
private Animator animator;
|
||||
private TweenBase objectTween;
|
||||
//private Coroutine cooldownCoroutine;
|
||||
@@ -21,7 +22,7 @@ public class soundBird_FlyingBehaviour : MonoBehaviour
|
||||
|
||||
void Awake()
|
||||
{
|
||||
stateMachine = GetComponentInParent<StateMachine>();
|
||||
stateMachine = GetComponentInParent<AppleMachine>();
|
||||
animator = GetComponentInParent<Animator>();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Core.SaveLoad;
|
||||
using Pixelplacement;
|
||||
using Pixelplacement.TweenSystem;
|
||||
using UnityEngine;
|
||||
@@ -9,7 +10,7 @@ public class soundBird_LandingBehaviour1 : MonoBehaviour
|
||||
public float flightDuration;
|
||||
public float flightDelay;
|
||||
public soundBird_FlyingBehaviour flyingBehaviour;
|
||||
private StateMachine stateMachine;
|
||||
private AppleMachine stateMachine;
|
||||
private Animator animator;
|
||||
private TweenBase objectTween;
|
||||
|
||||
@@ -18,7 +19,7 @@ public class soundBird_LandingBehaviour1 : MonoBehaviour
|
||||
|
||||
void Awake()
|
||||
{
|
||||
stateMachine = GetComponentInParent<StateMachine>();
|
||||
stateMachine = GetComponentInParent<AppleMachine>();
|
||||
animator = GetComponentInParent<Animator>();
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ public class soundBird_LandingBehaviour1 : MonoBehaviour
|
||||
if (stateMachine != null)
|
||||
{
|
||||
animator.SetBool("isScared", false);
|
||||
stateMachine.ChangeState("SoundBird"); // Change to the desired state name
|
||||
stateMachine.ChangeState(0); // Change to the desired state name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Core.SaveLoad;
|
||||
using Pixelplacement;
|
||||
using Pixelplacement.TweenSystem;
|
||||
using UnityEngine;
|
||||
@@ -9,7 +10,7 @@ public class soundBird_TakeOffBehaviour : MonoBehaviour
|
||||
public Transform SoundBirdObject;
|
||||
public float flightDuration;
|
||||
public float flightDelay;
|
||||
private StateMachine stateMachine;
|
||||
private AppleMachine stateMachine;
|
||||
private Animator animator;
|
||||
private TweenBase objectTween;
|
||||
public soundBird_FlyingBehaviour flyingBehaviour;
|
||||
@@ -18,7 +19,7 @@ public class soundBird_TakeOffBehaviour : MonoBehaviour
|
||||
|
||||
void Awake()
|
||||
{
|
||||
stateMachine = GetComponentInParent<StateMachine>();
|
||||
stateMachine = GetComponentInParent<AppleMachine>();
|
||||
animator = GetComponentInParent<Animator>();
|
||||
}
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace AppleHills.Data.CardSystem
|
||||
|
||||
public enum CardZone
|
||||
{
|
||||
NotApplicable,
|
||||
AppleHills,
|
||||
Quarry,
|
||||
CementFactory,
|
||||
|
||||
@@ -2,23 +2,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AppleHills.Data.CardSystem;
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Core.Lifecycle;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Data.CardSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the player's card collection, booster packs, and related operations.
|
||||
/// Uses a singleton pattern for global access.
|
||||
/// Implements ISaveParticipant to integrate with the save/load system.
|
||||
/// Manages the card collection system for the game.
|
||||
/// Handles unlocking cards, tracking collections, and integrating with the save/load system.
|
||||
/// </summary>
|
||||
public class CardSystemManager : MonoBehaviour, ISaveParticipant
|
||||
public class CardSystemManager : ManagedBehaviour
|
||||
{
|
||||
private static CardSystemManager _instance;
|
||||
public static CardSystemManager Instance => _instance;
|
||||
|
||||
// Save system configuration
|
||||
public override bool AutoRegisterForSave => true;
|
||||
public override string SaveId => "CardSystemManager";
|
||||
|
||||
|
||||
[Header("Card Collection")]
|
||||
[SerializeField] private List<CardDefinition> availableCards = new List<CardDefinition>();
|
||||
|
||||
@@ -30,7 +34,8 @@ namespace Data.CardSystem
|
||||
private HashSet<string> _placedInAlbumCardIds = new HashSet<string>();
|
||||
|
||||
// Dictionary to quickly look up card definitions by ID
|
||||
private Dictionary<string, CardDefinition> _definitionLookup = new Dictionary<string, CardDefinition>();
|
||||
private Dictionary<string, CardDefinition> _definitionLookup;
|
||||
private bool _lookupInitialized = false;
|
||||
|
||||
// Event callbacks using System.Action
|
||||
public event Action<List<CardData>> OnBoosterOpened;
|
||||
@@ -40,20 +45,22 @@ namespace Data.CardSystem
|
||||
public event Action<CardData> OnPendingCardAdded;
|
||||
public event Action<CardData> OnCardPlacedInAlbum;
|
||||
|
||||
private void Awake()
|
||||
public override int ManagedAwakePriority => 60; // Data systems
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
|
||||
// Load card definitions from Addressables, then register with save system
|
||||
LoadCardDefinitionsFromAddressables();
|
||||
|
||||
Logging.Debug("[CardSystemManager] Post-boot initialization complete");
|
||||
}
|
||||
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
Logging.Debug("[CardSystemManager] Initialized");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,17 +95,6 @@ namespace Data.CardSystem
|
||||
BuildDefinitionLookup();
|
||||
|
||||
Logging.Debug($"[CardSystemManager] Loaded {availableCards.Count} card definitions from Addressables");
|
||||
|
||||
// NOW register with save/load system (definitions are ready for state restoration)
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.RegisterParticipant(this);
|
||||
Logging.Debug("[CardSystemManager] Registered with SaveLoadManager after definitions loaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[CardSystemManager] SaveLoadManager not available for registration");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -106,20 +102,17 @@ namespace Data.CardSystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// Unregister from save/load system
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.UnregisterParticipant(GetSaveId());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a lookup dictionary for quick access to card definitions by ID
|
||||
/// </summary>
|
||||
private void BuildDefinitionLookup()
|
||||
{
|
||||
if (_definitionLookup == null)
|
||||
{
|
||||
_definitionLookup = new Dictionary<string, CardDefinition>();
|
||||
}
|
||||
|
||||
_definitionLookup.Clear();
|
||||
|
||||
foreach (var cardDef in availableCards)
|
||||
@@ -139,6 +132,8 @@ namespace Data.CardSystem
|
||||
cardData.SetDefinition(def);
|
||||
}
|
||||
}
|
||||
|
||||
_lookupInitialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -647,10 +642,16 @@ namespace Data.CardSystem
|
||||
/// <summary>
|
||||
/// Apply a previously saved snapshot to the runtime inventory
|
||||
/// </summary>
|
||||
public void ApplyCardCollectionState(CardCollectionState state)
|
||||
public async void ApplyCardCollectionState(CardCollectionState state)
|
||||
{
|
||||
if (state == null) return;
|
||||
|
||||
// Wait for lookup to be initialized before loading
|
||||
while (!_lookupInitialized)
|
||||
{
|
||||
await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
playerInventory.ClearAllCards();
|
||||
_pendingRevealCards.Clear();
|
||||
_placedInAlbumCardIds.Clear();
|
||||
@@ -701,42 +702,35 @@ namespace Data.CardSystem
|
||||
}
|
||||
}
|
||||
|
||||
#region ISaveParticipant Implementation
|
||||
|
||||
private bool hasBeenRestored;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this participant has already had its state restored.
|
||||
/// Clears all card collection data - inventory, pending cards, boosters, and placement tracking
|
||||
/// Used for dev reset functionality
|
||||
/// </summary>
|
||||
public bool HasBeenRestored => hasBeenRestored;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the unique save ID for the CardSystemManager.
|
||||
/// Since this is a singleton global system, the ID is constant.
|
||||
/// </summary>
|
||||
public string GetSaveId()
|
||||
public void ClearAllCollectionData()
|
||||
{
|
||||
return "CardSystemManager";
|
||||
playerInventory.ClearAllCards();
|
||||
playerInventory.BoosterPackCount = 0;
|
||||
_pendingRevealCards.Clear();
|
||||
_placedInAlbumCardIds.Clear();
|
||||
|
||||
OnBoosterCountChanged?.Invoke(0);
|
||||
|
||||
Logging.Debug("[CardSystemManager] Cleared all collection data (inventory, boosters, pending, placement tracking)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the current card collection state to JSON.
|
||||
/// </summary>
|
||||
public string SerializeState()
|
||||
#region Save/Load Lifecycle Hooks
|
||||
|
||||
protected override string OnGlobalSaveRequested()
|
||||
{
|
||||
var state = ExportCardCollectionState();
|
||||
return JsonUtility.ToJson(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores the card collection state from serialized JSON data.
|
||||
/// </summary>
|
||||
public void RestoreState(string serializedData)
|
||||
protected override void OnGlobalRestoreRequested(string serializedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
Logging.Debug("[CardSystemManager] No saved state to restore, using defaults");
|
||||
hasBeenRestored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -746,7 +740,6 @@ namespace Data.CardSystem
|
||||
if (state != null)
|
||||
{
|
||||
ApplyCardCollectionState(state);
|
||||
hasBeenRestored = true;
|
||||
Logging.Debug("[CardSystemManager] Successfully restored card collection state");
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Interactions;
|
||||
using UnityEngine;
|
||||
using PuzzleS;
|
||||
@@ -12,7 +12,7 @@ namespace Dialogue
|
||||
{
|
||||
[AddComponentMenu("AppleHills/Dialogue/Dialogue Component")]
|
||||
[RequireComponent(typeof(AppleAudioSource))]
|
||||
public class DialogueComponent : MonoBehaviour
|
||||
public class DialogueComponent : ManagedBehaviour
|
||||
{
|
||||
[SerializeField] private RuntimeDialogueGraph dialogueGraph;
|
||||
|
||||
@@ -35,7 +35,9 @@ namespace Dialogue
|
||||
public string CurrentSpeakerName => dialogueGraph?.speakerName;
|
||||
|
||||
|
||||
private void Start()
|
||||
public override int ManagedAwakePriority => 150; // Dialogue systems
|
||||
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// Get required components
|
||||
appleAudioSource = GetComponent<AppleAudioSource>();
|
||||
@@ -58,11 +60,6 @@ namespace Dialogue
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Register for global events
|
||||
PuzzleManager.Instance.OnStepCompleted += OnAnyPuzzleStepCompleted;
|
||||
ItemManager.Instance.OnItemPickedUp += OnAnyItemPickedUp;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic; // Added for List<ITouchInputConsumer>
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.SceneManagement;
|
||||
using AppleHills.Core.Settings;
|
||||
using Bootstrap;
|
||||
using Core; // Added for IInteractionSettings
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
|
||||
namespace Input
|
||||
{
|
||||
@@ -22,7 +21,7 @@ namespace Input
|
||||
/// Handles input events and dispatches them to the appropriate ITouchInputConsumer.
|
||||
/// Supports tap and hold/drag logic, with interactable delegation and debug logging.
|
||||
/// </summary>
|
||||
public class InputManager : MonoBehaviour
|
||||
public class InputManager : ManagedBehaviour
|
||||
{
|
||||
private const string UiActions = "UI";
|
||||
private const string GameActions = "PlayerTouch";
|
||||
@@ -51,33 +50,29 @@ namespace Input
|
||||
private bool isHoldActive;
|
||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||
|
||||
void Awake()
|
||||
public override int ManagedAwakePriority => 25; // Input infrastructure
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
base.Awake(); // CRITICAL: Register with LifecycleManager!
|
||||
|
||||
// Set instance immediately so it's available before OnManagedAwake() is called
|
||||
_instance = this;
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Load verbosity settings early
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().inputLogVerbosity;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Subscribe to scene load completed events now that boot is complete
|
||||
SceneManagerService.Instance.SceneLoadCompleted += SwitchInputOnSceneLoaded;
|
||||
|
||||
// Initialize settings reference
|
||||
// Initialize settings reference early (GameManager sets these up in its Awake)
|
||||
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||||
|
||||
// Set up PlayerInput component and actions - critical for input to work
|
||||
playerInput = GetComponent<PlayerInput>();
|
||||
if (playerInput == null)
|
||||
{
|
||||
Debug.LogError("[InputManager] InputManager requires a PlayerInput component attached to the same GameObject.");
|
||||
return;
|
||||
}
|
||||
|
||||
tapMoveAction = playerInput.actions.FindAction("TapMove", false);
|
||||
holdMoveAction = playerInput.actions.FindAction("HoldMove", false);
|
||||
positionAction = playerInput.actions.FindAction("TouchPosition", false);
|
||||
@@ -90,14 +85,39 @@ namespace Input
|
||||
holdMoveAction.canceled += OnHoldMoveCanceled;
|
||||
}
|
||||
|
||||
// Initialize input mode for current scene
|
||||
SwitchInputOnSceneLoaded(SceneManager.GetActiveScene().name);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
// Unsubscribe from SceneManagerService
|
||||
// Subscribe to scene load events from SceneManagerService
|
||||
// This must happen in ManagedAwake because SceneManagerService instance needs to be set first
|
||||
if (SceneManagerService.Instance != null)
|
||||
SceneManagerService.Instance.SceneLoadCompleted -= SwitchInputOnSceneLoaded;
|
||||
{
|
||||
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when any scene finishes loading. Restores input to GameAndUI mode.
|
||||
/// </summary>
|
||||
private void OnSceneLoadCompleted(string sceneName)
|
||||
{
|
||||
LogDebugMessage($"Scene loaded: {sceneName}, restoring input mode");
|
||||
SwitchInputOnSceneLoaded(sceneName);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
// Unsubscribe from SceneManagerService events
|
||||
if (SceneManagerService.Instance != null)
|
||||
{
|
||||
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
|
||||
}
|
||||
|
||||
base.OnDestroy();
|
||||
// Input action cleanup happens automatically
|
||||
}
|
||||
|
||||
private void SwitchInputOnSceneLoaded(string sceneName)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Pathfinding;
|
||||
using AppleHills.Core.Settings;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Core.SaveLoad;
|
||||
using Bootstrap;
|
||||
|
||||
namespace Input
|
||||
{
|
||||
@@ -21,7 +21,7 @@ namespace Input
|
||||
/// Handles player movement in response to tap and hold input events.
|
||||
/// Supports both direct and pathfinding movement modes, and provides event/callbacks for arrival/cancellation.
|
||||
/// </summary>
|
||||
public class PlayerTouchController : MonoBehaviour, ITouchInputConsumer, ISaveParticipant
|
||||
public class PlayerTouchController : ManagedBehaviour, ITouchInputConsumer
|
||||
{
|
||||
// --- Movement State ---
|
||||
private Vector3 targetPosition;
|
||||
@@ -67,10 +67,13 @@ namespace Input
|
||||
private bool interruptMoveTo;
|
||||
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
|
||||
|
||||
// Save system tracking
|
||||
private bool hasBeenRestored;
|
||||
|
||||
void Awake()
|
||||
// Save system configuration
|
||||
public override bool AutoRegisterForSave => true;
|
||||
// Scene-specific SaveId - each level has its own player state
|
||||
public override string SaveId => $"{gameObject.scene.name}/PlayerController";
|
||||
public override int ManagedAwakePriority => 100; // Player controller
|
||||
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
aiPath = GetComponent<AIPath>();
|
||||
artTransform = transform.Find("CharacterArt");
|
||||
@@ -87,39 +90,12 @@ namespace Input
|
||||
// Initialize settings reference using GetSettingsObject
|
||||
_settings = GameManager.GetSettingsObject<IPlayerFollowerSettings>();
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Set default input consumer
|
||||
InputManager.Instance?.SetDefaultConsumer(this);
|
||||
|
||||
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().inputLogVerbosity;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Register with save system after boot
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.RegisterParticipant(this);
|
||||
Logging.Debug("[PlayerTouchController] Registered with SaveLoadManager");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[PlayerTouchController] SaveLoadManager not available for registration");
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// Unregister from save system
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.UnregisterParticipant(GetSaveId());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles tap input. Always uses pathfinding to move to the tapped location.
|
||||
/// Cancels any in-progress MoveToAndNotify.
|
||||
@@ -457,16 +433,9 @@ namespace Input
|
||||
}
|
||||
}
|
||||
|
||||
#region ISaveParticipant Implementation
|
||||
#region Save/Load Lifecycle Hooks
|
||||
|
||||
public bool HasBeenRestored => hasBeenRestored;
|
||||
|
||||
public string GetSaveId()
|
||||
{
|
||||
return "PlayerController";
|
||||
}
|
||||
|
||||
public string SerializeState()
|
||||
protected override string OnSceneSaveRequested()
|
||||
{
|
||||
var saveData = new PlayerSaveData
|
||||
{
|
||||
@@ -476,12 +445,11 @@ namespace Input
|
||||
return JsonUtility.ToJson(saveData);
|
||||
}
|
||||
|
||||
public void RestoreState(string serializedData)
|
||||
protected override void OnSceneRestoreRequested(string serializedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
Logging.Debug("[PlayerTouchController] No saved state to restore");
|
||||
hasBeenRestored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -492,7 +460,6 @@ namespace Input
|
||||
{
|
||||
transform.position = saveData.worldPosition;
|
||||
transform.rotation = saveData.worldRotation;
|
||||
hasBeenRestored = true;
|
||||
Logging.Debug($"[PlayerTouchController] Restored position: {saveData.worldPosition}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
using System.Threading.Tasks;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
|
||||
namespace Interactions
|
||||
{
|
||||
@@ -20,7 +21,7 @@ namespace Interactions
|
||||
/// Base class for interactable objects that can respond to tap input events.
|
||||
/// Subclasses should override OnCharacterArrived() to implement interaction-specific logic.
|
||||
/// </summary>
|
||||
public class InteractableBase : MonoBehaviour, ITouchInputConsumer
|
||||
public class InteractableBase : ManagedBehaviour, ITouchInputConsumer
|
||||
{
|
||||
[Header("Interaction Settings")]
|
||||
public bool isOneTime;
|
||||
@@ -33,21 +34,16 @@ namespace Interactions
|
||||
public UnityEvent characterArrived;
|
||||
public UnityEvent<bool> interactionComplete;
|
||||
|
||||
// Helpers for managing interaction state
|
||||
private bool _interactionInProgress;
|
||||
protected PlayerTouchController _playerRef;
|
||||
protected FollowerController _followerController;
|
||||
private bool _isActive = true;
|
||||
private InteractionEventType _currentEventType;
|
||||
private PlayerTouchController playerRef;
|
||||
protected FollowerController FollowerController;
|
||||
private bool isActive = true;
|
||||
|
||||
// Action component system
|
||||
private List<InteractionActionBase> _registeredActions = new List<InteractionActionBase>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Subscribe to interactionComplete event
|
||||
interactionComplete.AddListener(OnInteractionComplete);
|
||||
}
|
||||
// ManagedBehaviour configuration
|
||||
public override int ManagedAwakePriority => 100; // Gameplay base classes
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Register an action component with this interactable
|
||||
@@ -73,14 +69,12 @@ namespace Interactions
|
||||
/// </summary>
|
||||
private async Task DispatchEventAsync(InteractionEventType eventType)
|
||||
{
|
||||
_currentEventType = eventType;
|
||||
|
||||
// Collect all tasks from actions that want to respond
|
||||
List<Task<bool>> tasks = new List<Task<bool>>();
|
||||
|
||||
foreach (var action in _registeredActions)
|
||||
{
|
||||
Task<bool> task = action.OnInteractionEvent(eventType, _playerRef, _followerController);
|
||||
Task<bool> task = action.OnInteractionEvent(eventType, playerRef, FollowerController);
|
||||
if (task != null)
|
||||
{
|
||||
tasks.Add(task);
|
||||
@@ -97,39 +91,178 @@ namespace Interactions
|
||||
|
||||
/// <summary>
|
||||
/// Handles tap input. Triggers interaction logic.
|
||||
/// Can be overridden for fully custom interaction logic.
|
||||
/// </summary>
|
||||
public void OnTap(Vector2 worldPosition)
|
||||
public virtual void OnTap(Vector2 worldPosition)
|
||||
{
|
||||
if (!_isActive)
|
||||
// 1. High-level validation
|
||||
if (!CanBeClicked())
|
||||
{
|
||||
Logging.Debug($"[Interactable] Is disabled!");
|
||||
return;
|
||||
return; // Silent failure
|
||||
}
|
||||
|
||||
Logging.Debug($"[Interactable] OnTap at {worldPosition} on {gameObject.name}");
|
||||
|
||||
// Start the interaction process asynchronously
|
||||
_ = TryInteractAsync();
|
||||
_ = StartInteractionFlowAsync();
|
||||
}
|
||||
|
||||
private async Task TryInteractAsync()
|
||||
/// <summary>
|
||||
/// Template method that orchestrates the entire interaction flow.
|
||||
/// </summary>
|
||||
private async Task StartInteractionFlowAsync()
|
||||
{
|
||||
_interactionInProgress = true;
|
||||
// 2. Find characters
|
||||
playerRef = FindFirstObjectByType<PlayerTouchController>();
|
||||
FollowerController = FindFirstObjectByType<FollowerController>();
|
||||
|
||||
_playerRef = FindFirstObjectByType<PlayerTouchController>();
|
||||
_followerController = FindFirstObjectByType<FollowerController>();
|
||||
// 3. Virtual hook: Setup
|
||||
OnInteractionStarted();
|
||||
|
||||
interactionStarted?.Invoke(_playerRef, _followerController);
|
||||
|
||||
// Dispatch the InteractionStarted event to action components
|
||||
// 4. Fire events
|
||||
interactionStarted?.Invoke(playerRef, FollowerController);
|
||||
await DispatchEventAsync(InteractionEventType.InteractionStarted);
|
||||
|
||||
// After all InteractionStarted actions complete, proceed to player movement
|
||||
await StartPlayerMovementAsync();
|
||||
// 5. Orchestrate character movement
|
||||
await MoveCharactersAsync();
|
||||
|
||||
// 6. Virtual hook: Arrival reaction
|
||||
OnInteractingCharacterArrived();
|
||||
|
||||
// 7. Fire arrival events
|
||||
characterArrived?.Invoke();
|
||||
await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived);
|
||||
|
||||
// 8. Validation (base + child)
|
||||
var (canProceed, errorMessage) = ValidateInteraction();
|
||||
if (!canProceed)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
DebugUIMessage.Show(errorMessage, Color.yellow);
|
||||
}
|
||||
FinishInteraction(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 9. Virtual main logic: Do the thing!
|
||||
bool success = DoInteraction();
|
||||
|
||||
// 10. Finish up
|
||||
FinishInteraction(success);
|
||||
}
|
||||
|
||||
private async Task StartPlayerMovementAsync()
|
||||
#region Virtual Lifecycle Methods
|
||||
|
||||
/// <summary>
|
||||
/// High-level clickability check. Called BEFORE interaction starts.
|
||||
/// Override to add custom high-level validation (is active, on cooldown, etc.)
|
||||
/// </summary>
|
||||
/// <returns>True if interaction can start, false for silent rejection</returns>
|
||||
protected virtual bool CanBeClicked()
|
||||
{
|
||||
if (_playerRef == null)
|
||||
if (!isActive) return false;
|
||||
// Note: isOneTime and cooldown handled in FinishInteraction
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after characters are found but before movement starts.
|
||||
/// Override to perform setup logic.
|
||||
/// </summary>
|
||||
protected virtual void OnInteractionStarted()
|
||||
{
|
||||
// Default: do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the interacting character reaches destination.
|
||||
/// Override to trigger animations or other arrival reactions.
|
||||
/// </summary>
|
||||
protected virtual void OnInteractingCharacterArrived()
|
||||
{
|
||||
// Default: do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main interaction logic. OVERRIDE THIS in child classes.
|
||||
/// </summary>
|
||||
/// <returns>True if interaction succeeded, false otherwise</returns>
|
||||
protected virtual bool DoInteraction()
|
||||
{
|
||||
Logging.Warning($"[Interactable] DoInteraction not implemented for {GetType().Name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after interaction completes. Override to perform cleanup logic.
|
||||
/// </summary>
|
||||
/// <param name="success">Whether the interaction succeeded</param>
|
||||
protected virtual void OnInteractionFinished(bool success)
|
||||
{
|
||||
// Default: do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Child-specific validation. Override to add interaction-specific validation.
|
||||
/// </summary>
|
||||
/// <returns>Tuple of (canProceed, errorMessage)</returns>
|
||||
protected virtual (bool canProceed, string errorMessage) CanProceedWithInteraction()
|
||||
{
|
||||
return (true, null); // Default: always allow
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Validation
|
||||
|
||||
/// <summary>
|
||||
/// Combines base and child validation.
|
||||
/// </summary>
|
||||
private (bool, string) ValidateInteraction()
|
||||
{
|
||||
// Base validation (always runs)
|
||||
var (baseValid, baseError) = ValidateInteractionBase();
|
||||
if (!baseValid)
|
||||
return (false, baseError);
|
||||
|
||||
// Child validation (optional override)
|
||||
var (childValid, childError) = CanProceedWithInteraction();
|
||||
if (!childValid)
|
||||
return (false, childError);
|
||||
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base validation that always runs. Checks puzzle step locks and common prerequisites.
|
||||
/// </summary>
|
||||
private (bool canProceed, string errorMessage) ValidateInteractionBase()
|
||||
{
|
||||
// Check if there's an ObjectiveStepBehaviour attached
|
||||
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
|
||||
if (step != null && !step.IsStepUnlocked())
|
||||
{
|
||||
// Special case: ItemSlots can still be interacted with when locked (to swap items)
|
||||
if (!(this is ItemSlot))
|
||||
{
|
||||
return (false, "This step is locked!");
|
||||
}
|
||||
}
|
||||
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Character Movement Orchestration
|
||||
|
||||
/// <summary>
|
||||
/// Orchestrates character movement based on characterToInteract setting.
|
||||
/// </summary>
|
||||
private async Task MoveCharactersAsync()
|
||||
{
|
||||
if (playerRef == null)
|
||||
{
|
||||
Logging.Debug($"[Interactable] Player character could not be found. Aborting interaction.");
|
||||
interactionInterrupted.Invoke();
|
||||
@@ -137,350 +270,222 @@ namespace Interactions
|
||||
return;
|
||||
}
|
||||
|
||||
// If characterToInteract is None, immediately trigger the characterArrived event
|
||||
// If characterToInteract is None, skip movement
|
||||
if (characterToInteract == CharacterToInteract.None)
|
||||
{
|
||||
await BroadcastCharacterArrivedAsync();
|
||||
return;
|
||||
return; // Continue to arrival
|
||||
}
|
||||
|
||||
// Check for a CharacterMoveToTarget component for Trafalgar (player) or Both
|
||||
Vector3 stopPoint;
|
||||
// Move player and optionally follower based on characterToInteract setting
|
||||
if (characterToInteract == CharacterToInteract.Trafalgar)
|
||||
{
|
||||
await MovePlayerAsync();
|
||||
}
|
||||
else if (characterToInteract == CharacterToInteract.Pulver || characterToInteract == CharacterToInteract.Both)
|
||||
{
|
||||
await MovePlayerAsync(); // Move player to range first
|
||||
await MoveFollowerAsync(); // Then move follower to interaction point
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the player to the interaction point or custom target.
|
||||
/// </summary>
|
||||
private async Task MovePlayerAsync()
|
||||
{
|
||||
Vector3 stopPoint = transform.position; // Default to interactable position
|
||||
bool customTargetFound = false;
|
||||
|
||||
// Check for a CharacterMoveToTarget component for Trafalgar or Both
|
||||
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
||||
foreach (var target in moveTargets)
|
||||
{
|
||||
// Target is valid if it matches Trafalgar specifically or is set to Both
|
||||
if (target.characterType == CharacterToInteract.Trafalgar || target.characterType == CharacterToInteract.Both)
|
||||
{
|
||||
stopPoint = target.GetTargetPosition();
|
||||
customTargetFound = true;
|
||||
|
||||
// We need to wait for the player to arrive, so use a TaskCompletionSource
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
// Use local functions instead of circular lambda references
|
||||
void OnPlayerArrivedLocal()
|
||||
{
|
||||
// First remove both event handlers to prevent memory leaks
|
||||
if (_playerRef != null)
|
||||
{
|
||||
_playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
||||
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
||||
}
|
||||
|
||||
// Then continue with the interaction flow
|
||||
OnPlayerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true));
|
||||
}
|
||||
|
||||
void OnPlayerMoveCancelledLocal()
|
||||
{
|
||||
// First remove both event handlers to prevent memory leaks
|
||||
if (_playerRef != null)
|
||||
{
|
||||
_playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
||||
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
||||
}
|
||||
|
||||
// Then handle the cancellation
|
||||
OnPlayerMoveCancelledAsync().ContinueWith(_ => tcs.TrySetResult(false));
|
||||
}
|
||||
|
||||
// Unsubscribe previous handlers (if any)
|
||||
_playerRef.OnArrivedAtTarget -= OnPlayerArrived;
|
||||
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelled;
|
||||
|
||||
// Subscribe our new handlers
|
||||
_playerRef.OnArrivedAtTarget += OnPlayerArrivedLocal;
|
||||
_playerRef.OnMoveToCancelled += OnPlayerMoveCancelledLocal;
|
||||
|
||||
// Start the player movement
|
||||
_playerRef.MoveToAndNotify(stopPoint);
|
||||
|
||||
// Await player arrival
|
||||
await tcs.Task;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no custom target was found, use the default behavior
|
||||
// If no custom target, use default distance
|
||||
if (!customTargetFound)
|
||||
{
|
||||
// Compute closest point on the interaction radius
|
||||
Vector3 interactablePos = transform.position;
|
||||
Vector3 playerPos = _playerRef.transform.position;
|
||||
Vector3 playerPos = playerRef.transform.position;
|
||||
float stopDistance = characterToInteract == CharacterToInteract.Pulver
|
||||
? GameManager.Instance.PlayerStopDistance
|
||||
: GameManager.Instance.PlayerStopDistanceDirectInteraction;
|
||||
Vector3 toPlayer = (playerPos - interactablePos).normalized;
|
||||
stopPoint = interactablePos + toPlayer * stopDistance;
|
||||
|
||||
// We need to wait for the player to arrive, so use a TaskCompletionSource
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
// Use local functions instead of circular lambda references
|
||||
void OnPlayerArrivedLocal()
|
||||
{
|
||||
// First remove both event handlers to prevent memory leaks
|
||||
if (_playerRef != null)
|
||||
{
|
||||
_playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
||||
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
||||
}
|
||||
|
||||
// Then continue with the interaction flow
|
||||
OnPlayerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true));
|
||||
}
|
||||
|
||||
void OnPlayerMoveCancelledLocal()
|
||||
{
|
||||
// First remove both event handlers to prevent memory leaks
|
||||
if (_playerRef != null)
|
||||
{
|
||||
_playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
||||
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
||||
}
|
||||
|
||||
// Then handle the cancellation
|
||||
OnPlayerMoveCancelledAsync().ContinueWith(_ => tcs.TrySetResult(false));
|
||||
}
|
||||
|
||||
// Unsubscribe previous handlers (if any)
|
||||
_playerRef.OnArrivedAtTarget -= OnPlayerArrived;
|
||||
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelled;
|
||||
|
||||
// Subscribe our new handlers
|
||||
_playerRef.OnArrivedAtTarget += OnPlayerArrivedLocal;
|
||||
_playerRef.OnMoveToCancelled += OnPlayerMoveCancelledLocal;
|
||||
|
||||
// Start the player movement
|
||||
_playerRef.MoveToAndNotify(stopPoint);
|
||||
|
||||
// Await player arrival
|
||||
await tcs.Task;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnPlayerMoveCancelledAsync()
|
||||
{
|
||||
_interactionInProgress = false;
|
||||
interactionInterrupted?.Invoke();
|
||||
await DispatchEventAsync(InteractionEventType.InteractionInterrupted);
|
||||
}
|
||||
|
||||
private async Task OnPlayerArrivedAsync()
|
||||
{
|
||||
if (!_interactionInProgress)
|
||||
return;
|
||||
|
||||
// Dispatch PlayerArrived event
|
||||
await DispatchEventAsync(InteractionEventType.PlayerArrived);
|
||||
// Wait for player to arrive
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
// After all PlayerArrived actions complete, proceed to character interaction
|
||||
await HandleCharacterInteractionAsync();
|
||||
void OnPlayerArrivedLocal()
|
||||
{
|
||||
if (playerRef != null)
|
||||
{
|
||||
playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
||||
playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
||||
}
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
|
||||
void OnPlayerMoveCancelledLocal()
|
||||
{
|
||||
if (playerRef != null)
|
||||
{
|
||||
playerRef.OnArrivedAtTarget -= OnPlayerArrivedLocal;
|
||||
playerRef.OnMoveToCancelled -= OnPlayerMoveCancelledLocal;
|
||||
}
|
||||
_ = HandleInteractionCancelledAsync();
|
||||
tcs.TrySetResult(false);
|
||||
}
|
||||
|
||||
playerRef.OnArrivedAtTarget += OnPlayerArrivedLocal;
|
||||
playerRef.OnMoveToCancelled += OnPlayerMoveCancelledLocal;
|
||||
playerRef.MoveToAndNotify(stopPoint);
|
||||
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
private async Task HandleCharacterInteractionAsync()
|
||||
/// <summary>
|
||||
/// Moves the follower to the interaction point or custom target.
|
||||
/// </summary>
|
||||
private async Task MoveFollowerAsync()
|
||||
{
|
||||
if (characterToInteract == CharacterToInteract.Pulver)
|
||||
{
|
||||
// We need to wait for the follower to arrive, so use a TaskCompletionSource
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
// Create a proper local function for the event handler
|
||||
void OnFollowerArrivedLocal()
|
||||
{
|
||||
// First remove the event handler to prevent memory leaks
|
||||
if (_followerController != null)
|
||||
{
|
||||
_followerController.OnPickupArrived -= OnFollowerArrivedLocal;
|
||||
}
|
||||
|
||||
// Then continue with the interaction flow
|
||||
OnFollowerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true));
|
||||
}
|
||||
|
||||
// Register our new local function handler
|
||||
_followerController.OnPickupArrived += OnFollowerArrivedLocal;
|
||||
|
||||
// Check for a CharacterMoveToTarget component for Pulver or Both
|
||||
Vector3 targetPosition = transform.position;
|
||||
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
||||
foreach (var target in moveTargets)
|
||||
{
|
||||
if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both)
|
||||
{
|
||||
targetPosition = target.GetTargetPosition();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the new GoToPoint method instead of GoToPointAndReturn
|
||||
_followerController.GoToPoint(targetPosition);
|
||||
|
||||
// Await follower arrival
|
||||
await tcs.Task;
|
||||
}
|
||||
else if (characterToInteract == CharacterToInteract.Trafalgar)
|
||||
{
|
||||
await BroadcastCharacterArrivedAsync();
|
||||
}
|
||||
else if (characterToInteract == CharacterToInteract.Both)
|
||||
{
|
||||
// We need to wait for the follower to arrive, so use a TaskCompletionSource
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
// Create a proper local function for the event handler
|
||||
void OnFollowerArrivedLocal()
|
||||
{
|
||||
// First remove the event handler to prevent memory leaks
|
||||
if (_followerController != null)
|
||||
{
|
||||
_followerController.OnPickupArrived -= OnFollowerArrivedLocal;
|
||||
}
|
||||
|
||||
// Then continue with the interaction flow
|
||||
OnFollowerArrivedAsync().ContinueWith(_ => tcs.TrySetResult(true));
|
||||
}
|
||||
|
||||
// Register our new local function handler
|
||||
_followerController.OnPickupArrived += OnFollowerArrivedLocal;
|
||||
|
||||
// Check for a CharacterMoveToTarget component for Pulver or Both
|
||||
Vector3 targetPosition = transform.position;
|
||||
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
||||
foreach (var target in moveTargets)
|
||||
{
|
||||
if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both)
|
||||
{
|
||||
targetPosition = target.GetTargetPosition();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the new GoToPoint method instead of GoToPointAndReturn
|
||||
_followerController.GoToPoint(targetPosition);
|
||||
|
||||
// Await follower arrival
|
||||
await tcs.Task;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnFollowerArrivedAsync()
|
||||
{
|
||||
if (!_interactionInProgress)
|
||||
if (FollowerController == null)
|
||||
return;
|
||||
|
||||
// Dispatch InteractingCharacterArrived event and WAIT for all actions to complete
|
||||
// This ensures we wait for any timeline animations to finish before proceeding
|
||||
Logging.Debug("[Interactable] Follower arrived, dispatching InteractingCharacterArrived event and waiting for completion");
|
||||
await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived);
|
||||
Logging.Debug("[Interactable] All InteractingCharacterArrived actions completed, proceeding with interaction");
|
||||
|
||||
// Check if we have any components that might have paused the interaction flow
|
||||
foreach (var action in _registeredActions)
|
||||
// Check for a CharacterMoveToTarget component for Pulver or Both
|
||||
Vector3 targetPosition = transform.position;
|
||||
CharacterMoveToTarget[] moveTargets = GetComponentsInChildren<CharacterMoveToTarget>();
|
||||
foreach (var target in moveTargets)
|
||||
{
|
||||
if (action is InteractionTimelineAction timelineAction &&
|
||||
timelineAction.respondToEvents.Contains(InteractionEventType.InteractingCharacterArrived) &&
|
||||
timelineAction.pauseInteractionFlow)
|
||||
if (target.characterType == CharacterToInteract.Pulver || target.characterType == CharacterToInteract.Both)
|
||||
{
|
||||
targetPosition = target.GetTargetPosition();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the follower to return to the player
|
||||
if (_followerController != null && _playerRef != null)
|
||||
// Wait for follower to arrive
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
void OnFollowerArrivedLocal()
|
||||
{
|
||||
_followerController.ReturnToPlayer(_playerRef.transform);
|
||||
if (FollowerController != null)
|
||||
{
|
||||
FollowerController.OnPickupArrived -= OnFollowerArrivedLocal;
|
||||
}
|
||||
|
||||
// Tell follower to return to player
|
||||
if (FollowerController != null && playerRef != null)
|
||||
{
|
||||
FollowerController.ReturnToPlayer(playerRef.transform);
|
||||
}
|
||||
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
|
||||
// After all InteractingCharacterArrived actions complete, proceed to character arrived
|
||||
await BroadcastCharacterArrivedAsync();
|
||||
}
|
||||
|
||||
// Legacy non-async method to maintain compatibility with existing code
|
||||
private void OnPlayerArrived()
|
||||
{
|
||||
// This is now just a wrapper for the async version
|
||||
_ = OnPlayerArrivedAsync();
|
||||
}
|
||||
|
||||
// Legacy non-async method to maintain compatibility with existing code
|
||||
private void OnPlayerMoveCancelled()
|
||||
{
|
||||
// This is now just a wrapper for the async version
|
||||
_ = OnPlayerMoveCancelledAsync();
|
||||
}
|
||||
|
||||
private Task BroadcastCharacterArrivedAsync()
|
||||
{
|
||||
// Check for ObjectiveStepBehaviour and lock state
|
||||
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
|
||||
var slot = GetComponent<ItemSlot>();
|
||||
if (step != null && !step.IsStepUnlocked() && slot == null)
|
||||
{
|
||||
DebugUIMessage.Show("This step is locked!", Color.yellow);
|
||||
CompleteInteraction(false);
|
||||
// Reset variables for next time
|
||||
_interactionInProgress = false;
|
||||
_playerRef = null;
|
||||
_followerController = null;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Dispatch CharacterArrived event
|
||||
// await DispatchEventAsync(InteractionEventType.InteractingCharacterArrived);
|
||||
FollowerController.OnPickupArrived += OnFollowerArrivedLocal;
|
||||
FollowerController.GoToPoint(targetPosition);
|
||||
|
||||
// Broadcast appropriate event
|
||||
characterArrived?.Invoke();
|
||||
|
||||
// Call the virtual method for subclasses to override
|
||||
OnCharacterArrived();
|
||||
|
||||
// Reset variables for next time
|
||||
_interactionInProgress = false;
|
||||
_playerRef = null;
|
||||
_followerController = null;
|
||||
return Task.CompletedTask;
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the character has arrived at the interaction point.
|
||||
/// Subclasses should override this to implement interaction-specific logic
|
||||
/// and call CompleteInteraction(bool success) when done.
|
||||
/// Handles interaction being cancelled (player stopped moving).
|
||||
/// </summary>
|
||||
protected virtual void OnCharacterArrived()
|
||||
private async Task HandleInteractionCancelledAsync()
|
||||
{
|
||||
// Default implementation does nothing - subclasses should override
|
||||
// and call CompleteInteraction when their logic is complete
|
||||
interactionInterrupted?.Invoke();
|
||||
await DispatchEventAsync(InteractionEventType.InteractionInterrupted);
|
||||
}
|
||||
|
||||
private async void OnInteractionComplete(bool success)
|
||||
#endregion
|
||||
|
||||
#region Finalization
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the interaction after DoInteraction completes.
|
||||
/// </summary>
|
||||
private async void FinishInteraction(bool success)
|
||||
{
|
||||
// Dispatch InteractionComplete event
|
||||
// Virtual hook: Cleanup
|
||||
OnInteractionFinished(success);
|
||||
|
||||
// Fire completion events
|
||||
interactionComplete?.Invoke(success);
|
||||
await DispatchEventAsync(InteractionEventType.InteractionComplete);
|
||||
|
||||
// Handle one-time / cooldown
|
||||
if (success)
|
||||
{
|
||||
if (isOneTime)
|
||||
{
|
||||
_isActive = false;
|
||||
isActive = false;
|
||||
}
|
||||
else if (cooldown >= 0f)
|
||||
{
|
||||
StartCoroutine(HandleCooldown());
|
||||
}
|
||||
}
|
||||
|
||||
// Reset state
|
||||
playerRef = null;
|
||||
FollowerController = null;
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator HandleCooldown()
|
||||
{
|
||||
_isActive = false;
|
||||
isActive = false;
|
||||
yield return new WaitForSeconds(cooldown);
|
||||
_isActive = true;
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Legacy Methods & Compatibility
|
||||
|
||||
/// <summary>
|
||||
/// DEPRECATED: Override DoInteraction() instead.
|
||||
/// This method is kept temporarily for backward compatibility during migration.
|
||||
/// </summary>
|
||||
[Obsolete("Override DoInteraction() instead")]
|
||||
protected virtual void OnCharacterArrived()
|
||||
{
|
||||
// Default implementation does nothing
|
||||
// Children should override DoInteraction() in the new pattern
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this from subclasses to mark the interaction as complete.
|
||||
/// NOTE: In the new pattern, just return true/false from DoInteraction().
|
||||
/// This is kept for backward compatibility during migration.
|
||||
/// </summary>
|
||||
protected void CompleteInteraction(bool success)
|
||||
{
|
||||
// For now, this manually triggers completion
|
||||
// After migration, DoInteraction() return value will replace this
|
||||
interactionComplete?.Invoke(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legacy method for backward compatibility.
|
||||
/// </summary>
|
||||
[Obsolete("Use CompleteInteraction instead")]
|
||||
public void BroadcastInteractionComplete(bool success)
|
||||
{
|
||||
CompleteInteraction(success);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITouchInputConsumer Implementation
|
||||
|
||||
public void OnHoldStart(Vector2 position)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -495,25 +500,8 @@ namespace Interactions
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this from subclasses to mark the interaction as complete.
|
||||
/// </summary>
|
||||
/// <param name="success">Whether the interaction was successful</param>
|
||||
protected void CompleteInteraction(bool success)
|
||||
{
|
||||
interactionComplete?.Invoke(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legacy method for backward compatibility. Use CompleteInteraction instead.
|
||||
/// </summary>
|
||||
/// TODO: Remove this method in future versions
|
||||
[Obsolete("Use CompleteInteraction instead")]
|
||||
public void BroadcastInteractionComplete(bool success)
|
||||
{
|
||||
CompleteInteraction(success);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
|
||||
@@ -19,32 +19,40 @@ namespace Interactions
|
||||
/// <summary>
|
||||
/// Saveable data for ItemSlot state
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
[Serializable]
|
||||
public class ItemSlotSaveData
|
||||
{
|
||||
public PickupSaveData pickupData; // Base pickup state
|
||||
public ItemSlotState slotState; // Current slot validation state
|
||||
public string slottedItemSaveId; // Save ID of slotted item (if any)
|
||||
public string slottedItemDataAssetPath; // Asset path to PickupItemData
|
||||
public ItemSlotState slotState;
|
||||
public string slottedItemSaveId;
|
||||
public string slottedItemDataId; // ItemId of the PickupItemData (for verification)
|
||||
}
|
||||
|
||||
// TODO: Remove this ridiculous inheritance from Pickup if possible
|
||||
/// <summary>
|
||||
/// Interaction requirement that allows slotting, swapping, or picking up items in a slot.
|
||||
/// Interaction that allows slotting, swapping, or picking up items in a slot.
|
||||
/// ItemSlot is a CONTAINER, not a Pickup itself.
|
||||
/// </summary>
|
||||
public class ItemSlot : Pickup
|
||||
public class ItemSlot : SaveableInteractable
|
||||
{
|
||||
// Slot visual data (for the slot itself, not the item in it)
|
||||
public PickupItemData itemData;
|
||||
public SpriteRenderer iconRenderer;
|
||||
|
||||
// Slotted item tracking
|
||||
private PickupItemData currentlySlottedItemData;
|
||||
public SpriteRenderer slottedItemRenderer;
|
||||
private GameObject currentlySlottedItemObject;
|
||||
|
||||
// Tracks the current state of the slotted item
|
||||
private ItemSlotState _currentState = ItemSlotState.None;
|
||||
private ItemSlotState currentState = ItemSlotState.None;
|
||||
|
||||
// Settings reference
|
||||
private IInteractionSettings _interactionSettings;
|
||||
private IPlayerFollowerSettings _playerFollowerSettings;
|
||||
private IInteractionSettings interactionSettings;
|
||||
private IPlayerFollowerSettings playerFollowerSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Read-only access to the current slotted item state.
|
||||
/// </summary>
|
||||
public ItemSlotState CurrentSlottedState => _currentState;
|
||||
public ItemSlotState CurrentSlottedState => currentState;
|
||||
|
||||
public UnityEvent onItemSlotted;
|
||||
public UnityEvent onItemSlotRemoved;
|
||||
@@ -62,118 +70,199 @@ namespace Interactions
|
||||
public UnityEvent onForbiddenItemSlotted;
|
||||
// Native C# event alternative for code-only subscribers
|
||||
public event Action<PickupItemData, PickupItemData> OnForbiddenItemSlotted;
|
||||
|
||||
private PickupItemData _currentlySlottedItemData;
|
||||
public SpriteRenderer slottedItemRenderer;
|
||||
private GameObject _currentlySlottedItemObject;
|
||||
|
||||
public GameObject GetSlottedObject()
|
||||
{
|
||||
return _currentlySlottedItemObject;
|
||||
return currentlySlottedItemObject;
|
||||
}
|
||||
|
||||
public void SetSlottedObject(GameObject obj)
|
||||
{
|
||||
_currentlySlottedItemObject = obj;
|
||||
if (_currentlySlottedItemObject != null)
|
||||
currentlySlottedItemObject = obj;
|
||||
if (currentlySlottedItemObject != null)
|
||||
{
|
||||
_currentlySlottedItemObject.SetActive(false);
|
||||
currentlySlottedItemObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
base.Awake(); // SaveableInteractable registration
|
||||
|
||||
// Setup visuals
|
||||
if (iconRenderer == null)
|
||||
iconRenderer = GetComponent<SpriteRenderer>();
|
||||
|
||||
ApplyItemData();
|
||||
|
||||
// Initialize settings references
|
||||
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||||
_playerFollowerSettings = GameManager.GetSettingsObject<IPlayerFollowerSettings>();
|
||||
interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||||
playerFollowerSettings = GameManager.GetSettingsObject<IPlayerFollowerSettings>();
|
||||
}
|
||||
|
||||
protected override void OnCharacterArrived()
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Unity OnValidate callback. Ensures icon and data are up to date in editor.
|
||||
/// </summary>
|
||||
void OnValidate()
|
||||
{
|
||||
Logging.Debug("[ItemSlot] OnCharacterArrived");
|
||||
|
||||
var heldItemData = _followerController.CurrentlyHeldItemData;
|
||||
var heldItemObj = _followerController.GetHeldPickupObject();
|
||||
var config = _interactionSettings?.GetSlotItemConfig(itemData);
|
||||
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
|
||||
|
||||
// Held item, slot empty -> try to slot item
|
||||
if (heldItemData != null && _currentlySlottedItemObject == null)
|
||||
{
|
||||
// First check for forbidden items at the very start so we don't continue unnecessarily
|
||||
if (PickupItemData.ListContainsEquivalent(forbidden, heldItemData))
|
||||
{
|
||||
DebugUIMessage.Show("Can't place that here.", Color.red);
|
||||
onForbiddenItemSlotted?.Invoke();
|
||||
OnForbiddenItemSlotted?.Invoke(itemData, heldItemData);
|
||||
_currentState = ItemSlotState.Forbidden;
|
||||
CompleteInteraction(false);
|
||||
return;
|
||||
}
|
||||
if (iconRenderer == null)
|
||||
iconRenderer = GetComponent<SpriteRenderer>();
|
||||
ApplyItemData();
|
||||
}
|
||||
#endif
|
||||
|
||||
SlotItem(heldItemObj, heldItemData, true);
|
||||
return;
|
||||
/// <summary>
|
||||
/// Applies the item data to the slot (icon, name, etc).
|
||||
/// </summary>
|
||||
public void ApplyItemData()
|
||||
{
|
||||
if (itemData != null)
|
||||
{
|
||||
if (iconRenderer != null && itemData.mapSprite != null)
|
||||
{
|
||||
iconRenderer.sprite = itemData.mapSprite;
|
||||
}
|
||||
gameObject.name = itemData.itemName + "_Slot";
|
||||
}
|
||||
}
|
||||
|
||||
#region Interaction Logic
|
||||
|
||||
/// <summary>
|
||||
/// Validation: Check if interaction can proceed based on held item and slot state.
|
||||
/// </summary>
|
||||
protected override (bool canProceed, string errorMessage) CanProceedWithInteraction()
|
||||
{
|
||||
var heldItem = FollowerController?.CurrentlyHeldItemData;
|
||||
|
||||
// Scenario: Nothing held + Empty slot = Error
|
||||
if (heldItem == null && currentlySlottedItemObject == null)
|
||||
return (false, "This requires an item.");
|
||||
|
||||
// Check forbidden items if trying to slot into empty slot
|
||||
if (heldItem != null && currentlySlottedItemObject == null)
|
||||
{
|
||||
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
||||
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
|
||||
|
||||
if (PickupItemData.ListContainsEquivalent(forbidden, heldItem))
|
||||
return (false, "Can't place that here.");
|
||||
}
|
||||
|
||||
// Either pickup or swap items
|
||||
if ((heldItemData == null && _currentlySlottedItemObject != null)
|
||||
|| (heldItemData != null && _currentlySlottedItemObject != null))
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main interaction logic: Slot, pickup, swap, or combine items.
|
||||
/// Returns true only if correct item was slotted.
|
||||
/// </summary>
|
||||
protected override bool DoInteraction()
|
||||
{
|
||||
Logging.Debug("[ItemSlot] DoInteraction");
|
||||
|
||||
var heldItemData = FollowerController.CurrentlyHeldItemData;
|
||||
var heldItemObj = FollowerController.GetHeldPickupObject();
|
||||
|
||||
// Scenario 1: Held item + Empty slot = Slot it
|
||||
if (heldItemData != null && currentlySlottedItemObject == null)
|
||||
{
|
||||
// If both held and slotted items exist, attempt combination via follower (reuse existing logic from Pickup)
|
||||
if (heldItemData != null && _currentlySlottedItemData != null)
|
||||
SlotItem(heldItemObj, heldItemData);
|
||||
FollowerController.ClearHeldItem(); // Clear follower's hand after slotting
|
||||
return IsSlottedItemCorrect();
|
||||
}
|
||||
|
||||
// Scenario 2 & 3: Slot is full
|
||||
if (currentlySlottedItemObject != null)
|
||||
{
|
||||
// Try combination if both items present
|
||||
if (heldItemData != null)
|
||||
{
|
||||
var slottedPickup = _currentlySlottedItemObject?.GetComponent<Pickup>();
|
||||
var slottedPickup = currentlySlottedItemObject.GetComponent<Pickup>();
|
||||
if (slottedPickup != null)
|
||||
{
|
||||
var comboResult = _followerController.TryCombineItems(slottedPickup, out var combinationResultItem);
|
||||
if (combinationResultItem != null && comboResult == FollowerController.CombinationResult.Successful)
|
||||
var comboResult = FollowerController.TryCombineItems(slottedPickup, out var combinationResultItem);
|
||||
|
||||
if (comboResult == FollowerController.CombinationResult.Successful)
|
||||
{
|
||||
// Combination succeeded: fire slot-removed events and clear internals (don't call SlotItem to avoid duplicate events)
|
||||
onItemSlotRemoved?.Invoke();
|
||||
OnItemSlotRemoved?.Invoke(_currentlySlottedItemData);
|
||||
_currentState = ItemSlotState.None;
|
||||
|
||||
// Clear internal references and visuals
|
||||
_currentlySlottedItemObject = null;
|
||||
_currentlySlottedItemData = null;
|
||||
UpdateSlottedSprite();
|
||||
|
||||
CompleteInteraction(false);
|
||||
return;
|
||||
// Combination succeeded - clear slot and return false (not a "slot success")
|
||||
ClearSlot();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No combination (or not applicable) -> perform normal swap/pickup behavior
|
||||
_followerController.TryPickupItem(_currentlySlottedItemObject, _currentlySlottedItemData, false);
|
||||
onItemSlotRemoved?.Invoke();
|
||||
OnItemSlotRemoved?.Invoke(_currentlySlottedItemData);
|
||||
_currentState = ItemSlotState.None;
|
||||
SlotItem(heldItemObj, heldItemData, _currentlySlottedItemObject == null);
|
||||
return;
|
||||
|
||||
// No combination or unsuccessful - perform swap
|
||||
// Step 1: Pickup from slot (follower now holds the old slotted item)
|
||||
FollowerController.TryPickupItem(currentlySlottedItemObject, currentlySlottedItemData, dropItem: false);
|
||||
ClearSlot();
|
||||
|
||||
// Step 2: If we had a held item, slot it (follower already holding picked up item, don't clear!)
|
||||
if (heldItemData != null)
|
||||
{
|
||||
SlotItem(heldItemObj, heldItemData);
|
||||
// Don't clear follower - they're holding the item they picked up from the slot
|
||||
return IsSlottedItemCorrect();
|
||||
}
|
||||
|
||||
// Just picked up from slot - not a success
|
||||
return false;
|
||||
}
|
||||
|
||||
// No held item, slot empty -> show warning
|
||||
if (heldItemData == null && _currentlySlottedItemObject == null)
|
||||
{
|
||||
DebugUIMessage.Show("This requires an item.", Color.red);
|
||||
return;
|
||||
}
|
||||
// Shouldn't reach here (validation prevents empty + no held)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper: Check if the currently slotted item is correct.
|
||||
/// </summary>
|
||||
private bool IsSlottedItemCorrect()
|
||||
{
|
||||
return currentState == ItemSlotState.Correct;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper: Clear the slot and fire removal events.
|
||||
/// </summary>
|
||||
private void ClearSlot()
|
||||
{
|
||||
var previousData = currentlySlottedItemData;
|
||||
|
||||
// Clear the pickup's OwningSlot reference
|
||||
if (currentlySlottedItemObject != null)
|
||||
{
|
||||
var pickup = currentlySlottedItemObject.GetComponent<Pickup>();
|
||||
if (pickup != null)
|
||||
{
|
||||
pickup.OwningSlot = null;
|
||||
}
|
||||
}
|
||||
|
||||
currentlySlottedItemObject = null;
|
||||
currentlySlottedItemData = null;
|
||||
currentState = ItemSlotState.None;
|
||||
UpdateSlottedSprite();
|
||||
|
||||
// Fire removal events
|
||||
onItemSlotRemoved?.Invoke();
|
||||
OnItemSlotRemoved?.Invoke(previousData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Visual Updates
|
||||
|
||||
/// <summary>
|
||||
/// Updates the sprite and scale for the currently slotted item.
|
||||
/// </summary>
|
||||
private void UpdateSlottedSprite()
|
||||
{
|
||||
if (slottedItemRenderer != null && _currentlySlottedItemData != null && _currentlySlottedItemData.mapSprite != null)
|
||||
if (slottedItemRenderer != null && currentlySlottedItemData != null && currentlySlottedItemData.mapSprite != null)
|
||||
{
|
||||
slottedItemRenderer.sprite = _currentlySlottedItemData.mapSprite;
|
||||
slottedItemRenderer.sprite = currentlySlottedItemData.mapSprite;
|
||||
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
|
||||
float desiredHeight = _playerFollowerSettings?.HeldIconDisplayHeight ?? 2.0f;
|
||||
var sprite = _currentlySlottedItemData.mapSprite;
|
||||
float desiredHeight = playerFollowerSettings?.HeldIconDisplayHeight ?? 2.0f;
|
||||
var sprite = currentlySlottedItemData.mapSprite;
|
||||
float spriteHeight = sprite.bounds.size.y;
|
||||
Vector3 parentScale = slottedItemRenderer.transform.parent != null
|
||||
? slottedItemRenderer.transform.parent.localScale
|
||||
@@ -191,18 +280,18 @@ namespace Interactions
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Register with ItemManager when enabled
|
||||
protected override void Start()
|
||||
private void OnEnable()
|
||||
{
|
||||
base.Start(); // This calls Pickup.Start() which registers with save system
|
||||
|
||||
// Additionally register as ItemSlot
|
||||
// Register as ItemSlot
|
||||
ItemManager.Instance?.RegisterItemSlot(this);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy(); // Unregister from save system and pickup manager
|
||||
base.OnDestroy();
|
||||
|
||||
// Unregister from slot manager
|
||||
ItemManager.Instance?.UnregisterItemSlot(this);
|
||||
@@ -212,35 +301,30 @@ namespace Interactions
|
||||
|
||||
protected override object GetSerializableState()
|
||||
{
|
||||
// Get base pickup state
|
||||
PickupSaveData baseData = base.GetSerializableState() as PickupSaveData;
|
||||
|
||||
// Get slotted item save ID if there's a slotted item
|
||||
string slottedSaveId = "";
|
||||
string slottedAssetPath = "";
|
||||
string slottedDataId = "";
|
||||
|
||||
if (_currentlySlottedItemObject != null)
|
||||
if (currentlySlottedItemObject != null)
|
||||
{
|
||||
var slottedPickup = _currentlySlottedItemObject.GetComponent<Pickup>();
|
||||
var slottedPickup = currentlySlottedItemObject.GetComponent<Pickup>();
|
||||
if (slottedPickup is SaveableInteractable saveablePickup)
|
||||
{
|
||||
slottedSaveId = saveablePickup.GetSaveId();
|
||||
}
|
||||
|
||||
if (_currentlySlottedItemData != null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
slottedAssetPath = UnityEditor.AssetDatabase.GetAssetPath(_currentlySlottedItemData);
|
||||
#endif
|
||||
slottedSaveId = saveablePickup.SaveId;
|
||||
}
|
||||
}
|
||||
|
||||
// Also save the itemData ID for verification
|
||||
if (currentlySlottedItemData != null)
|
||||
{
|
||||
slottedDataId = currentlySlottedItemData.itemId;
|
||||
}
|
||||
|
||||
return new ItemSlotSaveData
|
||||
{
|
||||
pickupData = baseData,
|
||||
slotState = _currentState,
|
||||
slotState = currentState,
|
||||
slottedItemSaveId = slottedSaveId,
|
||||
slottedItemDataAssetPath = slottedAssetPath
|
||||
slottedItemDataId = slottedDataId
|
||||
};
|
||||
}
|
||||
|
||||
@@ -249,24 +333,18 @@ namespace Interactions
|
||||
ItemSlotSaveData data = JsonUtility.FromJson<ItemSlotSaveData>(serializedData);
|
||||
if (data == null)
|
||||
{
|
||||
Debug.LogWarning($"[ItemSlot] Failed to deserialize save data for {gameObject.name}");
|
||||
Logging.Warning($"[ItemSlot] Failed to deserialize save data for {gameObject.name}");
|
||||
return;
|
||||
}
|
||||
|
||||
// First restore base pickup state
|
||||
if (data.pickupData != null)
|
||||
{
|
||||
string pickupJson = JsonUtility.ToJson(data.pickupData);
|
||||
base.ApplySerializableState(pickupJson);
|
||||
}
|
||||
|
||||
// Restore slot state
|
||||
_currentState = data.slotState;
|
||||
currentState = data.slotState;
|
||||
|
||||
// Restore slotted item if there was one
|
||||
if (!string.IsNullOrEmpty(data.slottedItemSaveId))
|
||||
{
|
||||
RestoreSlottedItem(data.slottedItemSaveId, data.slottedItemDataAssetPath);
|
||||
Logging.Debug($"[ItemSlot] Restoring slotted item: {data.slottedItemSaveId} (itemId: {data.slottedItemDataId})");
|
||||
RestoreSlottedItem(data.slottedItemSaveId, data.slottedItemDataId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,117 +352,193 @@ namespace Interactions
|
||||
/// Restore a slotted item from save data.
|
||||
/// This is called during load restoration and should NOT trigger events.
|
||||
/// </summary>
|
||||
private void RestoreSlottedItem(string slottedItemSaveId, string slottedItemDataAssetPath)
|
||||
private void RestoreSlottedItem(string slottedItemSaveId, string expectedItemDataId)
|
||||
{
|
||||
// Try to find the item in the scene by its save ID via ItemManager
|
||||
GameObject slottedObject = ItemManager.Instance?.FindPickupBySaveId(slottedItemSaveId);
|
||||
|
||||
if (slottedObject == null)
|
||||
if (slottedObject == null && !string.IsNullOrEmpty(expectedItemDataId))
|
||||
{
|
||||
Debug.LogWarning($"[ItemSlot] Could not find slotted item with save ID: {slottedItemSaveId}");
|
||||
// Item not found in scene - it might be a dynamically spawned combined item
|
||||
// Try to spawn it from the itemDataId
|
||||
Logging.Debug($"[ItemSlot] Slotted item not found in scene: {slottedItemSaveId}, attempting to spawn from itemId: {expectedItemDataId}");
|
||||
|
||||
GameObject prefab = interactionSettings?.FindPickupPrefabByItemId(expectedItemDataId);
|
||||
if (prefab != null)
|
||||
{
|
||||
// Spawn the item (inactive, since it will be slotted)
|
||||
slottedObject = Instantiate(prefab, transform.position, Quaternion.identity);
|
||||
slottedObject.SetActive(false);
|
||||
Logging.Debug($"[ItemSlot] Successfully spawned combined item for slot: {expectedItemDataId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[ItemSlot] Could not find prefab for itemId: {expectedItemDataId}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (slottedObject == null)
|
||||
{
|
||||
Logging.Warning($"[ItemSlot] Could not find slotted item with save ID: {slottedItemSaveId}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the item data
|
||||
// Get the item data from the pickup component
|
||||
PickupItemData slottedData = null;
|
||||
#if UNITY_EDITOR
|
||||
if (!string.IsNullOrEmpty(slottedItemDataAssetPath))
|
||||
var pickup = slottedObject.GetComponent<Pickup>();
|
||||
if (pickup != null)
|
||||
{
|
||||
slottedData = UnityEditor.AssetDatabase.LoadAssetAtPath<PickupItemData>(slottedItemDataAssetPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (slottedData == null)
|
||||
{
|
||||
var pickup = slottedObject.GetComponent<Pickup>();
|
||||
if (pickup != null)
|
||||
{
|
||||
slottedData = pickup.itemData;
|
||||
}
|
||||
}
|
||||
|
||||
// Silently slot the item (no events, no interaction completion)
|
||||
ApplySlottedItemState(slottedObject, slottedData, triggerEvents: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core logic for slotting an item. Can be used both for normal slotting and silent restoration.
|
||||
/// </summary>
|
||||
/// <param name="itemToSlot">The item GameObject to slot (or null to clear)</param>
|
||||
/// <param name="itemToSlotData">The PickupItemData for the item</param>
|
||||
/// <param name="triggerEvents">Whether to fire events and complete interaction</param>
|
||||
/// <param name="clearFollowerHeldItem">Whether to clear the follower's held item</param>
|
||||
private void ApplySlottedItemState(GameObject itemToSlot, PickupItemData itemToSlotData, bool triggerEvents, bool clearFollowerHeldItem = true)
|
||||
{
|
||||
// Cache the previous item data before clearing, needed for OnItemSlotRemoved event
|
||||
var previousItemData = _currentlySlottedItemData;
|
||||
bool wasSlotCleared = _currentlySlottedItemObject != null && itemToSlot == null;
|
||||
|
||||
if (itemToSlot == null)
|
||||
{
|
||||
_currentlySlottedItemObject = null;
|
||||
_currentlySlottedItemData = null;
|
||||
_currentState = ItemSlotState.None;
|
||||
slottedData = pickup.itemData;
|
||||
|
||||
// Fire native event for slot clearing (only if triggering events)
|
||||
if (wasSlotCleared && triggerEvents)
|
||||
// Verify itemId matches if we have it (safety check)
|
||||
if (slottedData != null && !string.IsNullOrEmpty(expectedItemDataId))
|
||||
{
|
||||
OnItemSlotRemoved?.Invoke(previousItemData);
|
||||
if (slottedData.itemId != expectedItemDataId)
|
||||
{
|
||||
Logging.Warning($"[ItemSlot] ItemId mismatch! Pickup has '{slottedData.itemId}' but expected '{expectedItemDataId}'");
|
||||
}
|
||||
}
|
||||
|
||||
if (slottedData == null)
|
||||
{
|
||||
Logging.Warning($"[ItemSlot] Pickup {pickup.gameObject.name} has null itemData! Expected itemId: {expectedItemDataId}");
|
||||
if (slottedObject != null)
|
||||
Destroy(slottedObject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[ItemSlot] Slotted object has no Pickup component: {slottedObject.name}");
|
||||
if (slottedObject != null)
|
||||
Destroy(slottedObject);
|
||||
return;
|
||||
}
|
||||
|
||||
// Silently slot the item (no events, no interaction completion)
|
||||
// Follower state is managed separately during save/load restoration
|
||||
ApplySlottedItemState(slottedObject, slottedData, triggerEvents: false);
|
||||
|
||||
Logging.Debug($"[ItemSlot] Successfully restored slotted item: {slottedData.itemName} (itemId: {slottedData.itemId})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core logic for slotting an item. Can be used both for normal slotting and silent restoration.
|
||||
/// NOTE: Does NOT call CompleteInteraction - the template method handles that via DoInteraction return value.
|
||||
/// NOTE: Does NOT manage follower state - caller is responsible for clearing follower's hand if needed.
|
||||
/// </summary>
|
||||
/// <param name="itemToSlot">The item GameObject to slot (or null to clear)</param>
|
||||
/// <param name="itemToSlotData">The PickupItemData for the item</param>
|
||||
/// <param name="triggerEvents">Whether to fire events</param>
|
||||
private void ApplySlottedItemState(GameObject itemToSlot, PickupItemData itemToSlotData, bool triggerEvents)
|
||||
{
|
||||
if (itemToSlot == null)
|
||||
{
|
||||
// Clear slot - also clear the pickup's OwningSlot reference
|
||||
if (currentlySlottedItemObject != null)
|
||||
{
|
||||
var oldPickup = currentlySlottedItemObject.GetComponent<Pickup>();
|
||||
if (oldPickup != null)
|
||||
{
|
||||
oldPickup.OwningSlot = null;
|
||||
}
|
||||
}
|
||||
|
||||
var previousData = currentlySlottedItemData;
|
||||
currentlySlottedItemObject = null;
|
||||
currentlySlottedItemData = null;
|
||||
currentState = ItemSlotState.None;
|
||||
|
||||
// Fire native event for slot clearing (only if triggering events)
|
||||
if (previousData != null && triggerEvents)
|
||||
{
|
||||
onItemSlotRemoved?.Invoke();
|
||||
OnItemSlotRemoved?.Invoke(previousData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slot the item
|
||||
itemToSlot.SetActive(false);
|
||||
itemToSlot.transform.SetParent(null);
|
||||
SetSlottedObject(itemToSlot);
|
||||
_currentlySlottedItemData = itemToSlotData;
|
||||
}
|
||||
|
||||
if (clearFollowerHeldItem && _followerController != null)
|
||||
{
|
||||
_followerController.ClearHeldItem();
|
||||
}
|
||||
UpdateSlottedSprite();
|
||||
|
||||
// Only validate and trigger events if requested
|
||||
if (triggerEvents)
|
||||
{
|
||||
// Once an item is slotted, we know it is not forbidden, so we can skip that check, but now check if it was
|
||||
// the correct item we're looking for
|
||||
var config = _interactionSettings?.GetSlotItemConfig(itemData);
|
||||
currentlySlottedItemData = itemToSlotData;
|
||||
|
||||
// Mark the pickup as picked up and track slot ownership for save/load
|
||||
var pickup = itemToSlot.GetComponent<Pickup>();
|
||||
if (pickup != null)
|
||||
{
|
||||
pickup.IsPickedUp = true;
|
||||
pickup.OwningSlot = this;
|
||||
}
|
||||
|
||||
// Determine if correct
|
||||
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
||||
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
||||
|
||||
if (itemToSlotData != null && PickupItemData.ListContainsEquivalent(allowed, itemToSlotData))
|
||||
{
|
||||
if (itemToSlot != null)
|
||||
currentState = ItemSlotState.Correct;
|
||||
|
||||
// Fire events if requested
|
||||
if (triggerEvents)
|
||||
{
|
||||
DebugUIMessage.Show("You correctly slotted " + itemToSlotData.itemName + " into: " + itemData.itemName, Color.green);
|
||||
DebugUIMessage.Show($"You correctly slotted {itemToSlotData.itemName} into: {itemData.itemName}", Color.green);
|
||||
onCorrectItemSlotted?.Invoke();
|
||||
OnCorrectItemSlotted?.Invoke(itemData, _currentlySlottedItemData);
|
||||
_currentState = ItemSlotState.Correct;
|
||||
OnCorrectItemSlotted?.Invoke(itemData, currentlySlottedItemData);
|
||||
}
|
||||
|
||||
CompleteInteraction(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (itemToSlot != null)
|
||||
currentState = ItemSlotState.Incorrect;
|
||||
|
||||
// Fire events if requested
|
||||
if (triggerEvents)
|
||||
{
|
||||
DebugUIMessage.Show("I'm not sure this works.", Color.yellow);
|
||||
onIncorrectItemSlotted?.Invoke();
|
||||
OnIncorrectItemSlotted?.Invoke(itemData, _currentlySlottedItemData);
|
||||
_currentState = ItemSlotState.Incorrect;
|
||||
OnIncorrectItemSlotted?.Invoke(itemData, currentlySlottedItemData);
|
||||
}
|
||||
CompleteInteraction(false);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSlottedSprite();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public API for slotting items during gameplay.
|
||||
/// Caller is responsible for managing follower's held item state.
|
||||
/// </summary>
|
||||
public void SlotItem(GameObject itemToSlot, PickupItemData itemToSlotData, bool clearFollowerHeldItem = true)
|
||||
public void SlotItem(GameObject itemToSlot, PickupItemData itemToSlotData)
|
||||
{
|
||||
ApplySlottedItemState(itemToSlot, itemToSlotData, triggerEvents: true, clearFollowerHeldItem);
|
||||
ApplySlottedItemState(itemToSlot, itemToSlotData, triggerEvents: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bilateral restoration entry point: Pickup calls this to offer itself to the Slot.
|
||||
/// Returns true if claim was successful, false if slot already has an item or wrong pickup.
|
||||
/// </summary>
|
||||
public bool TryClaimSlottedItem(Pickup pickup)
|
||||
{
|
||||
if (pickup == null)
|
||||
return false;
|
||||
|
||||
// If slot already has an item, reject the claim
|
||||
if (currentlySlottedItemObject != null)
|
||||
{
|
||||
Logging.Warning($"[ItemSlot] Already has a slotted item, rejecting claim from {pickup.gameObject.name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify this pickup's SaveId matches what we expect (from our save data)
|
||||
// Note: We don't have easy access to the expected SaveId here, so we just accept it
|
||||
// The Pickup's bilateral restoration ensures it only claims the correct slot
|
||||
|
||||
// Claim the pickup
|
||||
ApplySlottedItemState(pickup.gameObject, pickup.itemData, triggerEvents: false);
|
||||
|
||||
Logging.Debug($"[ItemSlot] Successfully claimed slotted item: {pickup.itemData?.itemName}");
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using UnityEngine;
|
||||
using Input;
|
||||
using Interactions;
|
||||
|
||||
namespace Interactions
|
||||
namespace Interactions
|
||||
{
|
||||
/// <summary>
|
||||
/// Interactable that immediately completes when the character arrives at the interaction point.
|
||||
@@ -11,11 +7,11 @@ namespace Interactions
|
||||
public class OneClickInteraction : InteractableBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Override: Immediately completes the interaction with success when character arrives.
|
||||
/// Main interaction logic: Simply return success.
|
||||
/// </summary>
|
||||
protected override void OnCharacterArrived()
|
||||
protected override bool DoInteraction()
|
||||
{
|
||||
CompleteInteraction(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
using Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Bootstrap; // added for Action<T>
|
||||
using Core; // register with ItemManager
|
||||
using Core;
|
||||
|
||||
namespace Interactions
|
||||
{
|
||||
/// <summary>
|
||||
/// Saveable data for Pickup state
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
[Serializable]
|
||||
public class PickupSaveData
|
||||
{
|
||||
public bool isPickedUp;
|
||||
public bool wasHeldByFollower; // Track if held by follower for bilateral restoration
|
||||
public bool wasHeldByFollower;
|
||||
public bool wasInSlot; // NEW: Was this pickup in a slot?
|
||||
public string slotSaveId; // NEW: Which slot held this pickup?
|
||||
public Vector3 worldPosition;
|
||||
public Quaternion worldRotation;
|
||||
public bool isActive;
|
||||
@@ -24,19 +24,14 @@ namespace Interactions
|
||||
{
|
||||
public PickupItemData itemData;
|
||||
public SpriteRenderer iconRenderer;
|
||||
|
||||
// Track if the item has been picked up
|
||||
public bool IsPickedUp { get; internal set; }
|
||||
|
||||
// Event: invoked when the item was picked up successfully
|
||||
|
||||
// Track which slot owns this pickup (for bilateral restoration)
|
||||
internal ItemSlot OwningSlot { get; set; }
|
||||
|
||||
public event Action<PickupItemData> OnItemPickedUp;
|
||||
|
||||
// Event: invoked when this item is successfully combined with another
|
||||
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
|
||||
|
||||
/// <summary>
|
||||
/// Unity Awake callback. Sets up icon and applies item data.
|
||||
/// </summary>
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake(); // Register with save system
|
||||
@@ -47,28 +42,16 @@ namespace Interactions
|
||||
ApplyItemData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register with ItemManager on Start
|
||||
/// </summary>
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start(); // Register with save system
|
||||
|
||||
// Always register with ItemManager, even if picked up
|
||||
// Always register with ItemManager, even if picked up
|
||||
// This allows the save/load system to find held items when restoring state
|
||||
BootCompletionService.RegisterInitAction(() =>
|
||||
{
|
||||
ItemManager.Instance?.RegisterPickup(this);
|
||||
});
|
||||
|
||||
protected override void OnManagedAwake()
|
||||
{
|
||||
ItemManager.Instance?.RegisterPickup(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity OnDestroy callback. Unregisters from ItemManager.
|
||||
/// </summary>
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy(); // Unregister from save system
|
||||
base.OnDestroy();
|
||||
|
||||
// Unregister from ItemManager
|
||||
ItemManager.Instance?.UnregisterPickup(this);
|
||||
@@ -103,64 +86,57 @@ namespace Interactions
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override: Called when character arrives at the interaction point.
|
||||
/// Handles item pickup and combination logic.
|
||||
/// </summary>
|
||||
protected override void OnCharacterArrived()
|
||||
{
|
||||
Logging.Debug("[Pickup] OnCharacterArrived");
|
||||
|
||||
var combinationResult = _followerController.TryCombineItems(this, out var combinationResultItem);
|
||||
if (combinationResultItem != null)
|
||||
{
|
||||
CompleteInteraction(true);
|
||||
|
||||
// Fire the combination event when items are successfully combined
|
||||
if (combinationResult == FollowerController.CombinationResult.Successful)
|
||||
{
|
||||
var resultPickup = combinationResultItem.GetComponent<Pickup>();
|
||||
if (resultPickup != null && resultPickup.itemData != null)
|
||||
{
|
||||
// Get the combined item data
|
||||
var resultItemData = resultPickup.itemData;
|
||||
var heldItem = _followerController.GetHeldPickupObject();
|
||||
|
||||
if (heldItem != null)
|
||||
{
|
||||
var heldPickup = heldItem.GetComponent<Pickup>();
|
||||
if (heldPickup != null && heldPickup.itemData != null)
|
||||
{
|
||||
// Trigger the combination event
|
||||
OnItemsCombined?.Invoke(itemData, heldPickup.itemData, resultItemData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_followerController?.TryPickupItem(gameObject, itemData);
|
||||
|
||||
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
|
||||
if (step != null && !step.IsStepUnlocked())
|
||||
{
|
||||
CompleteInteraction(false);
|
||||
return;
|
||||
}
|
||||
|
||||
bool wasPickedUp = (combinationResult == FollowerController.CombinationResult.NotApplicable
|
||||
|| combinationResult == FollowerController.CombinationResult.Unsuccessful);
|
||||
CompleteInteraction(wasPickedUp);
|
||||
#region Interaction Logic
|
||||
|
||||
// Update pickup state and invoke event when the item was picked up successfully
|
||||
if (wasPickedUp)
|
||||
/// <summary>
|
||||
/// Main interaction logic: Try combination, then try pickup.
|
||||
/// </summary>
|
||||
protected override bool DoInteraction()
|
||||
{
|
||||
Logging.Debug("[Pickup] DoInteraction");
|
||||
|
||||
// IMPORTANT: Capture held item data BEFORE combination
|
||||
// TryCombineItems destroys the original items, so we need this data for the event
|
||||
var heldItemObject = FollowerController?.GetHeldPickupObject();
|
||||
var heldItemData = heldItemObject?.GetComponent<Pickup>()?.itemData;
|
||||
|
||||
// Try combination first
|
||||
var combinationResult = FollowerController.TryCombineItems(this, out var resultItem);
|
||||
|
||||
if (combinationResult == FollowerController.CombinationResult.Successful)
|
||||
{
|
||||
// Mark this pickup as picked up (consumed in combination) to prevent restoration
|
||||
IsPickedUp = true;
|
||||
OnItemPickedUp?.Invoke(itemData);
|
||||
|
||||
// Combination succeeded - original items destroyed, result picked up by TryCombineItems
|
||||
FireCombinationEvent(resultItem, heldItemData);
|
||||
return true;
|
||||
}
|
||||
|
||||
// No combination (or unsuccessful) - do regular pickup
|
||||
FollowerController?.TryPickupItem(gameObject, itemData);
|
||||
IsPickedUp = true;
|
||||
OnItemPickedUp?.Invoke(itemData);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to fire the combination event with correct item data.
|
||||
/// </summary>
|
||||
/// <param name="resultItem">The spawned result item</param>
|
||||
/// <param name="originalHeldItemData">The ORIGINAL held item data (before destruction)</param>
|
||||
private void FireCombinationEvent(GameObject resultItem, PickupItemData originalHeldItemData)
|
||||
{
|
||||
var resultPickup = resultItem?.GetComponent<Pickup>();
|
||||
|
||||
// Verify we have all required data
|
||||
if (resultPickup?.itemData != null && originalHeldItemData != null && itemData != null)
|
||||
{
|
||||
OnItemsCombined?.Invoke(itemData, originalHeldItemData, resultPickup.itemData);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Save/Load Implementation
|
||||
|
||||
@@ -169,10 +145,16 @@ namespace Interactions
|
||||
// Check if this pickup is currently held by the follower
|
||||
bool isHeldByFollower = IsPickedUp && !gameObject.activeSelf && transform.parent != null;
|
||||
|
||||
// Check if this pickup is in a slot
|
||||
bool isInSlot = OwningSlot != null;
|
||||
string slotId = isInSlot && OwningSlot is SaveableInteractable saveableSlot ? saveableSlot.SaveId : "";
|
||||
|
||||
return new PickupSaveData
|
||||
{
|
||||
isPickedUp = this.IsPickedUp,
|
||||
wasHeldByFollower = isHeldByFollower,
|
||||
wasInSlot = isInSlot,
|
||||
slotSaveId = slotId,
|
||||
worldPosition = transform.position,
|
||||
worldRotation = transform.rotation,
|
||||
isActive = gameObject.activeSelf
|
||||
@@ -184,7 +166,7 @@ namespace Interactions
|
||||
PickupSaveData data = JsonUtility.FromJson<PickupSaveData>(serializedData);
|
||||
if (data == null)
|
||||
{
|
||||
Debug.LogWarning($"[Pickup] Failed to deserialize save data for {gameObject.name}");
|
||||
Logging.Warning($"[Pickup] Failed to deserialize save data for {gameObject.name}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -207,6 +189,20 @@ namespace Interactions
|
||||
follower.TryClaimHeldItem(this);
|
||||
}
|
||||
}
|
||||
// If this was in a slot, try bilateral restoration with the slot
|
||||
else if (data.wasInSlot && !string.IsNullOrEmpty(data.slotSaveId))
|
||||
{
|
||||
// Try to give this pickup to the slot
|
||||
var slot = FindSlotBySaveId(data.slotSaveId);
|
||||
if (slot != null)
|
||||
{
|
||||
slot.TryClaimSlottedItem(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[Pickup] Could not find slot with SaveId: {data.slotSaveId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -220,6 +216,28 @@ namespace Interactions
|
||||
// This prevents duplicate logic execution
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find an ItemSlot by its SaveId (for bilateral restoration).
|
||||
/// </summary>
|
||||
private ItemSlot FindSlotBySaveId(string slotSaveId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(slotSaveId)) return null;
|
||||
|
||||
// Get all ItemSlots from ItemManager
|
||||
var allSlots = ItemManager.Instance?.GetAllItemSlots();
|
||||
if (allSlots == null) return null;
|
||||
|
||||
foreach (var slot in allSlots)
|
||||
{
|
||||
if (slot is SaveableInteractable saveable && saveable.SaveId == slotSaveId)
|
||||
{
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the pickup state when the item is dropped back into the world.
|
||||
/// Called by FollowerController when swapping items.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Core.SaveLoad;
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Interactions
|
||||
{
|
||||
@@ -8,21 +7,13 @@ namespace Interactions
|
||||
/// Base class for interactables that participate in the save/load system.
|
||||
/// Provides common save ID generation and serialization infrastructure.
|
||||
/// </summary>
|
||||
public abstract class SaveableInteractable : InteractableBase, ISaveParticipant
|
||||
public abstract class SaveableInteractable : InteractableBase
|
||||
{
|
||||
[Header("Save System")]
|
||||
[SerializeField]
|
||||
[Tooltip("Optional custom save ID. If empty, will auto-generate from hierarchy path.")]
|
||||
private string customSaveId = "";
|
||||
|
||||
/// <summary>
|
||||
/// Sets a custom save ID for this interactable.
|
||||
/// Used when spawning dynamic objects that need stable save IDs.
|
||||
/// </summary>
|
||||
public void SetCustomSaveId(string saveId)
|
||||
{
|
||||
customSaveId = saveId;
|
||||
}
|
||||
[SerializeField]
|
||||
|
||||
// Save system configuration
|
||||
public override bool AutoRegisterForSave => true;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to indicate we're currently restoring from save data.
|
||||
@@ -30,99 +21,10 @@ namespace Interactions
|
||||
/// </summary>
|
||||
protected bool IsRestoringFromSave { get; private set; }
|
||||
|
||||
private bool hasRegistered;
|
||||
private bool hasRestoredState;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this participant has already had its state restored.
|
||||
/// </summary>
|
||||
public bool HasBeenRestored => hasRestoredState;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
// Register early in Awake so even disabled objects are tracked
|
||||
RegisterWithSaveSystem();
|
||||
}
|
||||
#region Save/Load Lifecycle Hooks
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
// If we didn't register in Awake (shouldn't happen), register now
|
||||
if (!hasRegistered)
|
||||
{
|
||||
RegisterWithSaveSystem();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
UnregisterFromSaveSystem();
|
||||
}
|
||||
|
||||
private void RegisterWithSaveSystem()
|
||||
{
|
||||
if (hasRegistered) return;
|
||||
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.RegisterParticipant(this);
|
||||
hasRegistered = true;
|
||||
|
||||
// Check if save data was already loaded before we registered
|
||||
// If so, we need to subscribe to the next load event
|
||||
if (!SaveLoadManager.Instance.IsSaveDataLoaded && !hasRestoredState)
|
||||
{
|
||||
SaveLoadManager.Instance.OnLoadCompleted += OnSaveDataLoadedHandler;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[SaveableInteractable] SaveLoadManager not found for {gameObject.name}");
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterFromSaveSystem()
|
||||
{
|
||||
if (!hasRegistered) return;
|
||||
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.UnregisterParticipant(GetSaveId());
|
||||
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
|
||||
hasRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for when save data finishes loading.
|
||||
/// Called if the object registered before save data was loaded.
|
||||
/// </summary>
|
||||
private void OnSaveDataLoadedHandler(string slot)
|
||||
{
|
||||
// The SaveLoadManager will automatically call RestoreState on us
|
||||
// We just need to unsubscribe from the event
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
#region ISaveParticipant Implementation
|
||||
|
||||
public string GetSaveId()
|
||||
{
|
||||
string sceneName = GetSceneName();
|
||||
|
||||
if (!string.IsNullOrEmpty(customSaveId))
|
||||
{
|
||||
return $"{sceneName}/{customSaveId}";
|
||||
}
|
||||
|
||||
// Auto-generate from hierarchy path
|
||||
string hierarchyPath = GetHierarchyPath();
|
||||
return $"{sceneName}/{hierarchyPath}";
|
||||
}
|
||||
|
||||
public string SerializeState()
|
||||
protected override string OnSceneSaveRequested()
|
||||
{
|
||||
object stateData = GetSerializableState();
|
||||
if (stateData == null)
|
||||
@@ -133,28 +35,17 @@ namespace Interactions
|
||||
return JsonUtility.ToJson(stateData);
|
||||
}
|
||||
|
||||
public void RestoreState(string serializedData)
|
||||
protected override void OnSceneRestoreRequested(string serializedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serializedData))
|
||||
{
|
||||
Debug.LogWarning($"[SaveableInteractable] Empty save data for {GetSaveId()}");
|
||||
return;
|
||||
}
|
||||
|
||||
// CRITICAL: Only restore state if we're actually in a restoration context
|
||||
// This prevents state machines from teleporting objects when they enable them mid-gameplay
|
||||
if (SaveLoadManager.Instance != null && !SaveLoadManager.Instance.IsRestoringState)
|
||||
{
|
||||
// If we're not in an active restoration cycle, this is probably a late registration
|
||||
// (object was disabled during initial load and just got enabled)
|
||||
// Skip restoration to avoid mid-gameplay teleportation
|
||||
Debug.Log($"[SaveableInteractable] Skipping late restoration for {GetSaveId()} - object enabled after initial load");
|
||||
hasRestoredState = true; // Mark as restored to prevent future attempts
|
||||
Logging.Warning($"[SaveableInteractable] Empty save data for {SaveId}");
|
||||
return;
|
||||
}
|
||||
|
||||
// OnSceneRestoreRequested is guaranteed by the lifecycle system to only fire during actual restoration
|
||||
// No need to check IsRestoringState - the lifecycle manager handles timing deterministically
|
||||
IsRestoringFromSave = true;
|
||||
hasRestoredState = true;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -162,7 +53,7 @@ namespace Interactions
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"[SaveableInteractable] Failed to restore state for {GetSaveId()}: {e.Message}");
|
||||
Debug.LogError($"[SaveableInteractable] Failed to restore state for {SaveId}: {e.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -189,62 +80,23 @@ namespace Interactions
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private string GetSceneName()
|
||||
{
|
||||
Scene scene = gameObject.scene;
|
||||
if (!scene.IsValid())
|
||||
{
|
||||
Debug.LogWarning($"[SaveableInteractable] GameObject {gameObject.name} has invalid scene");
|
||||
return "UnknownScene";
|
||||
}
|
||||
|
||||
return scene.name;
|
||||
}
|
||||
|
||||
private string GetHierarchyPath()
|
||||
{
|
||||
// Build path from scene root to this object
|
||||
// Format: ParentName/ChildName/ObjectName_SiblingIndex
|
||||
string path = gameObject.name;
|
||||
Transform current = transform.parent;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
path = $"{current.name}/{path}";
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
// Add sibling index for uniqueness among same-named objects
|
||||
int siblingIndex = transform.GetSiblingIndex();
|
||||
if (siblingIndex > 0)
|
||||
{
|
||||
path = $"{path}_{siblingIndex}";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Editor Helpers
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[ContextMenu("Log Save ID")]
|
||||
private void LogSaveId()
|
||||
{
|
||||
Debug.Log($"Save ID: {GetSaveId()}");
|
||||
Logging.Debug($"Save ID: {SaveId}");
|
||||
}
|
||||
|
||||
[ContextMenu("Test Serialize/Deserialize")]
|
||||
private void TestSerializeDeserialize()
|
||||
{
|
||||
string serialized = SerializeState();
|
||||
Debug.Log($"Serialized state: {serialized}");
|
||||
string serialized = OnSceneSaveRequested();
|
||||
Logging.Debug($"Serialized state: {serialized}");
|
||||
|
||||
RestoreState(serialized);
|
||||
Debug.Log("Deserialization test complete");
|
||||
OnSceneRestoreRequested(serialized);
|
||||
Logging.Debug("Deserialization test complete");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user