diff --git a/Assets/Art/Textures/DivingBackground.png b/Assets/Art/Textures/DivingBackground.png
new file mode 100644
index 00000000..8b0a5782
Binary files /dev/null and b/Assets/Art/Textures/DivingBackground.png differ
diff --git a/Assets/Art/Textures/DivingBackground.png.meta b/Assets/Art/Textures/DivingBackground.png.meta
new file mode 100644
index 00000000..b080923e
--- /dev/null
+++ b/Assets/Art/Textures/DivingBackground.png.meta
@@ -0,0 +1,195 @@
+fileFormatVersion: 2
+guid: ad9b785acb09cb247ae2c8cd895863de
+TextureImporter:
+ internalIDToNameTable:
+ - first:
+ 213: 5958968447627082961
+ second: DivingBackground_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: 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
+ - serializedVersion: 4
+ buildTarget: Android
+ 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: 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:
+ - serializedVersion: 2
+ name: DivingBackground_0
+ rect:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1080
+ height: 1981
+ alignment: 0
+ pivot: {x: 0, y: 0}
+ border: {x: 0, y: 0, z: 0, w: 0}
+ customData:
+ outline: []
+ physicsShape: []
+ tessellationDetail: -1
+ bones: []
+ spriteID: 1dcb29c2b3282b250800000000000000
+ internalID: 5958968447627082961
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable:
+ DivingBackground_0: 5958968447627082961
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Editor/DivingGameManagerEditor.cs b/Assets/Editor/DivingGameManagerEditor.cs
new file mode 100644
index 00000000..53bde798
--- /dev/null
+++ b/Assets/Editor/DivingGameManagerEditor.cs
@@ -0,0 +1,48 @@
+using UnityEditor;
+using UnityEngine;
+using Minigames.DivingForPictures;
+
+///
+/// Custom editor for DivingGameManager that adds runtime buttons for testing surfacing and other functionality
+///
+[CustomEditor(typeof(DivingGameManager))]
+public class DivingGameManagerEditor : UnityEditor.Editor
+{
+ public override void OnInspectorGUI()
+ {
+ // Draw the default inspector
+ DrawDefaultInspector();
+
+ // Get the target DivingGameManager
+ DivingGameManager manager = (DivingGameManager)target;
+
+ // Add space between default inspector and custom buttons
+ EditorGUILayout.Space(10);
+
+ // Separator line
+ EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
+
+ // Add a label for the runtime testing section
+ EditorGUILayout.LabelField("Runtime Testing", EditorStyles.boldLabel);
+
+ // Only enable the buttons during play mode
+ EditorGUI.BeginDisabledGroup(!Application.isPlaying);
+
+ // Add the button to call StartSurfacing
+ if (GUILayout.Button("Start Surfacing", GUILayout.Height(30)))
+ {
+ manager.StartSurfacing();
+ }
+
+ // Add a button for breaking a rope (for testing damage)
+ if (GUILayout.Button("Break Rope (Test Damage)", GUILayout.Height(30)))
+ {
+ manager.ForceBreakRope();
+ }
+
+ EditorGUI.EndDisabledGroup();
+
+ // Add explanatory text
+ EditorGUILayout.HelpBox("These buttons only work in Play Mode. 'Start Surfacing' will reverse the trench direction, slow bubbles, and reverse obstacles. 'Break Rope' simulates player taking damage.", MessageType.Info);
+ }
+}
diff --git a/Assets/Editor/DivingGameManagerEditor.cs.meta b/Assets/Editor/DivingGameManagerEditor.cs.meta
new file mode 100644
index 00000000..cde212bf
--- /dev/null
+++ b/Assets/Editor/DivingGameManagerEditor.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8bbb340d8d9b4af581770757e86cc1f8
+timeCreated: 1758532258
\ No newline at end of file
diff --git a/Assets/Editor/TrenchTileSpawnerEditor.cs b/Assets/Editor/TrenchTileSpawnerEditor.cs
new file mode 100644
index 00000000..1178e8ad
--- /dev/null
+++ b/Assets/Editor/TrenchTileSpawnerEditor.cs
@@ -0,0 +1,42 @@
+using UnityEditor;
+using UnityEngine;
+using Minigames.DivingForPictures;
+
+///
+/// Custom editor for TrenchTileSpawner that adds a runtime button to test the StartSurfacing function
+///
+[CustomEditor(typeof(TrenchTileSpawner))]
+public class TrenchTileSpawnerEditor : UnityEditor.Editor
+{
+ public override void OnInspectorGUI()
+ {
+ // Draw the default inspector
+ DrawDefaultInspector();
+
+ // Get the target TrenchTileSpawner
+ TrenchTileSpawner spawner = (TrenchTileSpawner)target;
+
+ // Add space between default inspector and custom button
+ EditorGUILayout.Space(10);
+
+ // Separator line
+ EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
+
+ // Add a label for the runtime testing section
+ EditorGUILayout.LabelField("Runtime Testing", EditorStyles.boldLabel);
+
+ // Only enable the button during play mode
+ EditorGUI.BeginDisabledGroup(!Application.isPlaying);
+
+ // Add the button to call StartSurfacing
+ if (GUILayout.Button("Start Surfacing", GUILayout.Height(30)))
+ {
+ spawner.StartSurfacing();
+ }
+
+ EditorGUI.EndDisabledGroup();
+
+ // Add explanatory text
+ EditorGUILayout.HelpBox("This button will reverse the direction of the trench movement, making the player surface instead of descend. Only works in Play Mode.", MessageType.Info);
+ }
+}
diff --git a/Assets/Editor/TrenchTileSpawnerEditor.cs.meta b/Assets/Editor/TrenchTileSpawnerEditor.cs.meta
new file mode 100644
index 00000000..99db4891
--- /dev/null
+++ b/Assets/Editor/TrenchTileSpawnerEditor.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9fb1a138e45d4720ba5c95da894b4491
+timeCreated: 1758531024
\ No newline at end of file
diff --git a/Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef b/Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
new file mode 100644
index 00000000..ad3635d4
--- /dev/null
+++ b/Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
@@ -0,0 +1,3 @@
+{
+ "name": "OptimizedRope"
+}
diff --git a/Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta b/Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
new file mode 100644
index 00000000..ae3e171c
--- /dev/null
+++ b/Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: f7c43f01316c63c43a8b70a1dd6bdfac
+AssemblyDefinitionImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/OptimizedRopesAndCables/Script/Rope.cs b/Assets/External/OptimizedRopesAndCables/Script/Rope.cs
index 4ed753da..91853ad7 100644
--- a/Assets/External/OptimizedRopesAndCables/Script/Rope.cs
+++ b/Assets/External/OptimizedRopesAndCables/Script/Rope.cs
@@ -75,8 +75,20 @@ namespace GogoGaga.OptimizedRopesAndCables
public bool IsPrefab => gameObject.scene.rootCount == 0;
- private void Start()
+ // Track initialization state
+ private bool isInitialized = false;
+
+ ///
+ /// Public method to explicitly initialize the rope.
+ /// Call this after setting up endpoints if creating ropes at runtime.
+ ///
+ /// True if initialization was successful, false otherwise
+ public bool Initialize()
{
+ // Skip if already initialized
+ if (isInitialized)
+ return true;
+
InitializeLineRenderer();
if (AreEndPointsValid())
{
@@ -84,7 +96,17 @@ namespace GogoGaga.OptimizedRopesAndCables
targetValue = currentValue;
currentVelocity = Vector3.zero;
SetSplinePoint(); // Ensure initial spline point is set correctly
+ isInitialized = true;
+ return true;
}
+
+ return false;
+ }
+
+ private void Start()
+ {
+ // Use the same initialization method to avoid code duplication
+ Initialize();
}
private void OnValidate()
@@ -208,15 +230,62 @@ namespace GogoGaga.OptimizedRopesAndCables
return point;
}
- public Vector3 GetPointAt(float t)
+ ///
+ /// Set the start point of the rope
+ ///
+ public void SetStartPoint(Transform newStartPoint, bool recalculateRope = false)
{
- if (!AreEndPointsValid())
- {
- Debug.LogError("StartPoint or EndPoint is not assigned.", gameObject);
- return Vector3.zero;
- }
+ startPoint = newStartPoint;
+ if (recalculateRope)
+ RecalculateRope();
+ }
- return GetRationalBezierPoint(startPoint.position, currentValue, endPoint.position, t, StartPointWeight, midPointWeight, EndPointWeight);
+ ///
+ /// Set the end point of the rope
+ ///
+ public void SetEndPoint(Transform newEndPoint, bool recalculateRope = false)
+ {
+ endPoint = newEndPoint;
+ if (recalculateRope)
+ RecalculateRope();
+ }
+
+ ///
+ /// Set the mid point of the rope
+ ///
+ public void SetMidPoint(Transform newMidPoint, bool recalculateRope = false)
+ {
+ midPoint = newMidPoint;
+ if (recalculateRope)
+ RecalculateRope();
+ }
+
+ ///
+ /// Get a point along the rope at the specified position (0-1)
+ ///
+ public Vector3 GetPointAt(float position)
+ {
+ position = Mathf.Clamp01(position);
+ Vector3 mid = GetMidPoint();
+ return GetRationalBezierPoint(startPoint.position, mid, endPoint.position, position, StartPointWeight, midPointWeight, EndPointWeight);
+ }
+
+ ///
+ /// Force recalculation of the rope
+ ///
+ public void RecalculateRope()
+ {
+ if (!isInitialized)
+ {
+ Initialize();
+ }
+
+ if (AreEndPointsValid())
+ {
+ SetSplinePoint();
+ SimulatePhysics();
+ NotifyPointsChanged();
+ }
}
private void FixedUpdate()
@@ -262,61 +331,6 @@ namespace GogoGaga.OptimizedRopesAndCables
// Gizmos.DrawSphere(midPos, 0.2f);
}
- // New API methods for setting start and end points
- // with instantAssign parameter to recalculate the rope immediately, without
- // animating the rope to the new position.
- // When newStartPoint or newEndPoint is null, the rope will be recalculated immediately
-
- public void SetStartPoint(Transform newStartPoint, bool instantAssign = false)
- {
- startPoint = newStartPoint;
- prevStartPointPosition = startPoint == null ? Vector3.zero : startPoint.position;
-
- if (instantAssign || newStartPoint == null)
- {
- RecalculateRope();
- }
-
- NotifyPointsChanged();
- }
- public void SetMidPoint(Transform newMidPoint, bool instantAssign = false)
- {
- midPoint = newMidPoint;
- prevMidPointPosition = midPoint == null ? 0.5f : midPointPosition;
-
- if (instantAssign || newMidPoint == null)
- {
- RecalculateRope();
- }
- NotifyPointsChanged();
- }
-
- public void SetEndPoint(Transform newEndPoint, bool instantAssign = false)
- {
- endPoint = newEndPoint;
- prevEndPointPosition = endPoint == null ? Vector3.zero : endPoint.position;
-
- if (instantAssign || newEndPoint == null)
- {
- RecalculateRope();
- }
-
- NotifyPointsChanged();
- }
-
- public void RecalculateRope()
- {
- if (!AreEndPointsValid())
- {
- lineRenderer.positionCount = 0;
- return;
- }
-
- currentValue = GetMidPoint();
- targetValue = currentValue;
- currentVelocity = Vector3.zero;
- SetSplinePoint();
- }
private void NotifyPointsChanged()
{
diff --git a/Assets/Playables.meta b/Assets/Playables.meta
new file mode 100644
index 00000000..f6a6ecf6
--- /dev/null
+++ b/Assets/Playables.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2c0088270c13b3a4e8ce04a3f672887d
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Playables/SurfacingTimeline.playable b/Assets/Playables/SurfacingTimeline.playable
new file mode 100644
index 00000000..1138b302
--- /dev/null
+++ b/Assets/Playables/SurfacingTimeline.playable
@@ -0,0 +1,1248 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &-4039891455399305819
+MonoBehaviour:
+ m_ObjectHideFlags: 1
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: d21dcc2386d650c4597f3633c75a1f98, type: 3}
+ m_Name: Animation Track (2)
+ m_EditorClassIdentifier:
+ m_Version: 3
+ m_AnimClip: {fileID: 0}
+ m_Locked: 0
+ m_Muted: 0
+ m_CustomPlayableFullTypename:
+ m_Curves: {fileID: 0}
+ m_Parent: {fileID: 11400000}
+ m_Children: []
+ m_Clips: []
+ m_Markers:
+ m_Objects: []
+ m_InfiniteClipPreExtrapolation: 1
+ m_InfiniteClipPostExtrapolation: 1
+ m_InfiniteClipOffsetPosition: {x: 0, y: 0, z: 0}
+ m_InfiniteClipOffsetEulerAngles: {x: 0, y: 0, z: 0}
+ m_InfiniteClipTimeOffset: 0
+ m_InfiniteClipRemoveOffset: 0
+ m_InfiniteClipApplyFootIK: 1
+ mInfiniteClipLoop: 0
+ m_MatchTargetFields: 63
+ m_Position: {x: 0, y: 0, z: 0}
+ m_EulerAngles: {x: 0, y: 0, z: 0}
+ m_AvatarMask: {fileID: 0}
+ m_ApplyAvatarMask: 1
+ m_TrackOffset: 0
+ m_InfiniteClip: {fileID: -1120528782975220419}
+ m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_Rotation: {x: 0, y: 0, z: 0, w: 1}
+ m_ApplyOffsets: 0
+--- !u!74 &-3085705704792956194
+AnimationClip:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Recorded (1)
+ serializedVersion: 7
+ m_Legacy: 0
+ m_Compressed: 0
+ m_UseHighQualityCurve: 1
+ m_RotationCurves: []
+ m_CompressedRotationCurves: []
+ m_EulerCurves: []
+ m_PositionCurves:
+ - curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0.95
+ value: {x: 0, y: 0.60010004, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 1.0833334
+ value: {x: 0, y: 0.16010022, z: 0}
+ inSlope: {x: 0, y: -3.2999988, z: 0}
+ outSlope: {x: 0, y: -3.2999988, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 1.4833333
+ value: {x: 0, y: -3.8999, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 1.7
+ value: {x: 0, y: -3.3298998, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 1.9833333
+ value: {x: 0, y: -4.5899, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 2.3166666
+ value: {x: 0, y: -3.7998998, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 2.5833333
+ value: {x: 0, y: -4.6099, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 2.8166666
+ value: {x: 0, y: -4.0298996, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ path:
+ m_ScaleCurves: []
+ m_FloatCurves:
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: d39dbaae819c4a128a11ca60fbbc98c9, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: 9072050a53fc4b539f4f4716bab53c07, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: 8222f0e3aeeb4fc4975aaead6cf7afbe, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: c9c18dbd013d42ae8c221e6205e4d49c, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: d8ea29cc80524de8affe17b930cd75c1, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 60
+ script: {fileID: 0}
+ flags: 0
+ m_PPtrCurves: []
+ m_SampleRate: 60
+ m_WrapMode: 0
+ m_Bounds:
+ m_Center: {x: 0, y: 0, z: 0}
+ m_Extent: {x: 0, y: 0, z: 0}
+ m_ClipBindingConstant:
+ genericBindings:
+ - serializedVersion: 2
+ path: 0
+ attribute: 1
+ script: {fileID: 0}
+ typeID: 4
+ customType: 0
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ - serializedVersion: 2
+ path: 0
+ attribute: 3305885265
+ script: {fileID: 11500000, guid: d39dbaae819c4a128a11ca60fbbc98c9, type: 3}
+ typeID: 114
+ customType: 24
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ - serializedVersion: 2
+ path: 0
+ attribute: 3305885265
+ script: {fileID: 11500000, guid: 9072050a53fc4b539f4f4716bab53c07, type: 3}
+ typeID: 114
+ customType: 24
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ - serializedVersion: 2
+ path: 0
+ attribute: 3305885265
+ script: {fileID: 11500000, guid: 8222f0e3aeeb4fc4975aaead6cf7afbe, type: 3}
+ typeID: 114
+ customType: 24
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ - serializedVersion: 2
+ path: 0
+ attribute: 3305885265
+ script: {fileID: 11500000, guid: c9c18dbd013d42ae8c221e6205e4d49c, type: 3}
+ typeID: 114
+ customType: 24
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ - serializedVersion: 2
+ path: 0
+ attribute: 3305885265
+ script: {fileID: 11500000, guid: d8ea29cc80524de8affe17b930cd75c1, type: 3}
+ typeID: 114
+ customType: 24
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ - serializedVersion: 2
+ path: 0
+ attribute: 3305885265
+ script: {fileID: 0}
+ typeID: 60
+ customType: 0
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ pptrCurveMapping: []
+ m_AnimationClipSettings:
+ serializedVersion: 2
+ m_AdditiveReferencePoseClip: {fileID: 0}
+ m_AdditiveReferencePoseTime: 0
+ m_StartTime: 0
+ m_StopTime: 2.8166666
+ m_OrientationOffsetY: 0
+ m_Level: 0
+ m_CycleOffset: 0
+ m_HasAdditiveReferencePose: 0
+ m_LoopTime: 0
+ m_LoopBlend: 0
+ m_LoopBlendOrientation: 0
+ m_LoopBlendPositionY: 0
+ m_LoopBlendPositionXZ: 0
+ m_KeepOriginalOrientation: 0
+ m_KeepOriginalPositionY: 1
+ m_KeepOriginalPositionXZ: 0
+ m_HeightFromFeet: 0
+ m_Mirror: 0
+ m_EditorCurves:
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.0833334
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.4833333
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.7
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.9833333
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.3166666
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.5833333
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.8166666
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_LocalPosition.x
+ path:
+ classID: 4
+ script: {fileID: 0}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0.95
+ value: 0.60010004
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.0833334
+ value: 0.16010022
+ inSlope: -3.2999988
+ outSlope: -3.2999988
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.4833333
+ value: -3.8999
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.7
+ value: -3.3298998
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.9833333
+ value: -4.5899
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.3166666
+ value: -3.7998998
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.5833333
+ value: -4.6099
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.8166666
+ value: -4.0298996
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_LocalPosition.y
+ path:
+ classID: 4
+ script: {fileID: 0}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.0833334
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.4833333
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.7
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.9833333
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.3166666
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.5833333
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.8166666
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_LocalPosition.z
+ path:
+ classID: 4
+ script: {fileID: 0}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: d39dbaae819c4a128a11ca60fbbc98c9, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: 9072050a53fc4b539f4f4716bab53c07, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: 8222f0e3aeeb4fc4975aaead6cf7afbe, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: c9c18dbd013d42ae8c221e6205e4d49c, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: d8ea29cc80524de8affe17b930cd75c1, type: 3}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 0.95
+ value: 0
+ inSlope: Infinity
+ outSlope: Infinity
+ tangentMode: 103
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_Enabled
+ path:
+ classID: 60
+ script: {fileID: 0}
+ flags: 0
+ m_EulerEditorCurves: []
+ m_HasGenericRootTransform: 1
+ m_HasMotionFloatCurves: 0
+ m_Events: []
+--- !u!74 &-1120528782975220419
+AnimationClip:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Recorded (2)
+ serializedVersion: 7
+ m_Legacy: 0
+ m_Compressed: 0
+ m_UseHighQualityCurve: 1
+ m_RotationCurves: []
+ m_CompressedRotationCurves: []
+ m_EulerCurves: []
+ m_PositionCurves: []
+ m_ScaleCurves: []
+ m_FloatCurves:
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 1
+ value: 6.75
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.8166666
+ value: 3
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: Lens.OrthographicSize
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
+ flags: 0
+ m_PPtrCurves: []
+ m_SampleRate: 60
+ m_WrapMode: 0
+ m_Bounds:
+ m_Center: {x: 0, y: 0, z: 0}
+ m_Extent: {x: 0, y: 0, z: 0}
+ m_ClipBindingConstant:
+ genericBindings:
+ - serializedVersion: 2
+ path: 0
+ attribute: 2514370844
+ script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
+ typeID: 114
+ customType: 0
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ pptrCurveMapping: []
+ m_AnimationClipSettings:
+ serializedVersion: 2
+ m_AdditiveReferencePoseClip: {fileID: 0}
+ m_AdditiveReferencePoseTime: 0
+ m_StartTime: 0
+ m_StopTime: 2.8166666
+ m_OrientationOffsetY: 0
+ m_Level: 0
+ m_CycleOffset: 0
+ m_HasAdditiveReferencePose: 0
+ m_LoopTime: 0
+ m_LoopBlend: 0
+ m_LoopBlendOrientation: 0
+ m_LoopBlendPositionY: 0
+ m_LoopBlendPositionXZ: 0
+ m_KeepOriginalOrientation: 0
+ m_KeepOriginalPositionY: 1
+ m_KeepOriginalPositionXZ: 0
+ m_HeightFromFeet: 0
+ m_Mirror: 0
+ m_EditorCurves:
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 1
+ value: 6.75
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 2.8166666
+ value: 3
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: Lens.OrthographicSize
+ path:
+ classID: 114
+ script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
+ flags: 0
+ m_EulerEditorCurves: []
+ m_HasGenericRootTransform: 0
+ m_HasMotionFloatCurves: 0
+ m_Events: []
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: bfda56da833e2384a9677cd3c976a436, type: 3}
+ m_Name: SurfacingTimeline
+ m_EditorClassIdentifier:
+ m_Version: 0
+ m_Tracks:
+ - {fileID: 7536617106820686252}
+ - {fileID: 1284158391674687369}
+ - {fileID: -4039891455399305819}
+ m_FixedDuration: 0
+ m_EditorSettings:
+ m_Framerate: 60
+ m_ScenePreview: 1
+ m_DurationMode: 0
+ m_MarkerTrack: {fileID: 0}
+--- !u!114 &1284158391674687369
+MonoBehaviour:
+ m_ObjectHideFlags: 1
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: d21dcc2386d650c4597f3633c75a1f98, type: 3}
+ m_Name: Animation Track (1)
+ m_EditorClassIdentifier:
+ m_Version: 3
+ m_AnimClip: {fileID: 0}
+ m_Locked: 0
+ m_Muted: 0
+ m_CustomPlayableFullTypename:
+ m_Curves: {fileID: 0}
+ m_Parent: {fileID: 11400000}
+ m_Children: []
+ m_Clips: []
+ m_Markers:
+ m_Objects: []
+ m_InfiniteClipPreExtrapolation: 1
+ m_InfiniteClipPostExtrapolation: 1
+ m_InfiniteClipOffsetPosition: {x: 0, y: 1.24, z: 0}
+ m_InfiniteClipOffsetEulerAngles: {x: -0, y: 0, z: 0}
+ m_InfiniteClipTimeOffset: 0
+ m_InfiniteClipRemoveOffset: 0
+ m_InfiniteClipApplyFootIK: 1
+ mInfiniteClipLoop: 0
+ m_MatchTargetFields: 63
+ m_Position: {x: 0, y: 0, z: 0}
+ m_EulerAngles: {x: 0, y: 0, z: 0}
+ m_AvatarMask: {fileID: 0}
+ m_ApplyAvatarMask: 1
+ m_TrackOffset: 0
+ m_InfiniteClip: {fileID: 3844679312356863604}
+ m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_Rotation: {x: 0, y: 0, z: 0, w: 1}
+ m_ApplyOffsets: 0
+--- !u!74 &3844679312356863604
+AnimationClip:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Recorded
+ serializedVersion: 7
+ m_Legacy: 0
+ m_Compressed: 0
+ m_UseHighQualityCurve: 1
+ m_RotationCurves: []
+ m_CompressedRotationCurves: []
+ m_EulerCurves: []
+ m_PositionCurves:
+ - curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: {x: 0, y: 0, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ - serializedVersion: 3
+ time: 1.8333334
+ value: {x: 0, y: -9.16, z: 0}
+ inSlope: {x: 0, y: 0, z: 0}
+ outSlope: {x: 0, y: 0, z: 0}
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ path:
+ m_ScaleCurves: []
+ m_FloatCurves: []
+ m_PPtrCurves: []
+ m_SampleRate: 60
+ m_WrapMode: 0
+ m_Bounds:
+ m_Center: {x: 0, y: 0, z: 0}
+ m_Extent: {x: 0, y: 0, z: 0}
+ m_ClipBindingConstant:
+ genericBindings:
+ - serializedVersion: 2
+ path: 0
+ attribute: 1
+ script: {fileID: 0}
+ typeID: 4
+ customType: 0
+ isPPtrCurve: 0
+ isIntCurve: 0
+ isSerializeReferenceCurve: 0
+ pptrCurveMapping: []
+ m_AnimationClipSettings:
+ serializedVersion: 2
+ m_AdditiveReferencePoseClip: {fileID: 0}
+ m_AdditiveReferencePoseTime: 0
+ m_StartTime: 0
+ m_StopTime: 1.8333334
+ m_OrientationOffsetY: 0
+ m_Level: 0
+ m_CycleOffset: 0
+ m_HasAdditiveReferencePose: 0
+ m_LoopTime: 0
+ m_LoopBlend: 0
+ m_LoopBlendOrientation: 0
+ m_LoopBlendPositionY: 0
+ m_LoopBlendPositionXZ: 0
+ m_KeepOriginalOrientation: 0
+ m_KeepOriginalPositionY: 1
+ m_KeepOriginalPositionXZ: 0
+ m_HeightFromFeet: 0
+ m_Mirror: 0
+ m_EditorCurves:
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.8333334
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_LocalPosition.x
+ path:
+ classID: 4
+ script: {fileID: 0}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.8333334
+ value: -9.16
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_LocalPosition.y
+ path:
+ classID: 4
+ script: {fileID: 0}
+ flags: 0
+ - serializedVersion: 2
+ curve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ - serializedVersion: 3
+ time: 1.8333334
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 136
+ weightedMode: 0
+ inWeight: 0.33333334
+ outWeight: 0.33333334
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ attribute: m_LocalPosition.z
+ path:
+ classID: 4
+ script: {fileID: 0}
+ flags: 0
+ m_EulerEditorCurves: []
+ m_HasGenericRootTransform: 1
+ m_HasMotionFloatCurves: 0
+ m_Events: []
+--- !u!114 &7536617106820686252
+MonoBehaviour:
+ m_ObjectHideFlags: 1
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: d21dcc2386d650c4597f3633c75a1f98, type: 3}
+ m_Name: Animation Track
+ m_EditorClassIdentifier:
+ m_Version: 3
+ m_AnimClip: {fileID: 0}
+ m_Locked: 0
+ m_Muted: 0
+ m_CustomPlayableFullTypename:
+ m_Curves: {fileID: 0}
+ m_Parent: {fileID: 11400000}
+ m_Children: []
+ m_Clips: []
+ m_Markers:
+ m_Objects: []
+ m_InfiniteClipPreExtrapolation: 1
+ m_InfiniteClipPostExtrapolation: 1
+ m_InfiniteClipOffsetPosition: {x: 0, y: 2.9799, z: 0}
+ m_InfiniteClipOffsetEulerAngles: {x: -0, y: 0, z: 0}
+ m_InfiniteClipTimeOffset: 0
+ m_InfiniteClipRemoveOffset: 0
+ m_InfiniteClipApplyFootIK: 1
+ mInfiniteClipLoop: 0
+ m_MatchTargetFields: 63
+ m_Position: {x: 0, y: 0, z: 0}
+ m_EulerAngles: {x: 0, y: 0, z: 0}
+ m_AvatarMask: {fileID: 0}
+ m_ApplyAvatarMask: 1
+ m_TrackOffset: 0
+ m_InfiniteClip: {fileID: -3085705704792956194}
+ m_OpenClipOffsetRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_Rotation: {x: 0, y: 0, z: 0, w: 1}
+ m_ApplyOffsets: 0
diff --git a/Assets/Playables/SurfacingTimeline.playable.meta b/Assets/Playables/SurfacingTimeline.playable.meta
new file mode 100644
index 00000000..7f454016
--- /dev/null
+++ b/Assets/Playables/SurfacingTimeline.playable.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5ecd3cfdb172df5439e4522c15c48f75
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scenes/MiniGames/DivingForPictures.unity b/Assets/Scenes/MiniGames/DivingForPictures.unity
index 36a7fbf4..8ea86f34 100644
--- a/Assets/Scenes/MiniGames/DivingForPictures.unity
+++ b/Assets/Scenes/MiniGames/DivingForPictures.unity
@@ -248,6 +248,7 @@ GameObject:
- component: {fileID: 173052725}
- component: {fileID: 173052727}
- component: {fileID: 173052726}
+ - component: {fileID: 173052728}
m_Layer: 0
m_Name: Rope2
m_TagString: Untagged
@@ -339,15 +340,15 @@ LineRenderer:
m_SortingOrder: 0
m_Positions:
- {x: 0, y: 4.1716814, z: 0}
- - {x: -0.0011514801, y: 3.9187107, z: 0}
- - {x: -0.00230296, y: 3.6922278, z: 0}
- - {x: -0.0034544398, y: 3.4922323, z: 0}
- - {x: -0.00460592, y: 3.3187256, z: 0}
- - {x: -0.0057574, y: 3.1717062, z: 0}
- - {x: -0.0069088796, y: 3.0511749, z: 0}
- - {x: -0.008060359, y: 2.9571314, z: 0}
- - {x: -0.00921184, y: 2.8895762, z: 0}
- - {x: -0.010363319, y: 2.8485086, z: 0}
+ - {x: -0.0011514801, y: 3.9551861, z: 0}
+ - {x: -0.00230296, y: 3.757073, z: 0}
+ - {x: -0.0034544398, y: 3.577342, z: 0}
+ - {x: -0.00460592, y: 3.4159937, z: 0}
+ - {x: -0.0057574, y: 3.273027, z: 0}
+ - {x: -0.0069088796, y: 3.1484427, z: 0}
+ - {x: -0.008060359, y: 3.042241, z: 0}
+ - {x: -0.00921184, y: 2.9544215, z: 0}
+ - {x: -0.010363319, y: 2.884984, z: 0}
- {x: -0.0115148, y: 2.833929, z: 0}
m_Parameters:
serializedVersion: 3
@@ -417,6 +418,28 @@ LineRenderer:
m_UseWorldSpace: 1
m_Loop: 0
m_ApplyActiveColorSpace: 1
+--- !u!114 &173052728
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 173052724}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ breakPosition: 0.5
+ breakEffect: {fileID: 0}
+ breakSound: {fileID: 0}
+ ropeFollowSpeed: 5
+ ropeTrailing: 0.2
+ ropeGravityStrength: 9.8
+ ropeVerticalHangStrength: 2
+ ropeDamping: 0.3
+ initialSeparationDistance: 0.1
+ initialFallImpulse: 2
--- !u!1 &224729330
GameObject:
m_ObjectHideFlags: 0
@@ -427,6 +450,7 @@ GameObject:
m_Component:
- component: {fileID: 224729333}
- component: {fileID: 224729332}
+ - component: {fileID: 224729334}
m_Layer: 0
m_Name: CinemachineCamera
m_TagString: Untagged
@@ -492,6 +516,28 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!95 &224729334
+Animator:
+ serializedVersion: 7
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 224729330}
+ m_Enabled: 1
+ m_Avatar: {fileID: 0}
+ m_Controller: {fileID: 0}
+ 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!1 &323864663
GameObject:
m_ObjectHideFlags: 0
@@ -600,6 +646,14 @@ MonoBehaviour:
spawnCooldown: 5
basePoints: 10
depthMultiplier: 2
+ playerRopes:
+ - {fileID: 1435210811}
+ - {fileID: 1062017697}
+ - {fileID: 173052728}
+ speedTransitionDuration: 2
+ surfacingSpeedFactor: 3
+ surfacingSpawnDelay: 3
+ surfacingTimeline: {fileID: 2064311130}
--- !u!4 &424805726
Transform:
m_ObjectHideFlags: 0
@@ -615,6 +669,116 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &461301695
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 461301697}
+ - component: {fileID: 461301696}
+ - component: {fileID: 461301698}
+ m_Layer: 0
+ m_Name: DivingBackground_0
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!212 &461301696
+SpriteRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 461301695}
+ m_Enabled: 1
+ m_CastShadows: 0
+ m_ReceiveShadows: 0
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 0
+ m_RayTraceProcedural: 0
+ m_RayTracingAccelStructBuildFlagsOverride: 0
+ m_RayTracingAccelStructBuildFlags: 1
+ m_SmallMeshCulling: 1
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 0
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 622133659
+ m_SortingLayer: -1
+ m_SortingOrder: 0
+ m_Sprite: {fileID: 5958968447627082961, guid: ad9b785acb09cb247ae2c8cd895863de, type: 3}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_FlipX: 0
+ m_FlipY: 0
+ m_DrawMode: 0
+ m_Size: {x: 10.803711, y: 19.81}
+ m_AdaptiveModeThreshold: 0.5
+ m_SpriteTileMode: 0
+ m_WasSpriteAssigned: 1
+ m_MaskInteraction: 0
+ m_SpriteSortPoint: 0
+--- !u!4 &461301697
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 461301695}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 1.24, z: 0}
+ m_LocalScale: {x: 0.81438, y: 0.81438, z: 0.81438}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!95 &461301698
+Animator:
+ serializedVersion: 7
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 461301695}
+ m_Enabled: 1
+ m_Avatar: {fileID: 0}
+ m_Controller: {fileID: 0}
+ 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!1 &730962732
GameObject:
m_ObjectHideFlags: 0
@@ -718,6 +882,7 @@ GameObject:
- component: {fileID: 747976402}
- component: {fileID: 747976403}
- component: {fileID: 747976404}
+ - component: {fileID: 747976405}
m_Layer: 0
m_Name: BottleMarine
m_TagString: Player
@@ -948,6 +1113,28 @@ MonoBehaviour:
blinkRate: 0.15
damageColorAlpha: 0.7
targetSpriteRenderer: {fileID: 730962734}
+--- !u!95 &747976405
+Animator:
+ serializedVersion: 7
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 747976396}
+ m_Enabled: 1
+ m_Avatar: {fileID: 0}
+ m_Controller: {fileID: 0}
+ 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!1 &824396214
GameObject:
m_ObjectHideFlags: 0
@@ -1076,6 +1263,7 @@ MonoBehaviour:
useObjectPooling: 1
initialPoolSize: 10
maxPoolSize: 30
+ surfacingSpeedFactor: 0.5
--- !u!4 &1003335105
Transform:
m_ObjectHideFlags: 0
@@ -1102,6 +1290,7 @@ GameObject:
- component: {fileID: 1062017694}
- component: {fileID: 1062017696}
- component: {fileID: 1062017695}
+ - component: {fileID: 1062017697}
m_Layer: 0
m_Name: Rope3
m_TagString: Untagged
@@ -1193,15 +1382,15 @@ LineRenderer:
m_SortingOrder: 0
m_Positions:
- {x: 0, y: 4.1716814, z: 0}
- - {x: 0.036271624, y: 3.927396, z: 0}
- - {x: 0.07254324, y: 3.7076683, z: 0}
- - {x: 0.10881486, y: 3.5124984, z: 0}
- - {x: 0.14508648, y: 3.3418865, z: 0}
- - {x: 0.1813581, y: 3.195832, z: 0}
- - {x: 0.21762972, y: 3.0743358, z: 0}
- - {x: 0.25390133, y: 2.9773972, z: 0}
- - {x: 0.29017296, y: 2.905017, z: 0}
- - {x: 0.32644457, y: 2.857194, z: 0}
+ - {x: 0.036271624, y: 3.9653695, z: 0}
+ - {x: 0.07254324, y: 3.7751768, z: 0}
+ - {x: 0.10881486, y: 3.6011028, z: 0}
+ - {x: 0.14508648, y: 3.443149, z: 0}
+ - {x: 0.1813581, y: 3.3013139, z: 0}
+ - {x: 0.21762972, y: 3.1755984, z: 0}
+ - {x: 0.25390133, y: 3.066002, z: 0}
+ - {x: 0.29017296, y: 2.9725251, z: 0}
+ - {x: 0.32644457, y: 2.8951674, z: 0}
- {x: 0.3627162, y: 2.833929, z: 0}
m_Parameters:
serializedVersion: 3
@@ -1271,6 +1460,28 @@ LineRenderer:
m_UseWorldSpace: 1
m_Loop: 0
m_ApplyActiveColorSpace: 1
+--- !u!114 &1062017697
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1062017693}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ breakPosition: 0.5
+ breakEffect: {fileID: 0}
+ breakSound: {fileID: 0}
+ ropeFollowSpeed: 5
+ ropeTrailing: 0.2
+ ropeGravityStrength: 9.8
+ ropeVerticalHangStrength: 2
+ ropeDamping: 0.3
+ initialSeparationDistance: 0.1
+ initialFallImpulse: 2
--- !u!1 &1063641111
GameObject:
m_ObjectHideFlags: 0
@@ -1283,6 +1494,7 @@ GameObject:
- component: {fileID: 1063641113}
- component: {fileID: 1063641112}
- component: {fileID: 1063641115}
+ - component: {fileID: 1063641116}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
@@ -1307,8 +1519,8 @@ Camera:
m_GameObject: {fileID: 1063641111}
m_Enabled: 1
serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+ m_ClearFlags: 2
+ m_BackGroundColor: {r: 0.5722232, g: 0.6321867, b: 0.7264151, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
@@ -1396,6 +1608,50 @@ MonoBehaviour:
m_PostInfinity: 2
m_RotationOrder: 4
CustomBlends: {fileID: 0}
+--- !u!114 &1063641116
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1063641111}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_RenderShadows: 1
+ m_RequiresDepthTextureOption: 2
+ m_RequiresOpaqueTextureOption: 2
+ m_CameraType: 0
+ m_Cameras: []
+ m_RendererIndex: -1
+ m_VolumeLayerMask:
+ serializedVersion: 2
+ m_Bits: 1
+ m_VolumeTrigger: {fileID: 0}
+ m_VolumeFrameworkUpdateModeOption: 2
+ m_RenderPostProcessing: 0
+ m_Antialiasing: 0
+ m_AntialiasingQuality: 2
+ m_StopNaN: 0
+ m_Dithering: 0
+ m_ClearDepth: 1
+ m_AllowXRRendering: 1
+ m_AllowHDROutput: 1
+ m_UseScreenCoordOverride: 0
+ m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
+ m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
+ m_RequiresDepthTexture: 0
+ m_RequiresColorTexture: 0
+ m_Version: 2
+ m_TaaSettings:
+ m_Quality: 3
+ m_FrameInfluence: 0.1
+ m_JitterScale: 1
+ m_MipBias: 0
+ m_VarianceClampScale: 0.9
+ m_ContrastAdaptiveSharpening: 0
--- !u!1 &1224833348
GameObject:
m_ObjectHideFlags: 0
@@ -1666,15 +1922,15 @@ LineRenderer:
m_SortingOrder: 0
m_Positions:
- {x: 0, y: 4.1716814, z: 0}
- - {x: -0.03339292, y: 3.9260902, z: 0}
- - {x: -0.066785835, y: 3.705347, z: 0}
- - {x: -0.10017875, y: 3.5094519, z: 0}
- - {x: -0.13357168, y: 3.3384047, z: 0}
- - {x: -0.16696459, y: 3.1922054, z: 0}
- - {x: -0.20035751, y: 3.0708542, z: 0}
- - {x: -0.2337504, y: 2.9743507, z: 0}
- - {x: -0.26714337, y: 2.9026957, z: 0}
- - {x: -0.30053627, y: 2.8558884, z: 0}
+ - {x: -0.03339292, y: 3.9638388, z: 0}
+ - {x: -0.066785835, y: 3.7724557, z: 0}
+ - {x: -0.10017875, y: 3.5975313, z: 0}
+ - {x: -0.13357168, y: 3.4390674, z: 0}
+ - {x: -0.16696459, y: 3.2970622, z: 0}
+ - {x: -0.20035751, y: 3.1715167, z: 0}
+ - {x: -0.2337504, y: 3.0624304, z: 0}
+ - {x: -0.26714337, y: 2.969804, z: 0}
+ - {x: -0.30053627, y: 2.8936367, z: 0}
- {x: -0.33392918, y: 2.833929, z: 0}
m_Parameters:
serializedVersion: 3
@@ -1744,51 +2000,28 @@ LineRenderer:
m_UseWorldSpace: 1
m_Loop: 0
m_ApplyActiveColorSpace: 1
---- !u!23 &1435210811
-MeshRenderer:
+--- !u!114 &1435210811
+MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1435210807}
m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_StaticShadowCaster: 0
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RayTracingMode: 2
- m_RayTraceProcedural: 0
- m_RayTracingAccelStructBuildFlagsOverride: 0
- m_RayTracingAccelStructBuildFlags: 1
- m_SmallMeshCulling: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_ReceiveGI: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 1
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_AdditionalVertexStreams: {fileID: 0}
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ breakPosition: 0.5
+ breakEffect: {fileID: 0}
+ breakSound: {fileID: 0}
+ ropeFollowSpeed: 5
+ ropeTrailing: 0.2
+ ropeGravityStrength: 9.8
+ ropeVerticalHangStrength: 2
+ ropeDamping: 0.3
+ initialSeparationDistance: 0.1
+ initialFallImpulse: 2
--- !u!1 &1679185997
GameObject:
m_ObjectHideFlags: 0
@@ -1842,7 +2075,7 @@ MonoBehaviour:
- {fileID: 2956826569642009690, guid: 7f7f10ca24a5afe46be797daea64111a, type: 3}
initialTileCount: 3
tileSpawnBuffer: 1
- moveSpeed: 3
+ moveSpeed: 2
speedUpFactor: 0
speedUpInterval: 0
maxMoveSpeed: 12
@@ -1855,6 +2088,10 @@ MonoBehaviour:
onTileDestroyed:
m_PersistentCalls:
m_Calls: []
+ velocityCalculationInterval: 0.5
+ onLastTileLeft:
+ m_PersistentCalls:
+ m_Calls: []
--- !u!1 &1834056336
GameObject:
m_ObjectHideFlags: 0
@@ -2004,6 +2241,61 @@ Transform:
m_Children: []
m_Father: {fileID: 2106431002}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &2064311128
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2064311129}
+ - component: {fileID: 2064311130}
+ m_Layer: 0
+ m_Name: SurfacingTimeline
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &2064311129
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2064311128}
+ serializedVersion: 2
+ 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}
+--- !u!320 &2064311130
+PlayableDirector:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2064311128}
+ m_Enabled: 1
+ serializedVersion: 3
+ m_PlayableAsset: {fileID: 11400000, guid: 5ecd3cfdb172df5439e4522c15c48f75, type: 2}
+ m_InitialState: 0
+ m_WrapMode: 0
+ m_DirectorUpdateMode: 1
+ m_InitialTime: 0
+ m_SceneBindings:
+ - key: {fileID: 7536617106820686252, guid: 5ecd3cfdb172df5439e4522c15c48f75, type: 2}
+ value: {fileID: 747976405}
+ - key: {fileID: 1284158391674687369, guid: 5ecd3cfdb172df5439e4522c15c48f75, type: 2}
+ value: {fileID: 461301698}
+ - key: {fileID: -4039891455399305819, guid: 5ecd3cfdb172df5439e4522c15c48f75, type: 2}
+ value: {fileID: 224729334}
+ m_ExposedReferences:
+ m_References: []
--- !u!1 &2106431001
GameObject:
m_ObjectHideFlags: 0
@@ -2017,7 +2309,7 @@ GameObject:
- component: {fileID: 2106431004}
m_Layer: 0
m_Name: Rock
- m_TagString: Untagged
+ m_TagString: Rock
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
@@ -2095,3 +2387,5 @@ SceneRoots:
- {fileID: 116234201}
- {fileID: 824396217}
- {fileID: 323864665}
+ - {fileID: 461301697}
+ - {fileID: 2064311129}
diff --git a/Assets/Scripts/AppleHillsScripts.asmdef b/Assets/Scripts/AppleHillsScripts.asmdef
index 0a67cb12..9b0a338d 100644
--- a/Assets/Scripts/AppleHillsScripts.asmdef
+++ b/Assets/Scripts/AppleHillsScripts.asmdef
@@ -7,7 +7,8 @@
"AstarPathfindingProject",
"Unity.ResourceManager",
"Unity.InputSystem",
- "Unity.TextMeshPro"
+ "Unity.TextMeshPro",
+ "OptimizedRope"
],
"includePlatforms": [],
"excludePlatforms": [],
diff --git a/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs
index 31758f57..d4859a84 100644
--- a/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs
+++ b/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs
@@ -26,10 +26,15 @@ namespace Minigames.DivingForPictures
public int initialPoolSize = 10;
public int maxPoolSize = 30;
+ [Header("Surfacing Settings")]
+ [Tooltip("Factor to multiply bubble speed by when surfacing (0.5 = half speed)")]
+ [SerializeField] private float surfacingSpeedFactor = 0.5f;
+
private float _timer;
private float _nextSpawnInterval;
private BubblePool _bubblePool;
private Camera _mainCamera; // Cache camera reference
+ private bool _isSurfacing = false;
void Awake()
{
@@ -98,7 +103,18 @@ namespace Minigames.DivingForPictures
}
// Randomize bubble properties
- bubble.speed = Random.Range(speedRange.x, speedRange.y);
+ float baseSpeed = Random.Range(speedRange.x, speedRange.y);
+
+ // Apply surfacing speed reduction if needed
+ if (_isSurfacing)
+ {
+ bubble.speed = baseSpeed * surfacingSpeedFactor;
+ }
+ else
+ {
+ bubble.speed = baseSpeed;
+ }
+
bubble.wobbleSpeed = Random.Range(wobbleSpeedRange.x, wobbleSpeedRange.y);
// Set base scale (initial size) for the bubble
@@ -119,6 +135,25 @@ namespace Minigames.DivingForPictures
bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
}
+ ///
+ /// Start surfacing mode - slow down all bubbles
+ ///
+ public void StartSurfacing()
+ {
+ if (_isSurfacing) return; // Already surfacing
+
+ _isSurfacing = true;
+
+ // Slow down all existing bubbles
+ Bubble[] activeBubbles = FindObjectsOfType();
+ foreach (Bubble bubble in activeBubbles)
+ {
+ bubble.speed *= surfacingSpeedFactor;
+ }
+
+ Debug.Log($"[BubbleSpawner] Started surfacing mode. Bubbles slowed to {surfacingSpeedFactor * 100}% speed.");
+ }
+
///
/// Logs the current pool statistics for debugging
///
diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs
index c3a94f56..d97285b4 100644
--- a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs
+++ b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs
@@ -1,7 +1,9 @@
using UnityEngine;
using System.Collections.Generic;
using System;
+using System.Collections;
using UnityEngine.Events;
+using UnityEngine.Playables;
namespace Minigames.DivingForPictures
{
@@ -31,6 +33,20 @@ namespace Minigames.DivingForPictures
[Tooltip("Additional points per depth unit")]
[SerializeField] private int depthMultiplier = 10;
+ [Header("Rope Damage System")]
+ [Tooltip("Ropes that will break one by one as player takes damage")]
+ [SerializeField] private RopeBreaker[] playerRopes;
+
+ [Header("Surfacing Settings")]
+ [Tooltip("Duration in seconds for speed transition when surfacing")]
+ [SerializeField] private float speedTransitionDuration = 2.0f;
+ [Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")]
+ [SerializeField] private float surfacingSpeedFactor = 3.0f;
+ [Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")]
+ [SerializeField] private float surfacingSpawnDelay = 5.0f;
+ [Tooltip("Reference to the PlayableDirector that will play the surfacing timeline")]
+ [SerializeField] private PlayableDirector surfacingTimeline;
+
// Private state variables
private int playerScore = 0;
private float currentSpawnProbability;
@@ -38,14 +54,32 @@ namespace Minigames.DivingForPictures
private float timeSinceLastSpawn = 0f;
private List activeMonsters = new List();
+ // Velocity management
+ // Velocity state tracking
+ private float _currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed
+ private Coroutine _velocityTransitionCoroutine;
+ private Coroutine _surfacingSequenceCoroutine;
+
// Public properties
public int PlayerScore => playerScore;
+ public float CurrentVelocityFactor => _currentVelocityFactor;
// Events
public event Action OnScoreChanged;
public event Action OnMonsterSpawned;
public event Action OnPictureTaken;
public event Action OnSpawnProbabilityChanged;
+ public event Action OnGameOver;
+ public event Action OnRopeBroken; // Passes remaining ropes count
+ public event Action OnVelocityFactorChanged;
+
+ // Private state variables for rope system
+ private int currentRopeIndex = 0;
+ private bool isGameOver = false;
+ private bool _isSurfacing = false;
+
+ // Used to track if we're currently surfacing
+ public bool IsSurfacing => _isSurfacing;
private void Awake()
{
@@ -64,6 +98,18 @@ namespace Minigames.DivingForPictures
{
Debug.LogWarning("No TrenchTileSpawner found in scene. Monster spawning won't work.");
}
+
+ // Subscribe to player damage events
+ PlayerCollisionBehavior.OnDamageTaken += OnPlayerDamageTaken;
+
+ // Validate rope references
+ ValidateRopeReferences();
+ }
+
+ private void OnDestroy()
+ {
+ // Unsubscribe from events when the manager is destroyed
+ PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
}
private void Update()
@@ -92,6 +138,9 @@ namespace Minigames.DivingForPictures
if (spawnPoints.Length == 0) return;
+ // If we're surfacing, don't spawn new monsters
+ if (_isSurfacing) return;
+
bool forceSpawn = timeSinceLastSpawn >= guaranteedSpawnTime;
bool onCooldown = timeSinceLastSpawn < spawnCooldown;
@@ -176,6 +225,335 @@ namespace Minigames.DivingForPictures
monster.OnMonsterDespawned -= OnMonsterDespawned;
}
+ ///
+ /// Called when the player takes damage from any collision
+ ///
+ private void OnPlayerDamageTaken()
+ {
+ if (isGameOver) return;
+
+ // Break the next rope in sequence
+ BreakNextRope();
+
+ // Check if all ropes are broken
+ if (currentRopeIndex >= playerRopes.Length)
+ {
+ TriggerGameOver();
+ }
+ else
+ {
+ // Notify listeners about rope break and remaining ropes
+ int remainingRopes = playerRopes.Length - currentRopeIndex;
+ OnRopeBroken?.Invoke(remainingRopes);
+
+ Debug.Log($"[DivingGameManager] Rope broken! {remainingRopes} ropes remaining.");
+ }
+ }
+
+ ///
+ /// Breaks the next available rope in the sequence
+ ///
+ private void BreakNextRope()
+ {
+ if (currentRopeIndex < playerRopes.Length)
+ {
+ RopeBreaker ropeToBreak = playerRopes[currentRopeIndex];
+
+ if (ropeToBreak != null)
+ {
+ // Let the RopeBreaker component handle the breaking, effects, and sounds
+ ropeToBreak.BreakRope();
+ }
+ else
+ {
+ Debug.LogWarning($"[DivingGameManager] Rope at index {currentRopeIndex} is null!");
+ }
+
+ // Move to the next rope regardless if current was null
+ currentRopeIndex++;
+ }
+ }
+
+ ///
+ /// Manually break a rope (for testing or external events)
+ ///
+ public void ForceBreakRope()
+ {
+ if (!isGameOver)
+ {
+ OnPlayerDamageTaken();
+ }
+ }
+
+ ///
+ /// Triggers game over state when all ropes are broken
+ ///
+ private void TriggerGameOver()
+ {
+ if (isGameOver) return;
+
+ isGameOver = true;
+ Debug.Log("[DivingGameManager] Game Over! All ropes broken. Starting surfacing sequence...");
+
+ // Fire game over event
+ OnGameOver?.Invoke();
+
+ // Start surfacing instead of directly ending the game
+ StartSurfacing();
+ }
+
+ ///
+ /// Validates rope references and logs warnings if any are missing
+ ///
+ private void ValidateRopeReferences()
+ {
+ if (playerRopes == null || playerRopes.Length == 0)
+ {
+ Debug.LogWarning("[DivingGameManager] No ropes assigned to break! Damage system won't work properly.");
+ return;
+ }
+
+ for (int i = 0; i < playerRopes.Length; i++)
+ {
+ if (playerRopes[i] == null)
+ {
+ Debug.LogWarning($"[DivingGameManager] Rope at index {i} is null!");
+ }
+ }
+ }
+
+ ///
+ /// Resets the rope system for a new game
+ ///
+ public void ResetRopeSystem()
+ {
+ // Reset rope state
+ currentRopeIndex = 0;
+ isGameOver = false;
+
+ // Restore all broken ropes
+ if (playerRopes != null)
+ {
+ foreach (var rope in playerRopes)
+ {
+ if (rope != null)
+ {
+ rope.RestoreRope();
+ }
+ }
+ }
+
+ Debug.Log("[DivingGameManager] Rope system reset.");
+ }
+
+ ///
+ /// Starts the surfacing mode - reverses trench direction and adjusts all spawned entities
+ ///
+ public void StartSurfacing()
+ {
+ if (_isSurfacing) return; // Already surfacing
+
+ _isSurfacing = true;
+
+ // 1. Initiate smooth velocity transition to surfacing speed
+ float targetVelocityFactor = -1.0f * surfacingSpeedFactor;
+ SetVelocityFactor(targetVelocityFactor);
+
+ // 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic)
+ TrenchTileSpawner tileSpawner = FindFirstObjectByType();
+ if (tileSpawner != null)
+ {
+ // Subscribe to velocity changes if not already subscribed
+ OnVelocityFactorChanged -= tileSpawner.OnVelocityFactorChanged;
+ OnVelocityFactorChanged += tileSpawner.OnVelocityFactorChanged;
+
+ // Subscribe to the last tile event
+ tileSpawner.onLastTileLeft.RemoveListener(OnLastTileLeft);
+ tileSpawner.onLastTileLeft.AddListener(OnLastTileLeft);
+
+ // Tell spawner to reverse spawn/despawn logic
+ tileSpawner.StartSurfacing();
+
+ // Immediately send current velocity factor
+ tileSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
+ }
+
+ // Handle the Rock object - disable components and animate it falling offscreen
+ GameObject rockObject = GameObject.FindGameObjectWithTag("Rock");
+ if (rockObject != null)
+ {
+ // Disable all components except Transform on the rock object (not its children)
+ foreach (Component component in rockObject.GetComponents())
+ {
+ if (!(component is Transform))
+ {
+ if (component is Behaviour behaviour)
+ {
+ behaviour.enabled = false;
+ }
+ }
+ }
+
+ // Start coroutine to animate the rock falling offscreen
+ StartCoroutine(MoveRockOffscreen(rockObject.transform));
+
+ Debug.Log("[DivingGameManager] Disabled rock components and animating it offscreen");
+ }
+
+ // Handle the Player object - disable components and reset X position
+ GameObject playerObject = GameObject.FindGameObjectWithTag("Player");
+ if (playerObject != null)
+ {
+ // Disable all components except Transform and Animator on the player object (not its children)
+ foreach (Component component in playerObject.GetComponents())
+ {
+ if (!(component is Transform) && !(component is Animator))
+ {
+ if (component is Behaviour behaviour)
+ {
+ behaviour.enabled = false;
+ }
+ }
+ }
+
+ // Start coroutine to reset X position to 0 over 1 second
+ StartCoroutine(ResetPlayerPosition(playerObject.transform));
+
+ Debug.Log("[DivingGameManager] Disabled player components (keeping Animator) and resetting position");
+ }
+
+ // 3. Find bubble spawner and slow down existing bubbles (no velocity management needed)
+ BubbleSpawner bubbleSpawner = FindFirstObjectByType();
+ if (bubbleSpawner != null)
+ {
+ bubbleSpawner.StartSurfacing();
+ }
+
+ // 4. Find obstacle spawner and set up for velocity changes
+ ObstacleSpawner obstacleSpawner = FindFirstObjectByType();
+ if (obstacleSpawner != null)
+ {
+ // Subscribe to velocity changes
+ OnVelocityFactorChanged -= obstacleSpawner.OnVelocityFactorChanged;
+ OnVelocityFactorChanged += obstacleSpawner.OnVelocityFactorChanged;
+
+ // Tell spawner to reverse spawn/despawn logic
+ obstacleSpawner.StartSurfacing();
+
+ // Immediately send current velocity factor
+ obstacleSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
+ }
+
+ // Start the surfacing sequence coroutine
+ if (_surfacingSequenceCoroutine != null)
+ {
+ StopCoroutine(_surfacingSequenceCoroutine);
+ }
+ _surfacingSequenceCoroutine = StartCoroutine(SurfacingSequence());
+
+ Debug.Log($"[DivingGameManager] Started surfacing with target velocity factor: {targetVelocityFactor}");
+ }
+
+ ///
+ /// Coroutine to animate the rock falling below the screen
+ ///
+ private IEnumerator MoveRockOffscreen(Transform rockTransform)
+ {
+ Vector3 startPosition = rockTransform.position;
+
+ // Calculate position below the screen
+ Camera mainCamera = Camera.main;
+ if (mainCamera == null)
+ {
+ Debug.LogWarning("[DivingGameManager] Cannot find main camera to calculate offscreen position");
+ yield break;
+ }
+
+ // Get a position below the bottom of the screen
+ Vector3 offscreenPosition = mainCamera.ViewportToWorldPoint(new Vector3(0.5f, -0.2f, mainCamera.nearClipPlane));
+ Vector3 targetPosition = new Vector3(startPosition.x, offscreenPosition.y, startPosition.z);
+
+ float duration = 2.0f; // Animation duration in seconds
+ float elapsed = 0f;
+
+ while (elapsed < duration)
+ {
+ elapsed += Time.deltaTime;
+ float t = Mathf.Clamp01(elapsed / duration);
+
+ // Use an easing function that accelerates to simulate falling
+ float easedT = t * t; // Quadratic easing
+
+ rockTransform.position = Vector3.Lerp(startPosition, targetPosition, easedT);
+ yield return null;
+ }
+
+ // Ensure final position is exactly at target
+ rockTransform.position = targetPosition;
+ }
+
+ ///
+ /// Coroutine to reset the player's X position to 0 over time
+ ///
+ private IEnumerator ResetPlayerPosition(Transform playerTransform)
+ {
+ Vector3 startPosition = playerTransform.position;
+ Vector3 targetPosition = new Vector3(0f, startPosition.y, startPosition.z);
+
+ float duration = 1.0f; // Reset duration in seconds (as requested)
+ float elapsed = 0f;
+
+ while (elapsed < duration)
+ {
+ elapsed += Time.deltaTime;
+ float t = Mathf.Clamp01(elapsed / duration);
+
+ // Use smooth step for more natural movement
+ float smoothT = Mathf.SmoothStep(0f, 1f, t);
+
+ playerTransform.position = Vector3.Lerp(startPosition, targetPosition, smoothT);
+ yield return null;
+ }
+
+ // Ensure final position is exactly at target
+ playerTransform.position = targetPosition;
+ }
+
+ ///
+ /// Coroutine to handle the surfacing sequence timing
+ ///
+ private IEnumerator SurfacingSequence()
+ {
+ // Wait for the configured delay
+ yield return new WaitForSeconds(surfacingSpawnDelay);
+
+ // Find tile spawner and tell it to stop spawning
+ TrenchTileSpawner tileSpawner = FindFirstObjectByType();
+ if (tileSpawner != null)
+ {
+ // Tell it to stop spawning new tiles
+ tileSpawner.StopSpawning();
+ Debug.Log("[DivingGameManager] Stopped spawning new tiles after delay");
+ }
+ }
+
+ ///
+ /// Called when the last tile leaves the screen
+ ///
+ private void OnLastTileLeft()
+ {
+ // Play the timeline
+ if (surfacingTimeline != null)
+ {
+ surfacingTimeline.Play();
+ Debug.Log("[DivingGameManager] Last tile left the screen, playing timeline");
+ }
+ else
+ {
+ Debug.LogWarning("[DivingGameManager] No surfacing timeline assigned!");
+ }
+ }
+
// Call this when the game ends
public void EndGame()
{
@@ -193,5 +571,49 @@ namespace Minigames.DivingForPictures
// Final score could be saved to player prefs or other persistence
Debug.Log($"Final Score: {playerScore}");
}
+
+ ///
+ /// Starts a smooth transition to the new velocity factor
+ ///
+ /// Target velocity factor (e.g., -1.0 for surfacing speed)
+ public void SetVelocityFactor(float targetFactor)
+ {
+ if (_velocityTransitionCoroutine != null)
+ {
+ StopCoroutine(_velocityTransitionCoroutine);
+ }
+
+ _velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor));
+ }
+
+ ///
+ /// Coroutine to smoothly transition the velocity factor over time
+ ///
+ private IEnumerator TransitionVelocityFactor(float targetFactor)
+ {
+ float startFactor = _currentVelocityFactor;
+ float elapsed = 0f;
+
+ while (elapsed < speedTransitionDuration)
+ {
+ elapsed += Time.deltaTime;
+ float t = Mathf.Clamp01(elapsed / speedTransitionDuration);
+
+ // Smooth step interpolation
+ float smoothStep = t * t * (3f - 2f * t);
+
+ _currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep);
+
+ // Notify listeners about the velocity factor change
+ OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
+
+ yield return null;
+ }
+
+ _currentVelocityFactor = targetFactor;
+
+ // Final assignment to ensure exact target value
+ OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
+ }
}
}
diff --git a/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs b/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs
index 52338634..2d285271 100644
--- a/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs
+++ b/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs
@@ -44,8 +44,12 @@ namespace Minigames.DivingForPictures
private Collider2D _collider;
private Camera _mainCamera;
private float _screenTop;
+ private float _screenBottom; // Added to track bottom of screen
private Coroutine _movementCoroutine;
private Coroutine _offScreenCheckCoroutine;
+ private bool _isSurfacing = false; // Flag to track surfacing state
+ private float _velocityFactor = 1.0f; // Current velocity factor from game manager
+ private float _baseMoveSpeed; // Original move speed before velocity factor is applied
private void Awake()
{
@@ -62,6 +66,7 @@ namespace Minigames.DivingForPictures
}
_mainCamera = Camera.main;
+ _baseMoveSpeed = moveSpeed; // Store original speed
}
private void OnEnable()
@@ -105,6 +110,30 @@ namespace Minigames.DivingForPictures
}
}
+ ///
+ /// Called when the velocity factor changes from the DivingGameManager via ObstacleSpawner
+ ///
+ public void OnVelocityFactorChanged(float velocityFactor)
+ {
+ _velocityFactor = velocityFactor;
+
+ // Update actual move speed based on velocity factor and base speed
+ // We use Abs for magnitude and Sign for direction
+ moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor);
+
+ // Restart movement with new speed if needed
+ if (enableMovement && gameObject.activeInHierarchy)
+ {
+ if (_movementCoroutine != null)
+ {
+ StopCoroutine(_movementCoroutine);
+ }
+ _movementCoroutine = StartCoroutine(MovementCoroutine());
+ }
+
+ Debug.Log($"[FloatingObstacle] {gameObject.name} velocity factor updated to {_velocityFactor:F2}, speed: {moveSpeed:F2}");
+ }
+
///
/// Coroutine that handles obstacle movement
///
@@ -112,8 +141,12 @@ namespace Minigames.DivingForPictures
{
while (enabled && gameObject.activeInHierarchy)
{
- // Move the obstacle upward
- transform.position += Vector3.up * (moveSpeed * Time.deltaTime);
+ // Use velocity factor sign to determine direction
+ Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor);
+ float speed = moveSpeed * Time.deltaTime;
+
+ // Apply movement in correct direction
+ transform.position += direction * speed;
// Wait for next frame
yield return null;
@@ -165,6 +198,9 @@ namespace Minigames.DivingForPictures
Vector3 topWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 1f, _mainCamera.transform.position.z));
_screenTop = topWorldPoint.y;
+ Vector3 bottomWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 0f, _mainCamera.transform.position.z));
+ _screenBottom = bottomWorldPoint.y;
+
// Check if obstacle is significantly above screen top (obstacles move upward)
// Use a larger buffer to ensure obstacles are truly off-screen before returning to pool
if (transform.position.y > _screenTop + 5f)
@@ -172,6 +208,11 @@ namespace Minigames.DivingForPictures
Debug.Log($"[FloatingObstacle] {gameObject.name} off-screen at Y:{transform.position.y:F2}, screen top:{_screenTop:F2}");
ReturnToPool();
}
+ else if (transform.position.y < _screenBottom - 5f) // Added check for bottom screen edge
+ {
+ Debug.Log($"[FloatingObstacle] {gameObject.name} below screen at Y:{transform.position.y:F2}, screen bottom:{_screenBottom:F2}");
+ ReturnToPool();
+ }
}
///
@@ -279,5 +320,20 @@ namespace Minigames.DivingForPictures
StartObstacleBehavior();
}
}
+
+ ///
+ /// Sets surfacing mode, which reverses obstacle movement direction
+ ///
+ public void StartSurfacing()
+ {
+ if (_isSurfacing) return; // Already surfacing
+
+ _isSurfacing = true;
+
+ // Reverse movement speed (already handled by ObstacleSpawner, but this ensures consistency)
+ moveSpeed *= -1;
+
+ Debug.Log($"[FloatingObstacle] {gameObject.name} started surfacing with speed: {moveSpeed}");
+ }
}
}
diff --git a/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs
index 67f0cffd..8c69ec38 100644
--- a/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs
+++ b/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs
@@ -75,6 +75,8 @@ namespace Minigames.DivingForPictures
private Coroutine _spawnCoroutine;
private readonly List _activeObstacles = new List();
private int _obstacleCounter = 0; // Counter for unique obstacle naming
+ private bool _isSurfacing = false; // Flag to track surfacing state
+ private float _velocityFactor = 1.0f; // Current velocity factor from the game manager
private void Awake()
{
@@ -250,6 +252,13 @@ namespace Minigames.DivingForPictures
///
private void TrySpawnObstacle()
{
+ // Don't spawn new obstacles when surfacing
+ if (_isSurfacing)
+ {
+ Debug.Log("[ObstacleSpawner] Skipping obstacle spawn - currently surfacing");
+ return;
+ }
+
Debug.Log($"[ObstacleSpawner] TrySpawnObstacle called at {Time.time:F2}");
if (obstaclePrefabs == null || obstaclePrefabs.Count == 0)
@@ -338,25 +347,53 @@ namespace Minigames.DivingForPictures
return;
}
- Debug.Log($"[ObstacleSpawner] Got obstacle {obstacle.name} from pool, active state: {obstacle.activeInHierarchy}");
-
- // FORCE ACTIVATION - bypass pool issues
- if (!obstacle.activeInHierarchy)
- {
- Debug.LogWarning($"[ObstacleSpawner] Pool returned inactive object {obstacle.name}, force activating!");
- obstacle.SetActive(true);
- Debug.Log($"[ObstacleSpawner] After force activation, {obstacle.name} active state: {obstacle.activeInHierarchy}");
- }
-
+ // Important: Set position/parent/rotation BEFORE activation to avoid visual glitches
obstacle.transform.position = position;
obstacle.transform.rotation = prefab.transform.rotation;
obstacle.transform.SetParent(transform);
- Debug.Log($"[ObstacleSpawner] After positioning, obstacle {obstacle.name} active state: {obstacle.activeInHierarchy}");
+
+ Debug.Log($"[ObstacleSpawner] Got obstacle {obstacle.name} from pool, active state: {obstacle.activeInHierarchy}");
+
+ // ENHANCED FORCE ACTIVATION - more robust approach
+ if (!obstacle.activeInHierarchy)
+ {
+ Debug.LogWarning($"[ObstacleSpawner] Pool returned inactive object {obstacle.name}, force activating!");
+
+ // Configure obstacle BEFORE activation
+ ConfigureObstacle(obstacle, prefabIndex);
+
+ // Force activate the obstacle
+ obstacle.SetActive(true);
+
+ // Double-check activation status
+ if (!obstacle.activeInHierarchy)
+ {
+ Debug.LogError($"[ObstacleSpawner] CRITICAL ERROR: Failed to activate {obstacle.name} after multiple attempts!");
+
+ // Last resort: try to instantiate a new one instead
+ GameObject newObstacle = Instantiate(prefab, position, prefab.transform.rotation, transform);
+ if (newObstacle != null)
+ {
+ obstacle = newObstacle;
+ ConfigureObstacle(obstacle, prefabIndex);
+ }
+ }
+
+ Debug.Log($"[ObstacleSpawner] After force activation, {obstacle.name} active state: {obstacle.activeInHierarchy}");
+ }
+ else
+ {
+ // Still configure if already active
+ ConfigureObstacle(obstacle, prefabIndex);
+ }
}
else
{
Debug.Log($"[ObstacleSpawner] Instantiating new obstacle (pooling disabled)");
obstacle = Instantiate(prefab, position, prefab.transform.rotation, transform);
+
+ // Configure the newly instantiated obstacle
+ ConfigureObstacle(obstacle, prefabIndex);
}
// Assign unique name with counter
@@ -364,10 +401,6 @@ namespace Minigames.DivingForPictures
string oldName = obstacle.name;
obstacle.name = $"Obstacle{_obstacleCounter:D3}";
Debug.Log($"[ObstacleSpawner] Renamed obstacle from '{oldName}' to '{obstacle.name}', active state: {obstacle.activeInHierarchy}");
-
- // Configure the obstacle
- ConfigureObstacle(obstacle, prefabIndex);
- Debug.Log($"[ObstacleSpawner] After configuration, obstacle {obstacle.name} active state: {obstacle.activeInHierarchy}");
// Track active obstacles
_activeObstacles.Add(obstacle);
@@ -459,6 +492,55 @@ namespace Minigames.DivingForPictures
CalculateScreenBounds();
}
+ ///
+ /// Called when the velocity factor changes from the DivingGameManager
+ ///
+ public void OnVelocityFactorChanged(float velocityFactor)
+ {
+ _velocityFactor = velocityFactor;
+
+ // Update all active obstacles with the new velocity factor
+ foreach (GameObject obstacle in _activeObstacles)
+ {
+ if (obstacle != null)
+ {
+ FloatingObstacle obstacleComponent = obstacle.GetComponent();
+ if (obstacleComponent != null)
+ {
+ obstacleComponent.OnVelocityFactorChanged(velocityFactor);
+ }
+ }
+ }
+
+ Debug.Log($"[ObstacleSpawner] Velocity factor updated to {_velocityFactor:F2}, propagated to {_activeObstacles.Count} active obstacles");
+ }
+
+ ///
+ /// Start surfacing mode - reverse direction of existing obstacles and stop spawning new ones
+ ///
+ public void StartSurfacing()
+ {
+ if (_isSurfacing) return; // Already surfacing
+
+ _isSurfacing = true;
+
+ // Notify obstacles about surfacing state (for direction-based logic)
+ foreach (GameObject obstacle in _activeObstacles)
+ {
+ if (obstacle != null)
+ {
+ FloatingObstacle obstacleComponent = obstacle.GetComponent();
+ if (obstacleComponent != null)
+ {
+ // Call StartSurfacing on the obstacle component itself
+ obstacleComponent.StartSurfacing();
+ }
+ }
+ }
+
+ Debug.Log($"[ObstacleSpawner] Started surfacing mode for {_activeObstacles.Count} active obstacles");
+ }
+
///
/// Gets the count of currently active obstacles
///
diff --git a/Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs b/Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
new file mode 100644
index 00000000..fa0b022c
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
@@ -0,0 +1,331 @@
+using UnityEngine;
+using System.Collections;
+using GogoGaga.OptimizedRopesAndCables;
+
+///
+/// Component that allows breaking a rope in half.
+/// Attach this to the same GameObject that has a Rope and LineRenderer component.
+///
+public class RopeBreaker : MonoBehaviour
+{
+ [Header("Break Settings")]
+ [Tooltip("Position along rope where break occurs (0-1)")]
+ [Range(0f, 1f)]
+ [SerializeField] private float breakPosition = 0.5f;
+
+ [Tooltip("Effect to spawn at break point (optional)")]
+ [SerializeField] private GameObject breakEffect;
+
+ [Tooltip("Sound to play when rope breaks (optional)")]
+ [SerializeField] private AudioClip breakSound;
+
+ [Header("Physics Settings")]
+ [Tooltip("Follow speed for the rope physics simulation")]
+ [SerializeField] private float ropeFollowSpeed = 5f;
+
+ [Tooltip("Trailing amount for the rope physics simulation")]
+ [SerializeField] private float ropeTrailing = 0.2f;
+
+ [Tooltip("Gravity strength applied to hanging rope end")]
+ [SerializeField] private float ropeGravityStrength = 9.8f;
+
+ [Tooltip("How strongly the rope tries to hang vertically")]
+ [SerializeField] private float ropeVerticalHangStrength = 2f;
+
+ [Tooltip("Damping for physics movement (higher = less bouncy)")]
+ [SerializeField] private float ropeDamping = 0.3f;
+
+ [Tooltip("Initial separation distance between rope ends when broken")]
+ [SerializeField] private float initialSeparationDistance = 0.1f;
+
+ [Tooltip("Initial downward impulse for falling rope end")]
+ [SerializeField] private float initialFallImpulse = 2.0f;
+
+ // Private references
+ private Rope originalRope;
+ private LineRenderer originalLineRenderer;
+ private GameObject firstHalfRope;
+ private GameObject secondHalfRope;
+ private Rope firstHalfRopeComponent;
+ private Rope secondHalfRopeComponent;
+ private Transform breakPointTransform;
+ private Transform secondBreakTransform;
+
+ private void Awake()
+ {
+ // Get references to the required components
+ originalRope = GetComponent();
+ originalLineRenderer = GetComponent();
+
+ if (originalRope == null || originalLineRenderer == null)
+ {
+ Debug.LogError("RopeBreaker requires both Rope and LineRenderer components on the same GameObject");
+ enabled = false;
+ }
+ }
+
+ ///
+ /// Breaks the rope at the specified position.
+ ///
+ /// Optional override for break position (0-1)
+ /// True if rope was broken successfully, false otherwise
+ public bool BreakRope(float? breakPositionOverride = null)
+ {
+ if (originalRope == null || !originalRope.StartPoint || !originalRope.EndPoint)
+ {
+ Debug.LogError("Cannot break rope: Missing rope component or endpoints");
+ return false;
+ }
+
+ // Use override position if provided
+ float breakPos = breakPositionOverride ?? breakPosition;
+ breakPos = Mathf.Clamp01(breakPos);
+
+ // Get the world position at the break point
+ Vector3 breakPointPosition = originalRope.GetPointAt(breakPos);
+
+ // Create a transform at the break point to use as an anchor
+ CreateBreakPointTransform(breakPointPosition);
+
+ // Create two new rope GameObjects
+ CreateRopeSegments(breakPointPosition);
+
+ // Hide the original rope
+ originalLineRenderer.enabled = false;
+
+ // Play effects
+ PlayBreakEffects(breakPointPosition);
+
+ return true;
+ }
+
+ ///
+ /// Creates a transform at the break point to use as an anchor
+ ///
+ private void CreateBreakPointTransform(Vector3 breakPointPosition)
+ {
+ // Store references to the original rope endpoints
+ Transform originalStartPoint = originalRope.StartPoint;
+ Transform originalEndPoint = originalRope.EndPoint;
+
+ // Create a new GameObject for the break point (attached to Player)
+ GameObject breakPointObj = new GameObject("RopeBreakPoint");
+ breakPointTransform = breakPointObj.transform;
+ breakPointTransform.position = breakPointPosition;
+ breakPointTransform.SetParent(transform.parent); // Parent to the same parent as the rope
+
+ // Add the physics follower component to the break point
+ RopeEndPhysicsFollower follower = breakPointObj.AddComponent();
+
+ // Set specific transform to follow instead of using tag
+ follower.SetTargetTransform(originalStartPoint);
+ follower.canFall = false; // Player rope end doesn't fall
+ follower.followSpeed = ropeFollowSpeed;
+ follower.trailing = ropeTrailing;
+
+ // Create second break point (for the rock-attached end)
+ GameObject secondBreakObj = new GameObject("RopeBreakPoint_Second");
+ secondBreakTransform = secondBreakObj.transform;
+ secondBreakTransform.position = breakPointPosition;
+ secondBreakTransform.SetParent(transform.parent);
+
+ // Add physics behavior to second break point
+ RopeEndPhysicsFollower secondFollower = secondBreakObj.AddComponent();
+
+ // Set specific transform to follow instead of using tag
+ secondFollower.SetTargetTransform(originalEndPoint);
+ secondFollower.canFall = true; // Rock end can fall
+ secondFollower.followSpeed = ropeFollowSpeed;
+ secondFollower.trailing = ropeTrailing;
+ secondFollower.gravityStrength = ropeGravityStrength;
+ secondFollower.verticalHangStrength = ropeVerticalHangStrength;
+ secondFollower.damping = ropeDamping;
+ secondFollower.initialFallImpulse = initialFallImpulse;
+
+ // Create initial separation
+ Vector3 direction = (originalEndPoint.position - breakPointPosition).normalized;
+ if (direction.magnitude < 0.01f) direction = Vector3.down;
+
+ breakPointTransform.position -= direction * initialSeparationDistance * 0.5f;
+ secondBreakTransform.position += direction * initialSeparationDistance * 0.5f;
+ }
+
+ ///
+ /// Creates two new rope GameObjects for the broken segments
+ ///
+ private void CreateRopeSegments(Vector3 breakPointPosition)
+ {
+ // Create the first half rope (from start to break point)
+ firstHalfRope = new GameObject("Rope_FirstHalf");
+ firstHalfRope.transform.position = transform.position;
+ firstHalfRope.transform.rotation = transform.rotation;
+ firstHalfRope.transform.SetParent(transform.parent);
+
+ // Add Rope component which automatically adds LineRenderer due to RequireComponent
+ firstHalfRopeComponent = firstHalfRope.AddComponent();
+
+ // Get the LineRenderer that was automatically added
+ LineRenderer firstLineRenderer = firstHalfRope.GetComponent();
+ if (firstLineRenderer == null)
+ {
+ // Only add if somehow not created (shouldn't happen, but safety check)
+ firstLineRenderer = firstHalfRope.AddComponent();
+ }
+ CopyLineRendererProperties(originalLineRenderer, firstLineRenderer);
+
+ // Create the second half rope (from break point to end)
+ secondHalfRope = new GameObject("Rope_SecondHalf");
+ secondHalfRope.transform.position = transform.position;
+ secondHalfRope.transform.rotation = transform.rotation;
+ secondHalfRope.transform.SetParent(transform.parent);
+
+ // Add Rope component which automatically adds LineRenderer due to RequireComponent
+ secondHalfRopeComponent = secondHalfRope.AddComponent();
+
+ // Get the LineRenderer that was automatically added
+ LineRenderer secondLineRenderer = secondHalfRope.GetComponent();
+ if (secondLineRenderer == null)
+ {
+ // Only add if somehow not created (shouldn't happen, but safety check)
+ secondLineRenderer = secondHalfRope.AddComponent();
+ }
+ CopyLineRendererProperties(originalLineRenderer, secondLineRenderer);
+
+ // Configure the first half rope
+ firstHalfRopeComponent.SetStartPoint(originalRope.StartPoint);
+ firstHalfRopeComponent.SetEndPoint(breakPointTransform, false); // Don't recalculate yet
+
+ // Copy properties from original rope
+ CopyRopeProperties(originalRope, firstHalfRopeComponent);
+
+ // Explicitly initialize the rope
+ firstHalfRopeComponent.Initialize();
+
+ // Now force recalculation after initialization
+ firstHalfRopeComponent.RecalculateRope();
+
+ // Configure the second half rope - REVERSED: Rock (End) is now Start, Break point is now End
+ secondHalfRopeComponent.SetStartPoint(originalRope.EndPoint);
+ secondHalfRopeComponent.SetEndPoint(secondBreakTransform, false); // Don't recalculate yet
+
+ // Copy properties from original rope
+ CopyRopeProperties(originalRope, secondHalfRopeComponent);
+
+ // Explicitly initialize the rope
+ secondHalfRopeComponent.Initialize();
+
+ // Now force recalculation after initialization
+ secondHalfRopeComponent.RecalculateRope();
+
+ // Set explicit rope length constraints on the physics followers
+ // This needs to be done after the rope segments are created so we have the correct rope lengths
+ RopeEndPhysicsFollower playerFollower = breakPointTransform.GetComponent();
+ if (playerFollower != null)
+ {
+ playerFollower.SetMaxDistance(firstHalfRopeComponent.ropeLength);
+ }
+
+ RopeEndPhysicsFollower rockFollower = secondBreakTransform.GetComponent();
+ if (rockFollower != null)
+ {
+ rockFollower.SetMaxDistance(secondHalfRopeComponent.ropeLength);
+ }
+ }
+
+ ///
+ /// Copies properties from one LineRenderer to another
+ ///
+ private void CopyLineRendererProperties(LineRenderer source, LineRenderer destination)
+ {
+ // Copy material
+ destination.material = source.material;
+
+ // Copy colors
+ destination.startColor = source.startColor;
+ destination.endColor = source.endColor;
+
+ // Copy width
+ destination.startWidth = source.startWidth;
+ destination.endWidth = source.endWidth;
+
+ // Copy other properties
+ destination.numCornerVertices = source.numCornerVertices;
+ destination.numCapVertices = source.numCapVertices;
+ destination.alignment = source.alignment;
+ destination.textureMode = source.textureMode;
+ destination.generateLightingData = source.generateLightingData;
+ destination.useWorldSpace = source.useWorldSpace;
+ destination.loop = source.loop;
+ destination.sortingLayerID = source.sortingLayerID;
+ destination.sortingOrder = source.sortingOrder;
+ }
+
+ ///
+ /// Copies properties from one Rope to another
+ ///
+ private void CopyRopeProperties(Rope source, Rope destination)
+ {
+ destination.linePoints = source.linePoints;
+ destination.stiffness = source.stiffness;
+ destination.damping = source.damping;
+ destination.ropeLength = source.ropeLength / 2f; // Halve the rope length for each segment
+ destination.ropeWidth = source.ropeWidth;
+ destination.midPointWeight = source.midPointWeight;
+ destination.midPointPosition = source.midPointPosition;
+
+ // Recalculate the rope to update its appearance
+ destination.RecalculateRope();
+ }
+
+ ///
+ /// Plays visual and audio effects at the break point
+ ///
+ private void PlayBreakEffects(Vector3 breakPointPosition)
+ {
+ // Spawn break effect if assigned
+ if (breakEffect != null)
+ {
+ Instantiate(breakEffect, breakPointPosition, Quaternion.identity);
+ }
+
+ // Play break sound if assigned
+ if (breakSound != null)
+ {
+ AudioSource.PlayClipAtPoint(breakSound, breakPointPosition);
+ }
+ }
+
+ ///
+ /// Restores the original rope and cleans up the broken pieces
+ ///
+ public void RestoreRope()
+ {
+ // Re-enable the original rope
+ if (originalLineRenderer != null)
+ {
+ originalLineRenderer.enabled = true;
+ }
+
+ // Clean up the broken rope pieces
+ if (firstHalfRope != null)
+ {
+ Destroy(firstHalfRope);
+ }
+
+ if (secondHalfRope != null)
+ {
+ Destroy(secondHalfRope);
+ }
+
+ // Clean up both break points
+ if (breakPointTransform != null)
+ {
+ Destroy(breakPointTransform.gameObject);
+ }
+
+ if (secondBreakTransform != null)
+ {
+ Destroy(secondBreakTransform.gameObject);
+ }
+ }
+}
diff --git a/Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs.meta b/Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs.meta
new file mode 100644
index 00000000..9cd7aa9f
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 30919200017f4879867c3b6289429924
+timeCreated: 1758466190
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/DivingForPictures/RopeEndPhysicsFollower.cs b/Assets/Scripts/Minigames/DivingForPictures/RopeEndPhysicsFollower.cs
new file mode 100644
index 00000000..a9549101
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/RopeEndPhysicsFollower.cs
@@ -0,0 +1,306 @@
+using GogoGaga.OptimizedRopesAndCables;
+using UnityEngine;
+
+public class RopeEndPhysicsFollower : MonoBehaviour
+{
+ [Header("Target Settings")]
+ [Tooltip("Transform this endpoint should follow")]
+ public Transform targetTransform;
+ [Tooltip("Tag of the object this endpoint should follow (only used if targetTransform is not set)")]
+ public string targetTag;
+ [Tooltip("How quickly the endpoint follows the target when not using physics")]
+ public float followSpeed = 5f;
+ [Tooltip("How much trailing (0 = instant, 1 = very slow)")]
+ public float trailing = 0.2f;
+
+ [Header("Physics Simulation")]
+ [Tooltip("Gravity strength")]
+ public float gravityStrength = 9.8f;
+ [Tooltip("How strongly the rope attempts to hang vertically")]
+ public float verticalHangStrength = 2f;
+ [Tooltip("Damping for physics movement (higher = less bouncy)")]
+ public float damping = 0.3f;
+ [Tooltip("Initial downward impulse when enabled")]
+ public float initialFallImpulse = 2.0f;
+ [Tooltip("Whether this end can fall with gravity (false for player-attached ends)")]
+ public bool canFall = true;
+
+ // Private variables
+ private Transform target;
+ private Vector2 physicsVelocity;
+ private Vector2 offset;
+ private Vector3 lastTargetPosition;
+ private bool initialized = false;
+ private bool debugLog = true;
+
+ // Rope reference to get the actual rope length
+ private Rope attachedRope;
+ private float maxDistance;
+
+ void Start()
+ {
+ // Find the Rope component to determine the maximum distance
+ FindAttachedRope();
+
+ // Use targetTransform if set, otherwise try to find by tag
+ if (targetTransform != null)
+ {
+ target = targetTransform;
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Using assigned target transform: {target.name}");
+ }
+ else if (!string.IsNullOrEmpty(targetTag))
+ {
+ GameObject found = GameObject.FindGameObjectWithTag(targetTag);
+ if (found)
+ {
+ target = found.transform;
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Found target by tag '{targetTag}': {target.name}");
+ }
+ }
+
+ // Initialize offset and velocities
+ if (target)
+ {
+ // Only store horizontal offset, not vertical for physics simulation
+ Vector2 offsetVec = transform.position - target.position;
+ offset.x = offsetVec.x;
+ offset.y = 0; // Don't preserve vertical offset for gravity simulation
+ lastTargetPosition = target.position;
+
+ // Apply initial falling impulse if this end can fall
+ if (canFall)
+ {
+ physicsVelocity = new Vector2(0, -initialFallImpulse);
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Initialized with target: {target.name}, initial Y velocity: {physicsVelocity.y}");
+ }
+ }
+ else
+ {
+ offset = Vector2.zero;
+ lastTargetPosition = transform.position;
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] No target found");
+ }
+
+ initialized = true;
+ }
+
+ void Update()
+ {
+ if (!target) return;
+
+ // Calculate deltaTime for physics stability
+ float deltaTime = Time.deltaTime;
+
+ // Get target velocity
+ Vector3 targetVelocity = (target.position - lastTargetPosition) / deltaTime;
+ lastTargetPosition = target.position;
+
+ // Current position relative to target
+ Vector2 relativePos = new Vector2(
+ transform.position.x - target.position.x,
+ transform.position.y - target.position.y
+ );
+
+ // Get the straight-line distance between target and this transform
+ float currentDistance = relativePos.magnitude;
+
+ // Normalized direction from target to this transform
+ Vector2 directionToTarget = relativePos.normalized;
+
+ // Apply forces based on whether this end can fall
+ if (canFall)
+ {
+ // 1. Gravity - always pulls down
+ physicsVelocity.y -= gravityStrength * deltaTime;
+ }
+
+ // 2. Vertical hanging force - try to align X with target when stationary
+ if (Mathf.Abs(targetVelocity.x) < 0.1f)
+ {
+ // Use the actual X position of the target as the desired X position
+ float xOffset = transform.position.x - target.position.x;
+ physicsVelocity.x -= xOffset * verticalHangStrength * deltaTime;
+
+ // Debug log to track vertical hanging behavior
+ if (debugLog && Time.frameCount % 120 == 0)
+ {
+ Debug.Log($"[RopeEndPhysicsFollower] Vertical hanging: target X={target.position.x}, my X={transform.position.x}, offset={xOffset}");
+ }
+ }
+
+ // 3. Rope length constraint - apply a force toward the target if we're exceeding the rope length
+ if (currentDistance > maxDistance)
+ {
+ // Calculate constraint force proportional to how much we're exceeding the rope length
+ float exceededDistance = currentDistance - maxDistance;
+
+ // Apply a stronger constraint force the more we exceed the max distance
+ Vector2 constraintForce = -directionToTarget * exceededDistance * 10f;
+
+ // Apply to velocity
+ physicsVelocity += constraintForce * deltaTime;
+
+ if (debugLog && Time.frameCount % 60 == 0)
+ {
+ Debug.Log($"[RopeEndPhysicsFollower] Exceeding max distance: {exceededDistance}, applying constraint");
+ }
+ }
+
+ // Apply damping to physics velocity
+ physicsVelocity *= (1f - damping * deltaTime);
+
+ // Log physics state periodically for debugging
+ if (debugLog && Time.frameCount % 60 == 0)
+ {
+ Debug.Log($"[RopeEndPhysicsFollower] Y position: {transform.position.y}, Y velocity: {physicsVelocity.y}, Distance: {currentDistance}/{maxDistance}");
+ }
+
+ // Apply physics velocity to position
+ Vector3 newPos = transform.position;
+ newPos.x += physicsVelocity.x * deltaTime;
+
+ // Only apply vertical movement if this end can fall
+ if (canFall)
+ {
+ newPos.y += physicsVelocity.y * deltaTime;
+ }
+
+ transform.position = newPos;
+
+ // Final distance check - hard constraint to ensure we never exceed the rope length
+ // This prevents numerical instability from causing the rope to stretch
+ float finalDistance = Vector2.Distance(
+ new Vector2(transform.position.x, transform.position.y),
+ new Vector2(target.position.x, target.position.y)
+ );
+
+ if (finalDistance > maxDistance)
+ {
+ // Calculate the direction from target to this transform
+ Vector2 direction = new Vector2(
+ transform.position.x - target.position.x,
+ transform.position.y - target.position.y
+ ).normalized;
+
+ // Set position to be exactly at the maximum distance
+ Vector3 constrainedPos = new Vector3(
+ target.position.x + direction.x * maxDistance,
+ target.position.y + direction.y * maxDistance,
+ transform.position.z
+ );
+
+ transform.position = constrainedPos;
+ }
+ }
+
+ private void FindAttachedRope()
+ {
+ // Find the Rope component on the same GameObject or parent
+ attachedRope = GetComponent();
+ if (attachedRope == null)
+ {
+ attachedRope = GetComponentInParent();
+ }
+
+ // If we still couldn't find it, look for it on a child GameObject
+ if (attachedRope == null)
+ {
+ attachedRope = GetComponentInChildren();
+ }
+
+ // Look for a rope attached to this endpoint
+ if (attachedRope == null)
+ {
+ // Find any rope that has this transform as an endpoint
+ Rope[] allRopes = FindObjectsOfType();
+ foreach (var rope in allRopes)
+ {
+ if (rope.EndPoint == transform || rope.StartPoint == transform)
+ {
+ attachedRope = rope;
+ break;
+ }
+ }
+ }
+
+ // Set max distance based on rope length if we found a rope
+ if (attachedRope != null)
+ {
+ maxDistance = attachedRope.ropeLength;
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Found attached rope with length: {maxDistance}");
+ }
+ else
+ {
+ // Default fallback value if no rope is found
+ maxDistance = 2f;
+ if (debugLog) Debug.Log("[RopeEndPhysicsFollower] No attached rope found, using default max distance");
+ }
+ }
+
+ public void SetTargetTransform(Transform newTarget)
+ {
+ targetTransform = newTarget;
+ target = newTarget;
+
+ if (target != null)
+ {
+ lastTargetPosition = target.position;
+
+ // Only update horizontal offset to maintain current vertical position
+ if (initialized)
+ {
+ Vector2 newOffset = transform.position - target.position;
+ offset.x = newOffset.x;
+ // Don't update offset.y to allow gravity to work
+ }
+ else
+ {
+ Vector2 newOffset = transform.position - target.position;
+ offset.x = newOffset.x;
+ offset.y = 0; // Don't preserve vertical offset for gravity simulation
+ }
+
+ // Apply initial falling impulse if this end can fall
+ if (canFall)
+ {
+ physicsVelocity = new Vector2(physicsVelocity.x, -initialFallImpulse);
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Reset Y velocity to {physicsVelocity.y} after target change to {target.name}");
+ }
+ }
+ }
+
+ // Original tag-based method kept for backward compatibility
+ public void SetTargetTag(string tag)
+ {
+ targetTag = tag;
+ GameObject found = GameObject.FindGameObjectWithTag(targetTag);
+ if (found)
+ {
+ SetTargetTransform(found.transform);
+ }
+ }
+
+ // Debug method to force reset the physics
+ public void ForceResetPhysics()
+ {
+ if (target)
+ {
+ // Reset velocity with a strong downward impulse
+ physicsVelocity = new Vector2(0, -initialFallImpulse * 2f);
+
+ // Reset position to be at the same level as the target
+ Vector3 pos = transform.position;
+ pos.y = target.position.y;
+ transform.position = pos;
+
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Physics forcibly reset, new Y velocity: {physicsVelocity.y}");
+ }
+ }
+
+ // Method to manually set the maximum distance
+ public void SetMaxDistance(float distance)
+ {
+ maxDistance = distance;
+ if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Max distance manually set to: {maxDistance}");
+ }
+}
diff --git a/Assets/Scripts/Minigames/DivingForPictures/RopeEndPhysicsFollower.cs.meta b/Assets/Scripts/Minigames/DivingForPictures/RopeEndPhysicsFollower.cs.meta
new file mode 100644
index 00000000..d7876677
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/RopeEndPhysicsFollower.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: bc5a0e35b5e74474b4241fae08971e7a
+timeCreated: 1758485385
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs
index 7d2bf387..064944dc 100644
--- a/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs
+++ b/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System.Collections;
+using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
@@ -48,13 +49,31 @@ namespace Minigames.DivingForPictures
private float _screenBottom;
private float _screenTop;
private TrenchTilePool _tilePool;
+
+ // Current velocity for tile movement
+ private float _currentVelocity;
+
+ // Interval for velocity calculations (seconds)
+ [SerializeField] private float velocityCalculationInterval = 0.5f;
private const float TileSpawnZ = -1f;
private const float DefaultTileHeight = 5f;
+ // Direction state
+ private bool _isSurfacing = false;
+ private bool _stopSpawning = false;
+
+ // Event triggered when the last tile leaves the screen after stopping spawning
+ public UnityEvent onLastTileLeft = new UnityEvent();
+
+ // Velocity management
+ private float _baseMoveSpeed;
+ private float _velocityFactor = 1.0f;
+
private void Awake()
{
_mainCamera = Camera.main;
+ _baseMoveSpeed = moveSpeed; // Store the original base speed
// Calculate tile heights for each prefab
CalculateTileHeights();
@@ -89,15 +108,57 @@ namespace Minigames.DivingForPictures
{
CalculateScreenBounds();
SpawnInitialTiles();
+
+ // Initialize velocity and start the velocity calculation coroutine
+ _currentVelocity = moveSpeed * Time.fixedDeltaTime;
+ StartCoroutine(VelocityCalculationRoutine());
}
private void Update()
{
- MoveTiles();
+ HandleMovement();
HandleTileDestruction();
HandleTileSpawning();
HandleSpeedRamping();
}
+
+ ///
+ /// Gets the current velocity of the tiles
+ ///
+ /// The current upward velocity of the tiles
+ public float GetCurrentVelocity()
+ {
+ return _currentVelocity;
+ }
+
+ ///
+ /// Sets a custom velocity, overriding the calculated one
+ ///
+ /// The new velocity value
+ public void SetVelocity(float velocity)
+ {
+ _currentVelocity = velocity;
+ }
+
+ ///
+ /// Coroutine that periodically calculates the velocity based on game state
+ ///
+ private IEnumerator VelocityCalculationRoutine()
+ {
+ while (true)
+ {
+ CalculateVelocity();
+ yield return new WaitForSeconds(velocityCalculationInterval);
+ }
+ }
+
+ ///
+ /// Calculates the current velocity based on move speed
+ ///
+ private void CalculateVelocity()
+ {
+ _currentVelocity = moveSpeed * Time.fixedDeltaTime;
+ }
///
/// Calculate height values for all tile prefabs
@@ -170,9 +231,25 @@ namespace Minigames.DivingForPictures
///
private void SpawnInitialTiles()
{
+ // Calculate starting Y position - moved 2 tiles up from the bottom of the screen
+ float startingY = _screenBottom;
+
+ // If we have prefab tiles with known heights, use their average height for offset calculation
+ float tileHeightEstimate = DefaultTileHeight;
+ if (tilePrefabs != null && tilePrefabs.Count > 0 && tilePrefabs[0] != null)
+ {
+ if (_tileHeights.TryGetValue(tilePrefabs[0], out float height))
+ {
+ tileHeightEstimate = height;
+ }
+ }
+
+ // Move starting position up by 2 tile heights
+ startingY += tileHeightEstimate * 2;
+
for (int i = 0; i < initialTileCount; i++)
{
- float y = _screenBottom;
+ float y = startingY;
// Calculate proper Y position based on previous tiles
if (i > 0 && _activeTiles.Count > 0)
{
@@ -206,16 +283,61 @@ namespace Minigames.DivingForPictures
}
///
- /// Move all active tiles upward
+ /// Called when the velocity factor changes from the DivingGameManager
///
- private void MoveTiles()
+ public void OnVelocityFactorChanged(float velocityFactor)
+ {
+ _velocityFactor = velocityFactor;
+
+ // Update the actual move speed based on the velocity factor
+ // This keeps the original move speed intact for game logic
+ moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor);
+
+ // Recalculate velocity immediately
+ CalculateVelocity();
+
+ Debug.Log($"[TrenchTileSpawner] Velocity factor updated to {_velocityFactor:F2}, moveSpeed: {moveSpeed:F2}");
+ }
+
+ ///
+ /// Reverses direction to start surfacing
+ ///
+ public void StartSurfacing()
+ {
+ if (_isSurfacing) return; // Already surfacing
+
+ // Set surfacing flag for spawn/despawn logic
+ _isSurfacing = true;
+
+ // Reverse the active tiles array to maintain consistent indexing logic
+ _activeTiles.Reverse();
+
+ Debug.Log("[TrenchTileSpawner] Started surfacing - reversed array order");
+ }
+
+ ///
+ /// Stops spawning new tiles
+ ///
+ public void StopSpawning()
+ {
+ _stopSpawning = true;
+ }
+
+ ///
+ /// Handles the movement of all active tiles based on the current velocity
+ ///
+ private void HandleMovement()
{
- float moveDelta = moveSpeed * Time.deltaTime;
foreach (var tile in _activeTiles)
{
if (tile != null)
{
- tile.transform.position += Vector3.up * moveDelta;
+ // Use velocity factor to determine direction
+ Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor);
+ float speed = _currentVelocity;
+
+ // Apply movement
+ tile.transform.position += direction * speed;
}
}
}
@@ -235,7 +357,20 @@ namespace Minigames.DivingForPictures
}
float tileHeight = GetTileHeight(topTile);
- if (topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer)
+
+ bool shouldDestroy;
+ if (_isSurfacing)
+ {
+ // When surfacing, destroy tiles at the bottom
+ shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
+ }
+ else
+ {
+ // When descending, destroy tiles at the top
+ shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
+ }
+
+ if (shouldDestroy)
{
_activeTiles.RemoveAt(0);
onTileDestroyed?.Invoke(topTile);
@@ -265,7 +400,15 @@ namespace Minigames.DivingForPictures
///
private void HandleTileSpawning()
{
- if (_activeTiles.Count == 0) return;
+ if (_activeTiles.Count == 0)
+ {
+ // If we have no active tiles and spawning is stopped, trigger the event
+ if (_stopSpawning)
+ {
+ onLastTileLeft.Invoke();
+ }
+ return;
+ }
GameObject bottomTile = _activeTiles[^1];
if (bottomTile == null)
@@ -274,15 +417,60 @@ namespace Minigames.DivingForPictures
return;
}
+ // Get the tile height once to use in all calculations
float tileHeight = GetTileHeight(bottomTile);
- float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
- if (bottomEdge > _screenBottom - tileSpawnBuffer)
+
+ // If we're in stop spawning mode, don't spawn new tiles
+ if (_stopSpawning)
+ {
+ // Check if this is the last tile, and if it's about to leave the screen
+ if (_activeTiles.Count == 1)
+ {
+ bool isLastTileLeaving;
+
+ if (_isSurfacing)
+ {
+ // When surfacing, check if the bottom of the tile is above the top of the screen
+ isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
+ }
+ else
+ {
+ // When descending, check if the top of the tile is below the bottom of the screen
+ isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
+ }
+
+ if (isLastTileLeaving)
+ {
+ onLastTileLeft.Invoke();
+ }
+ }
+ return;
+ }
+
+ bool shouldSpawn;
+ float newY;
+
+ if (_isSurfacing)
+ {
+ // When surfacing, spawn new tiles at the top
+ float topEdge = bottomTile.transform.position.y + tileHeight / 2;
+ shouldSpawn = topEdge < _screenTop + tileSpawnBuffer;
+ newY = bottomTile.transform.position.y + tileHeight;
+ }
+ else
+ {
+ // When descending, spawn new tiles at the bottom
+ float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
+ shouldSpawn = bottomEdge > _screenBottom - tileSpawnBuffer;
+ newY = bottomTile.transform.position.y - tileHeight;
+ }
+
+ if (shouldSpawn)
{
- float newY = bottomTile.transform.position.y - tileHeight;
SpawnTileAtY(newY);
}
}
-
+
///
/// Handle increasing the movement speed over time
///
diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset
index c795aa89..3436af9a 100644
--- a/ProjectSettings/TagManager.asset
+++ b/ProjectSettings/TagManager.asset
@@ -6,6 +6,7 @@ TagManager:
tags:
- CharacterArt
- Pulver
+ - Rock
layers:
- Default
- TransparentFX