Compare commits
10 Commits
dialogue_g
...
minigame_e
| Author | SHA1 | Date | |
|---|---|---|---|
| ec1a0e70aa | |||
| 46950aa877 | |||
| ae6b995f45 | |||
| b0e44f156e | |||
| bb3c91ec94 | |||
| 8326f03086 | |||
|
|
2942b22c62 | ||
|
|
38f578c56a | ||
|
|
ef3b50b99f | ||
|
|
af5dfbb7a2 |
BIN
Assets/Art/Textures/DivingBackground.png
Normal file
BIN
Assets/Art/Textures/DivingBackground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
195
Assets/Art/Textures/DivingBackground.png.meta
Normal file
195
Assets/Art/Textures/DivingBackground.png.meta
Normal file
@@ -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:
|
||||||
48
Assets/Editor/DivingGameManagerEditor.cs
Normal file
48
Assets/Editor/DivingGameManagerEditor.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using Minigames.DivingForPictures;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for DivingGameManager that adds runtime buttons for testing surfacing and other functionality
|
||||||
|
/// </summary>
|
||||||
|
[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Editor/DivingGameManagerEditor.cs.meta
Normal file
3
Assets/Editor/DivingGameManagerEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8bbb340d8d9b4af581770757e86cc1f8
|
||||||
|
timeCreated: 1758532258
|
||||||
42
Assets/Editor/TrenchTileSpawnerEditor.cs
Normal file
42
Assets/Editor/TrenchTileSpawnerEditor.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using Minigames.DivingForPictures;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for TrenchTileSpawner that adds a runtime button to test the StartSurfacing function
|
||||||
|
/// </summary>
|
||||||
|
[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Editor/TrenchTileSpawnerEditor.cs.meta
Normal file
3
Assets/Editor/TrenchTileSpawnerEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9fb1a138e45d4720ba5c95da894b4491
|
||||||
|
timeCreated: 1758531024
|
||||||
3
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
vendored
Normal file
3
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "OptimizedRope"
|
||||||
|
}
|
||||||
7
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
vendored
Normal file
7
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7c43f01316c63c43a8b70a1dd6bdfac
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -75,8 +75,20 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
|
|
||||||
public bool IsPrefab => gameObject.scene.rootCount == 0;
|
public bool IsPrefab => gameObject.scene.rootCount == 0;
|
||||||
|
|
||||||
private void Start()
|
// Track initialization state
|
||||||
|
private bool isInitialized = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public method to explicitly initialize the rope.
|
||||||
|
/// Call this after setting up endpoints if creating ropes at runtime.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if initialization was successful, false otherwise</returns>
|
||||||
|
public bool Initialize()
|
||||||
{
|
{
|
||||||
|
// Skip if already initialized
|
||||||
|
if (isInitialized)
|
||||||
|
return true;
|
||||||
|
|
||||||
InitializeLineRenderer();
|
InitializeLineRenderer();
|
||||||
if (AreEndPointsValid())
|
if (AreEndPointsValid())
|
||||||
{
|
{
|
||||||
@@ -84,7 +96,17 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
targetValue = currentValue;
|
targetValue = currentValue;
|
||||||
currentVelocity = Vector3.zero;
|
currentVelocity = Vector3.zero;
|
||||||
SetSplinePoint(); // Ensure initial spline point is set correctly
|
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()
|
private void OnValidate()
|
||||||
@@ -208,15 +230,62 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetPointAt(float t)
|
/// <summary>
|
||||||
|
/// Set the start point of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void SetStartPoint(Transform newStartPoint, bool recalculateRope = false)
|
||||||
{
|
{
|
||||||
if (!AreEndPointsValid())
|
startPoint = newStartPoint;
|
||||||
{
|
if (recalculateRope)
|
||||||
Debug.LogError("StartPoint or EndPoint is not assigned.", gameObject);
|
RecalculateRope();
|
||||||
return Vector3.zero;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return GetRationalBezierPoint(startPoint.position, currentValue, endPoint.position, t, StartPointWeight, midPointWeight, EndPointWeight);
|
/// <summary>
|
||||||
|
/// Set the end point of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void SetEndPoint(Transform newEndPoint, bool recalculateRope = false)
|
||||||
|
{
|
||||||
|
endPoint = newEndPoint;
|
||||||
|
if (recalculateRope)
|
||||||
|
RecalculateRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the mid point of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void SetMidPoint(Transform newMidPoint, bool recalculateRope = false)
|
||||||
|
{
|
||||||
|
midPoint = newMidPoint;
|
||||||
|
if (recalculateRope)
|
||||||
|
RecalculateRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a point along the rope at the specified position (0-1)
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 GetPointAt(float position)
|
||||||
|
{
|
||||||
|
position = Mathf.Clamp01(position);
|
||||||
|
Vector3 mid = GetMidPoint();
|
||||||
|
return GetRationalBezierPoint(startPoint.position, mid, endPoint.position, position, StartPointWeight, midPointWeight, EndPointWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Force recalculation of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void RecalculateRope()
|
||||||
|
{
|
||||||
|
if (!isInitialized)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AreEndPointsValid())
|
||||||
|
{
|
||||||
|
SetSplinePoint();
|
||||||
|
SimulatePhysics();
|
||||||
|
NotifyPointsChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FixedUpdate()
|
private void FixedUpdate()
|
||||||
@@ -262,61 +331,6 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
// Gizmos.DrawSphere(midPos, 0.2f);
|
// 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()
|
private void NotifyPointsChanged()
|
||||||
{
|
{
|
||||||
|
|||||||
8
Assets/Playables.meta
Normal file
8
Assets/Playables.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2c0088270c13b3a4e8ce04a3f672887d
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
1248
Assets/Playables/SurfacingTimeline.playable
Normal file
1248
Assets/Playables/SurfacingTimeline.playable
Normal file
File diff suppressed because it is too large
Load Diff
8
Assets/Playables/SurfacingTimeline.playable.meta
Normal file
8
Assets/Playables/SurfacingTimeline.playable.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5ecd3cfdb172df5439e4522c15c48f75
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -248,6 +248,7 @@ GameObject:
|
|||||||
- component: {fileID: 173052725}
|
- component: {fileID: 173052725}
|
||||||
- component: {fileID: 173052727}
|
- component: {fileID: 173052727}
|
||||||
- component: {fileID: 173052726}
|
- component: {fileID: 173052726}
|
||||||
|
- component: {fileID: 173052728}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Rope2
|
m_Name: Rope2
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -339,15 +340,15 @@ LineRenderer:
|
|||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_Positions:
|
m_Positions:
|
||||||
- {x: 0, y: 4.1716814, z: 0}
|
- {x: 0, y: 4.1716814, z: 0}
|
||||||
- {x: -0.0011514801, y: 3.9187107, z: 0}
|
- {x: -0.0011514801, y: 3.9551861, z: 0}
|
||||||
- {x: -0.00230296, y: 3.6922278, z: 0}
|
- {x: -0.00230296, y: 3.757073, z: 0}
|
||||||
- {x: -0.0034544398, y: 3.4922323, z: 0}
|
- {x: -0.0034544398, y: 3.577342, z: 0}
|
||||||
- {x: -0.00460592, y: 3.3187256, z: 0}
|
- {x: -0.00460592, y: 3.4159937, z: 0}
|
||||||
- {x: -0.0057574, y: 3.1717062, z: 0}
|
- {x: -0.0057574, y: 3.273027, z: 0}
|
||||||
- {x: -0.0069088796, y: 3.0511749, z: 0}
|
- {x: -0.0069088796, y: 3.1484427, z: 0}
|
||||||
- {x: -0.008060359, y: 2.9571314, z: 0}
|
- {x: -0.008060359, y: 3.042241, z: 0}
|
||||||
- {x: -0.00921184, y: 2.8895762, z: 0}
|
- {x: -0.00921184, y: 2.9544215, z: 0}
|
||||||
- {x: -0.010363319, y: 2.8485086, z: 0}
|
- {x: -0.010363319, y: 2.884984, z: 0}
|
||||||
- {x: -0.0115148, y: 2.833929, z: 0}
|
- {x: -0.0115148, y: 2.833929, z: 0}
|
||||||
m_Parameters:
|
m_Parameters:
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
@@ -417,6 +418,28 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
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
|
--- !u!1 &224729330
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -427,6 +450,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 224729333}
|
- component: {fileID: 224729333}
|
||||||
- component: {fileID: 224729332}
|
- component: {fileID: 224729332}
|
||||||
|
- component: {fileID: 224729334}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: CinemachineCamera
|
m_Name: CinemachineCamera
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -492,6 +516,28 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 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
|
--- !u!1 &323864663
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -600,6 +646,14 @@ MonoBehaviour:
|
|||||||
spawnCooldown: 5
|
spawnCooldown: 5
|
||||||
basePoints: 10
|
basePoints: 10
|
||||||
depthMultiplier: 2
|
depthMultiplier: 2
|
||||||
|
playerRopes:
|
||||||
|
- {fileID: 1435210811}
|
||||||
|
- {fileID: 1062017697}
|
||||||
|
- {fileID: 173052728}
|
||||||
|
speedTransitionDuration: 2
|
||||||
|
surfacingSpeedFactor: 3
|
||||||
|
surfacingSpawnDelay: 3
|
||||||
|
surfacingTimeline: {fileID: 2064311130}
|
||||||
--- !u!4 &424805726
|
--- !u!4 &424805726
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -615,6 +669,116 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 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
|
--- !u!1 &730962732
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -718,6 +882,7 @@ GameObject:
|
|||||||
- component: {fileID: 747976402}
|
- component: {fileID: 747976402}
|
||||||
- component: {fileID: 747976403}
|
- component: {fileID: 747976403}
|
||||||
- component: {fileID: 747976404}
|
- component: {fileID: 747976404}
|
||||||
|
- component: {fileID: 747976405}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: BottleMarine
|
m_Name: BottleMarine
|
||||||
m_TagString: Player
|
m_TagString: Player
|
||||||
@@ -948,6 +1113,28 @@ MonoBehaviour:
|
|||||||
blinkRate: 0.15
|
blinkRate: 0.15
|
||||||
damageColorAlpha: 0.7
|
damageColorAlpha: 0.7
|
||||||
targetSpriteRenderer: {fileID: 730962734}
|
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
|
--- !u!1 &824396214
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1076,6 +1263,7 @@ MonoBehaviour:
|
|||||||
useObjectPooling: 1
|
useObjectPooling: 1
|
||||||
initialPoolSize: 10
|
initialPoolSize: 10
|
||||||
maxPoolSize: 30
|
maxPoolSize: 30
|
||||||
|
surfacingSpeedFactor: 0.5
|
||||||
--- !u!4 &1003335105
|
--- !u!4 &1003335105
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1102,6 +1290,7 @@ GameObject:
|
|||||||
- component: {fileID: 1062017694}
|
- component: {fileID: 1062017694}
|
||||||
- component: {fileID: 1062017696}
|
- component: {fileID: 1062017696}
|
||||||
- component: {fileID: 1062017695}
|
- component: {fileID: 1062017695}
|
||||||
|
- component: {fileID: 1062017697}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Rope3
|
m_Name: Rope3
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -1193,15 +1382,15 @@ LineRenderer:
|
|||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_Positions:
|
m_Positions:
|
||||||
- {x: 0, y: 4.1716814, z: 0}
|
- {x: 0, y: 4.1716814, z: 0}
|
||||||
- {x: 0.036271624, y: 3.927396, z: 0}
|
- {x: 0.036271624, y: 3.9653695, z: 0}
|
||||||
- {x: 0.07254324, y: 3.7076683, z: 0}
|
- {x: 0.07254324, y: 3.7751768, z: 0}
|
||||||
- {x: 0.10881486, y: 3.5124984, z: 0}
|
- {x: 0.10881486, y: 3.6011028, z: 0}
|
||||||
- {x: 0.14508648, y: 3.3418865, z: 0}
|
- {x: 0.14508648, y: 3.443149, z: 0}
|
||||||
- {x: 0.1813581, y: 3.195832, z: 0}
|
- {x: 0.1813581, y: 3.3013139, z: 0}
|
||||||
- {x: 0.21762972, y: 3.0743358, z: 0}
|
- {x: 0.21762972, y: 3.1755984, z: 0}
|
||||||
- {x: 0.25390133, y: 2.9773972, z: 0}
|
- {x: 0.25390133, y: 3.066002, z: 0}
|
||||||
- {x: 0.29017296, y: 2.905017, z: 0}
|
- {x: 0.29017296, y: 2.9725251, z: 0}
|
||||||
- {x: 0.32644457, y: 2.857194, z: 0}
|
- {x: 0.32644457, y: 2.8951674, z: 0}
|
||||||
- {x: 0.3627162, y: 2.833929, z: 0}
|
- {x: 0.3627162, y: 2.833929, z: 0}
|
||||||
m_Parameters:
|
m_Parameters:
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
@@ -1271,6 +1460,28 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
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
|
--- !u!1 &1063641111
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1283,6 +1494,7 @@ GameObject:
|
|||||||
- component: {fileID: 1063641113}
|
- component: {fileID: 1063641113}
|
||||||
- component: {fileID: 1063641112}
|
- component: {fileID: 1063641112}
|
||||||
- component: {fileID: 1063641115}
|
- component: {fileID: 1063641115}
|
||||||
|
- component: {fileID: 1063641116}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Main Camera
|
m_Name: Main Camera
|
||||||
m_TagString: MainCamera
|
m_TagString: MainCamera
|
||||||
@@ -1307,8 +1519,8 @@ Camera:
|
|||||||
m_GameObject: {fileID: 1063641111}
|
m_GameObject: {fileID: 1063641111}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_ClearFlags: 1
|
m_ClearFlags: 2
|
||||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
m_BackGroundColor: {r: 0.5722232, g: 0.6321867, b: 0.7264151, a: 0}
|
||||||
m_projectionMatrixMode: 1
|
m_projectionMatrixMode: 1
|
||||||
m_GateFitMode: 2
|
m_GateFitMode: 2
|
||||||
m_FOVAxisMode: 0
|
m_FOVAxisMode: 0
|
||||||
@@ -1396,6 +1608,50 @@ MonoBehaviour:
|
|||||||
m_PostInfinity: 2
|
m_PostInfinity: 2
|
||||||
m_RotationOrder: 4
|
m_RotationOrder: 4
|
||||||
CustomBlends: {fileID: 0}
|
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
|
--- !u!1 &1224833348
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1666,15 +1922,15 @@ LineRenderer:
|
|||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_Positions:
|
m_Positions:
|
||||||
- {x: 0, y: 4.1716814, z: 0}
|
- {x: 0, y: 4.1716814, z: 0}
|
||||||
- {x: -0.03339292, y: 3.9260902, z: 0}
|
- {x: -0.03339292, y: 3.9638388, z: 0}
|
||||||
- {x: -0.066785835, y: 3.705347, z: 0}
|
- {x: -0.066785835, y: 3.7724557, z: 0}
|
||||||
- {x: -0.10017875, y: 3.5094519, z: 0}
|
- {x: -0.10017875, y: 3.5975313, z: 0}
|
||||||
- {x: -0.13357168, y: 3.3384047, z: 0}
|
- {x: -0.13357168, y: 3.4390674, z: 0}
|
||||||
- {x: -0.16696459, y: 3.1922054, z: 0}
|
- {x: -0.16696459, y: 3.2970622, z: 0}
|
||||||
- {x: -0.20035751, y: 3.0708542, z: 0}
|
- {x: -0.20035751, y: 3.1715167, z: 0}
|
||||||
- {x: -0.2337504, y: 2.9743507, z: 0}
|
- {x: -0.2337504, y: 3.0624304, z: 0}
|
||||||
- {x: -0.26714337, y: 2.9026957, z: 0}
|
- {x: -0.26714337, y: 2.969804, z: 0}
|
||||||
- {x: -0.30053627, y: 2.8558884, z: 0}
|
- {x: -0.30053627, y: 2.8936367, z: 0}
|
||||||
- {x: -0.33392918, y: 2.833929, z: 0}
|
- {x: -0.33392918, y: 2.833929, z: 0}
|
||||||
m_Parameters:
|
m_Parameters:
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
@@ -1744,51 +2000,28 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
m_ApplyActiveColorSpace: 1
|
||||||
--- !u!23 &1435210811
|
--- !u!114 &1435210811
|
||||||
MeshRenderer:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 1435210807}
|
m_GameObject: {fileID: 1435210807}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_CastShadows: 1
|
m_EditorHideFlags: 0
|
||||||
m_ReceiveShadows: 1
|
m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
|
||||||
m_DynamicOccludee: 1
|
m_Name:
|
||||||
m_StaticShadowCaster: 0
|
m_EditorClassIdentifier:
|
||||||
m_MotionVectors: 1
|
breakPosition: 0.5
|
||||||
m_LightProbeUsage: 1
|
breakEffect: {fileID: 0}
|
||||||
m_ReflectionProbeUsage: 1
|
breakSound: {fileID: 0}
|
||||||
m_RayTracingMode: 2
|
ropeFollowSpeed: 5
|
||||||
m_RayTraceProcedural: 0
|
ropeTrailing: 0.2
|
||||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
ropeGravityStrength: 9.8
|
||||||
m_RayTracingAccelStructBuildFlags: 1
|
ropeVerticalHangStrength: 2
|
||||||
m_SmallMeshCulling: 1
|
ropeDamping: 0.3
|
||||||
m_RenderingLayerMask: 1
|
initialSeparationDistance: 0.1
|
||||||
m_RendererPriority: 0
|
initialFallImpulse: 2
|
||||||
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}
|
|
||||||
--- !u!1 &1679185997
|
--- !u!1 &1679185997
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1842,7 +2075,7 @@ MonoBehaviour:
|
|||||||
- {fileID: 2956826569642009690, guid: 7f7f10ca24a5afe46be797daea64111a, type: 3}
|
- {fileID: 2956826569642009690, guid: 7f7f10ca24a5afe46be797daea64111a, type: 3}
|
||||||
initialTileCount: 3
|
initialTileCount: 3
|
||||||
tileSpawnBuffer: 1
|
tileSpawnBuffer: 1
|
||||||
moveSpeed: 3
|
moveSpeed: 2
|
||||||
speedUpFactor: 0
|
speedUpFactor: 0
|
||||||
speedUpInterval: 0
|
speedUpInterval: 0
|
||||||
maxMoveSpeed: 12
|
maxMoveSpeed: 12
|
||||||
@@ -1855,6 +2088,10 @@ MonoBehaviour:
|
|||||||
onTileDestroyed:
|
onTileDestroyed:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
velocityCalculationInterval: 0.5
|
||||||
|
onLastTileLeft:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
--- !u!1 &1834056336
|
--- !u!1 &1834056336
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -2004,6 +2241,61 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 2106431002}
|
m_Father: {fileID: 2106431002}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
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
|
--- !u!1 &2106431001
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -2017,7 +2309,7 @@ GameObject:
|
|||||||
- component: {fileID: 2106431004}
|
- component: {fileID: 2106431004}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Rock
|
m_Name: Rock
|
||||||
m_TagString: Untagged
|
m_TagString: Rock
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
@@ -2095,3 +2387,5 @@ SceneRoots:
|
|||||||
- {fileID: 116234201}
|
- {fileID: 116234201}
|
||||||
- {fileID: 824396217}
|
- {fileID: 824396217}
|
||||||
- {fileID: 323864665}
|
- {fileID: 323864665}
|
||||||
|
- {fileID: 461301697}
|
||||||
|
- {fileID: 2064311129}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
"AstarPathfindingProject",
|
"AstarPathfindingProject",
|
||||||
"Unity.ResourceManager",
|
"Unity.ResourceManager",
|
||||||
"Unity.InputSystem",
|
"Unity.InputSystem",
|
||||||
"Unity.TextMeshPro"
|
"Unity.TextMeshPro",
|
||||||
|
"OptimizedRope"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -26,10 +26,15 @@ namespace Minigames.DivingForPictures
|
|||||||
public int initialPoolSize = 10;
|
public int initialPoolSize = 10;
|
||||||
public int maxPoolSize = 30;
|
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 _timer;
|
||||||
private float _nextSpawnInterval;
|
private float _nextSpawnInterval;
|
||||||
private BubblePool _bubblePool;
|
private BubblePool _bubblePool;
|
||||||
private Camera _mainCamera; // Cache camera reference
|
private Camera _mainCamera; // Cache camera reference
|
||||||
|
private bool _isSurfacing = false;
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
@@ -98,7 +103,18 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Randomize bubble properties
|
// 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);
|
bubble.wobbleSpeed = Random.Range(wobbleSpeedRange.x, wobbleSpeedRange.y);
|
||||||
|
|
||||||
// Set base scale (initial size) for the bubble
|
// Set base scale (initial size) for the bubble
|
||||||
@@ -119,6 +135,25 @@ namespace Minigames.DivingForPictures
|
|||||||
bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
|
bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start surfacing mode - slow down all bubbles
|
||||||
|
/// </summary>
|
||||||
|
public void StartSurfacing()
|
||||||
|
{
|
||||||
|
if (_isSurfacing) return; // Already surfacing
|
||||||
|
|
||||||
|
_isSurfacing = true;
|
||||||
|
|
||||||
|
// Slow down all existing bubbles
|
||||||
|
Bubble[] activeBubbles = FindObjectsOfType<Bubble>();
|
||||||
|
foreach (Bubble bubble in activeBubbles)
|
||||||
|
{
|
||||||
|
bubble.speed *= surfacingSpeedFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"[BubbleSpawner] Started surfacing mode. Bubbles slowed to {surfacingSpeedFactor * 100}% speed.");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logs the current pool statistics for debugging
|
/// Logs the current pool statistics for debugging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
|
using UnityEngine.Playables;
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -31,6 +33,20 @@ namespace Minigames.DivingForPictures
|
|||||||
[Tooltip("Additional points per depth unit")]
|
[Tooltip("Additional points per depth unit")]
|
||||||
[SerializeField] private int depthMultiplier = 10;
|
[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 state variables
|
||||||
private int playerScore = 0;
|
private int playerScore = 0;
|
||||||
private float currentSpawnProbability;
|
private float currentSpawnProbability;
|
||||||
@@ -38,14 +54,32 @@ namespace Minigames.DivingForPictures
|
|||||||
private float timeSinceLastSpawn = 0f;
|
private float timeSinceLastSpawn = 0f;
|
||||||
private List<Monster> activeMonsters = new List<Monster>();
|
private List<Monster> activeMonsters = new List<Monster>();
|
||||||
|
|
||||||
|
// 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 properties
|
||||||
public int PlayerScore => playerScore;
|
public int PlayerScore => playerScore;
|
||||||
|
public float CurrentVelocityFactor => _currentVelocityFactor;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
public event Action<int> OnScoreChanged;
|
public event Action<int> OnScoreChanged;
|
||||||
public event Action<Monster> OnMonsterSpawned;
|
public event Action<Monster> OnMonsterSpawned;
|
||||||
public event Action<Monster, int> OnPictureTaken;
|
public event Action<Monster, int> OnPictureTaken;
|
||||||
public event Action<float> OnSpawnProbabilityChanged;
|
public event Action<float> OnSpawnProbabilityChanged;
|
||||||
|
public event Action OnGameOver;
|
||||||
|
public event Action<int> OnRopeBroken; // Passes remaining ropes count
|
||||||
|
public event Action<float> 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()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -64,6 +98,18 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
Debug.LogWarning("No TrenchTileSpawner found in scene. Monster spawning won't work.");
|
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()
|
private void Update()
|
||||||
@@ -92,6 +138,9 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
if (spawnPoints.Length == 0) return;
|
if (spawnPoints.Length == 0) return;
|
||||||
|
|
||||||
|
// If we're surfacing, don't spawn new monsters
|
||||||
|
if (_isSurfacing) return;
|
||||||
|
|
||||||
bool forceSpawn = timeSinceLastSpawn >= guaranteedSpawnTime;
|
bool forceSpawn = timeSinceLastSpawn >= guaranteedSpawnTime;
|
||||||
bool onCooldown = timeSinceLastSpawn < spawnCooldown;
|
bool onCooldown = timeSinceLastSpawn < spawnCooldown;
|
||||||
|
|
||||||
@@ -176,6 +225,335 @@ namespace Minigames.DivingForPictures
|
|||||||
monster.OnMonsterDespawned -= OnMonsterDespawned;
|
monster.OnMonsterDespawned -= OnMonsterDespawned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the player takes damage from any collision
|
||||||
|
/// </summary>
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Breaks the next available rope in the sequence
|
||||||
|
/// </summary>
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manually break a rope (for testing or external events)
|
||||||
|
/// </summary>
|
||||||
|
public void ForceBreakRope()
|
||||||
|
{
|
||||||
|
if (!isGameOver)
|
||||||
|
{
|
||||||
|
OnPlayerDamageTaken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers game over state when all ropes are broken
|
||||||
|
/// </summary>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates rope references and logs warnings if any are missing
|
||||||
|
/// </summary>
|
||||||
|
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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the rope system for a new game
|
||||||
|
/// </summary>
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts the surfacing mode - reverses trench direction and adjusts all spawned entities
|
||||||
|
/// </summary>
|
||||||
|
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<TrenchTileSpawner>();
|
||||||
|
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<Component>())
|
||||||
|
{
|
||||||
|
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<Component>())
|
||||||
|
{
|
||||||
|
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<BubbleSpawner>();
|
||||||
|
if (bubbleSpawner != null)
|
||||||
|
{
|
||||||
|
bubbleSpawner.StartSurfacing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Find obstacle spawner and set up for velocity changes
|
||||||
|
ObstacleSpawner obstacleSpawner = FindFirstObjectByType<ObstacleSpawner>();
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Coroutine to animate the rock falling below the screen
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Coroutine to reset the player's X position to 0 over time
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Coroutine to handle the surfacing sequence timing
|
||||||
|
/// </summary>
|
||||||
|
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<TrenchTileSpawner>();
|
||||||
|
if (tileSpawner != null)
|
||||||
|
{
|
||||||
|
// Tell it to stop spawning new tiles
|
||||||
|
tileSpawner.StopSpawning();
|
||||||
|
Debug.Log("[DivingGameManager] Stopped spawning new tiles after delay");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the last tile leaves the screen
|
||||||
|
/// </summary>
|
||||||
|
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
|
// Call this when the game ends
|
||||||
public void EndGame()
|
public void EndGame()
|
||||||
{
|
{
|
||||||
@@ -193,5 +571,49 @@ namespace Minigames.DivingForPictures
|
|||||||
// Final score could be saved to player prefs or other persistence
|
// Final score could be saved to player prefs or other persistence
|
||||||
Debug.Log($"Final Score: {playerScore}");
|
Debug.Log($"Final Score: {playerScore}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts a smooth transition to the new velocity factor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="targetFactor">Target velocity factor (e.g., -1.0 for surfacing speed)</param>
|
||||||
|
public void SetVelocityFactor(float targetFactor)
|
||||||
|
{
|
||||||
|
if (_velocityTransitionCoroutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(_velocityTransitionCoroutine);
|
||||||
|
}
|
||||||
|
|
||||||
|
_velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Coroutine to smoothly transition the velocity factor over time
|
||||||
|
/// </summary>
|
||||||
|
private IEnumerator<WaitForEndOfFrame> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,12 @@ namespace Minigames.DivingForPictures
|
|||||||
private Collider2D _collider;
|
private Collider2D _collider;
|
||||||
private Camera _mainCamera;
|
private Camera _mainCamera;
|
||||||
private float _screenTop;
|
private float _screenTop;
|
||||||
|
private float _screenBottom; // Added to track bottom of screen
|
||||||
private Coroutine _movementCoroutine;
|
private Coroutine _movementCoroutine;
|
||||||
private Coroutine _offScreenCheckCoroutine;
|
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()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -62,6 +66,7 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
|
|
||||||
_mainCamera = Camera.main;
|
_mainCamera = Camera.main;
|
||||||
|
_baseMoveSpeed = moveSpeed; // Store original speed
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
@@ -105,6 +110,30 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the velocity factor changes from the DivingGameManager via ObstacleSpawner
|
||||||
|
/// </summary>
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Coroutine that handles obstacle movement
|
/// Coroutine that handles obstacle movement
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -112,8 +141,12 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
while (enabled && gameObject.activeInHierarchy)
|
while (enabled && gameObject.activeInHierarchy)
|
||||||
{
|
{
|
||||||
// Move the obstacle upward
|
// Use velocity factor sign to determine direction
|
||||||
transform.position += Vector3.up * (moveSpeed * Time.deltaTime);
|
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
|
// Wait for next frame
|
||||||
yield return null;
|
yield return null;
|
||||||
@@ -165,6 +198,9 @@ namespace Minigames.DivingForPictures
|
|||||||
Vector3 topWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 1f, _mainCamera.transform.position.z));
|
Vector3 topWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 1f, _mainCamera.transform.position.z));
|
||||||
_screenTop = topWorldPoint.y;
|
_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)
|
// 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
|
// Use a larger buffer to ensure obstacles are truly off-screen before returning to pool
|
||||||
if (transform.position.y > _screenTop + 5f)
|
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}");
|
Debug.Log($"[FloatingObstacle] {gameObject.name} off-screen at Y:{transform.position.y:F2}, screen top:{_screenTop:F2}");
|
||||||
ReturnToPool();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -279,5 +320,20 @@ namespace Minigames.DivingForPictures
|
|||||||
StartObstacleBehavior();
|
StartObstacleBehavior();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets surfacing mode, which reverses obstacle movement direction
|
||||||
|
/// </summary>
|
||||||
|
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}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ namespace Minigames.DivingForPictures
|
|||||||
private Coroutine _spawnCoroutine;
|
private Coroutine _spawnCoroutine;
|
||||||
private readonly List<GameObject> _activeObstacles = new List<GameObject>();
|
private readonly List<GameObject> _activeObstacles = new List<GameObject>();
|
||||||
private int _obstacleCounter = 0; // Counter for unique obstacle naming
|
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()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -250,6 +252,13 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void TrySpawnObstacle()
|
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}");
|
Debug.Log($"[ObstacleSpawner] TrySpawnObstacle called at {Time.time:F2}");
|
||||||
|
|
||||||
if (obstaclePrefabs == null || obstaclePrefabs.Count == 0)
|
if (obstaclePrefabs == null || obstaclePrefabs.Count == 0)
|
||||||
@@ -338,25 +347,53 @@ namespace Minigames.DivingForPictures
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[ObstacleSpawner] Got obstacle {obstacle.name} from pool, active state: {obstacle.activeInHierarchy}");
|
// Important: Set position/parent/rotation BEFORE activation to avoid visual glitches
|
||||||
|
|
||||||
// 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}");
|
|
||||||
}
|
|
||||||
|
|
||||||
obstacle.transform.position = position;
|
obstacle.transform.position = position;
|
||||||
obstacle.transform.rotation = prefab.transform.rotation;
|
obstacle.transform.rotation = prefab.transform.rotation;
|
||||||
obstacle.transform.SetParent(transform);
|
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
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[ObstacleSpawner] Instantiating new obstacle (pooling disabled)");
|
Debug.Log($"[ObstacleSpawner] Instantiating new obstacle (pooling disabled)");
|
||||||
obstacle = Instantiate(prefab, position, prefab.transform.rotation, transform);
|
obstacle = Instantiate(prefab, position, prefab.transform.rotation, transform);
|
||||||
|
|
||||||
|
// Configure the newly instantiated obstacle
|
||||||
|
ConfigureObstacle(obstacle, prefabIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign unique name with counter
|
// Assign unique name with counter
|
||||||
@@ -364,10 +401,6 @@ namespace Minigames.DivingForPictures
|
|||||||
string oldName = obstacle.name;
|
string oldName = obstacle.name;
|
||||||
obstacle.name = $"Obstacle{_obstacleCounter:D3}";
|
obstacle.name = $"Obstacle{_obstacleCounter:D3}";
|
||||||
Debug.Log($"[ObstacleSpawner] Renamed obstacle from '{oldName}' to '{obstacle.name}', active state: {obstacle.activeInHierarchy}");
|
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
|
// Track active obstacles
|
||||||
_activeObstacles.Add(obstacle);
|
_activeObstacles.Add(obstacle);
|
||||||
@@ -459,6 +492,55 @@ namespace Minigames.DivingForPictures
|
|||||||
CalculateScreenBounds();
|
CalculateScreenBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the velocity factor changes from the DivingGameManager
|
||||||
|
/// </summary>
|
||||||
|
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<FloatingObstacle>();
|
||||||
|
if (obstacleComponent != null)
|
||||||
|
{
|
||||||
|
obstacleComponent.OnVelocityFactorChanged(velocityFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"[ObstacleSpawner] Velocity factor updated to {_velocityFactor:F2}, propagated to {_activeObstacles.Count} active obstacles");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start surfacing mode - reverse direction of existing obstacles and stop spawning new ones
|
||||||
|
/// </summary>
|
||||||
|
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<FloatingObstacle>();
|
||||||
|
if (obstacleComponent != null)
|
||||||
|
{
|
||||||
|
// Call StartSurfacing on the obstacle component itself
|
||||||
|
obstacleComponent.StartSurfacing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"[ObstacleSpawner] Started surfacing mode for {_activeObstacles.Count} active obstacles");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the count of currently active obstacles
|
/// Gets the count of currently active obstacles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
331
Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
Normal file
331
Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using GogoGaga.OptimizedRopesAndCables;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component that allows breaking a rope in half.
|
||||||
|
/// Attach this to the same GameObject that has a Rope and LineRenderer component.
|
||||||
|
/// </summary>
|
||||||
|
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<Rope>();
|
||||||
|
originalLineRenderer = GetComponent<LineRenderer>();
|
||||||
|
|
||||||
|
if (originalRope == null || originalLineRenderer == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("RopeBreaker requires both Rope and LineRenderer components on the same GameObject");
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Breaks the rope at the specified position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="breakPositionOverride">Optional override for break position (0-1)</param>
|
||||||
|
/// <returns>True if rope was broken successfully, false otherwise</returns>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a transform at the break point to use as an anchor
|
||||||
|
/// </summary>
|
||||||
|
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<RopeEndPhysicsFollower>();
|
||||||
|
|
||||||
|
// 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<RopeEndPhysicsFollower>();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates two new rope GameObjects for the broken segments
|
||||||
|
/// </summary>
|
||||||
|
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<Rope>();
|
||||||
|
|
||||||
|
// Get the LineRenderer that was automatically added
|
||||||
|
LineRenderer firstLineRenderer = firstHalfRope.GetComponent<LineRenderer>();
|
||||||
|
if (firstLineRenderer == null)
|
||||||
|
{
|
||||||
|
// Only add if somehow not created (shouldn't happen, but safety check)
|
||||||
|
firstLineRenderer = firstHalfRope.AddComponent<LineRenderer>();
|
||||||
|
}
|
||||||
|
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<Rope>();
|
||||||
|
|
||||||
|
// Get the LineRenderer that was automatically added
|
||||||
|
LineRenderer secondLineRenderer = secondHalfRope.GetComponent<LineRenderer>();
|
||||||
|
if (secondLineRenderer == null)
|
||||||
|
{
|
||||||
|
// Only add if somehow not created (shouldn't happen, but safety check)
|
||||||
|
secondLineRenderer = secondHalfRope.AddComponent<LineRenderer>();
|
||||||
|
}
|
||||||
|
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<RopeEndPhysicsFollower>();
|
||||||
|
if (playerFollower != null)
|
||||||
|
{
|
||||||
|
playerFollower.SetMaxDistance(firstHalfRopeComponent.ropeLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
RopeEndPhysicsFollower rockFollower = secondBreakTransform.GetComponent<RopeEndPhysicsFollower>();
|
||||||
|
if (rockFollower != null)
|
||||||
|
{
|
||||||
|
rockFollower.SetMaxDistance(secondHalfRopeComponent.ropeLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies properties from one LineRenderer to another
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies properties from one Rope to another
|
||||||
|
/// </summary>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plays visual and audio effects at the break point
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restores the original rope and cleans up the broken pieces
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 30919200017f4879867c3b6289429924
|
||||||
|
timeCreated: 1758466190
|
||||||
@@ -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<Rope>();
|
||||||
|
if (attachedRope == null)
|
||||||
|
{
|
||||||
|
attachedRope = GetComponentInParent<Rope>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still couldn't find it, look for it on a child GameObject
|
||||||
|
if (attachedRope == null)
|
||||||
|
{
|
||||||
|
attachedRope = GetComponentInChildren<Rope>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for a rope attached to this endpoint
|
||||||
|
if (attachedRope == null)
|
||||||
|
{
|
||||||
|
// Find any rope that has this transform as an endpoint
|
||||||
|
Rope[] allRopes = FindObjectsOfType<Rope>();
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bc5a0e35b5e74474b4241fae08971e7a
|
||||||
|
timeCreated: 1758485385
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
@@ -48,13 +49,31 @@ namespace Minigames.DivingForPictures
|
|||||||
private float _screenBottom;
|
private float _screenBottom;
|
||||||
private float _screenTop;
|
private float _screenTop;
|
||||||
private TrenchTilePool _tilePool;
|
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 TileSpawnZ = -1f;
|
||||||
private const float DefaultTileHeight = 5f;
|
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()
|
private void Awake()
|
||||||
{
|
{
|
||||||
_mainCamera = Camera.main;
|
_mainCamera = Camera.main;
|
||||||
|
_baseMoveSpeed = moveSpeed; // Store the original base speed
|
||||||
|
|
||||||
// Calculate tile heights for each prefab
|
// Calculate tile heights for each prefab
|
||||||
CalculateTileHeights();
|
CalculateTileHeights();
|
||||||
@@ -89,15 +108,57 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
CalculateScreenBounds();
|
CalculateScreenBounds();
|
||||||
SpawnInitialTiles();
|
SpawnInitialTiles();
|
||||||
|
|
||||||
|
// Initialize velocity and start the velocity calculation coroutine
|
||||||
|
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
||||||
|
StartCoroutine(VelocityCalculationRoutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
MoveTiles();
|
HandleMovement();
|
||||||
HandleTileDestruction();
|
HandleTileDestruction();
|
||||||
HandleTileSpawning();
|
HandleTileSpawning();
|
||||||
HandleSpeedRamping();
|
HandleSpeedRamping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current velocity of the tiles
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current upward velocity of the tiles</returns>
|
||||||
|
public float GetCurrentVelocity()
|
||||||
|
{
|
||||||
|
return _currentVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a custom velocity, overriding the calculated one
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="velocity">The new velocity value</param>
|
||||||
|
public void SetVelocity(float velocity)
|
||||||
|
{
|
||||||
|
_currentVelocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Coroutine that periodically calculates the velocity based on game state
|
||||||
|
/// </summary>
|
||||||
|
private IEnumerator VelocityCalculationRoutine()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
CalculateVelocity();
|
||||||
|
yield return new WaitForSeconds(velocityCalculationInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the current velocity based on move speed
|
||||||
|
/// </summary>
|
||||||
|
private void CalculateVelocity()
|
||||||
|
{
|
||||||
|
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculate height values for all tile prefabs
|
/// Calculate height values for all tile prefabs
|
||||||
@@ -170,9 +231,25 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SpawnInitialTiles()
|
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++)
|
for (int i = 0; i < initialTileCount; i++)
|
||||||
{
|
{
|
||||||
float y = _screenBottom;
|
float y = startingY;
|
||||||
// Calculate proper Y position based on previous tiles
|
// Calculate proper Y position based on previous tiles
|
||||||
if (i > 0 && _activeTiles.Count > 0)
|
if (i > 0 && _activeTiles.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -206,16 +283,61 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move all active tiles upward
|
/// Called when the velocity factor changes from the DivingGameManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reverses direction to start surfacing
|
||||||
|
/// </summary>
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops spawning new tiles
|
||||||
|
/// </summary>
|
||||||
|
public void StopSpawning()
|
||||||
|
{
|
||||||
|
_stopSpawning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the movement of all active tiles based on the current velocity
|
||||||
|
/// </summary>
|
||||||
|
private void HandleMovement()
|
||||||
{
|
{
|
||||||
float moveDelta = moveSpeed * Time.deltaTime;
|
|
||||||
foreach (var tile in _activeTiles)
|
foreach (var tile in _activeTiles)
|
||||||
{
|
{
|
||||||
if (tile != null)
|
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);
|
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);
|
_activeTiles.RemoveAt(0);
|
||||||
onTileDestroyed?.Invoke(topTile);
|
onTileDestroyed?.Invoke(topTile);
|
||||||
@@ -265,7 +400,15 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void HandleTileSpawning()
|
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];
|
GameObject bottomTile = _activeTiles[^1];
|
||||||
if (bottomTile == null)
|
if (bottomTile == null)
|
||||||
@@ -274,15 +417,60 @@ namespace Minigames.DivingForPictures
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the tile height once to use in all calculations
|
||||||
float tileHeight = GetTileHeight(bottomTile);
|
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);
|
SpawnTileAtY(newY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle increasing the movement speed over time
|
/// Handle increasing the movement speed over time
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ TagManager:
|
|||||||
tags:
|
tags:
|
||||||
- CharacterArt
|
- CharacterArt
|
||||||
- Pulver
|
- Pulver
|
||||||
|
- Rock
|
||||||
layers:
|
layers:
|
||||||
- Default
|
- Default
|
||||||
- TransparentFX
|
- TransparentFX
|
||||||
|
|||||||
Reference in New Issue
Block a user