Surfacing functions in all manager components
This commit is contained in:
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
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ namespace Minigames.DivingForPictures
|
|||||||
// Private state variables for rope system
|
// Private state variables for rope system
|
||||||
private int currentRopeIndex = 0;
|
private int currentRopeIndex = 0;
|
||||||
private bool isGameOver = false;
|
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()
|
||||||
{
|
{
|
||||||
@@ -114,6 +118,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;
|
||||||
|
|
||||||
@@ -319,6 +326,40 @@ namespace Minigames.DivingForPictures
|
|||||||
Debug.Log("[DivingGameManager] Rope system reset.");
|
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. Find and reverse trench tile spawner
|
||||||
|
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
||||||
|
if (tileSpawner != null)
|
||||||
|
{
|
||||||
|
tileSpawner.StartSurfacing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Find bubble spawner and slow down existing bubbles
|
||||||
|
BubbleSpawner bubbleSpawner = FindFirstObjectByType<BubbleSpawner>();
|
||||||
|
if (bubbleSpawner != null)
|
||||||
|
{
|
||||||
|
bubbleSpawner.StartSurfacing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Find obstacle spawner and reverse existing obstacles
|
||||||
|
ObstacleSpawner obstacleSpawner = FindFirstObjectByType<ObstacleSpawner>();
|
||||||
|
if (obstacleSpawner != null)
|
||||||
|
{
|
||||||
|
obstacleSpawner.StartSurfacing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Monster spawning is handled automatically through the Update and OnTileSpawned methods
|
||||||
|
// which will check the _isSurfacing flag
|
||||||
|
}
|
||||||
|
|
||||||
// Call this when the game ends
|
// Call this when the game ends
|
||||||
public void EndGame()
|
public void EndGame()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,8 +44,10 @@ 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 void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -165,6 +167,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 +177,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 +289,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,7 @@ 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 void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -250,6 +251,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 +346,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 +400,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 +491,32 @@ namespace Minigames.DivingForPictures
|
|||||||
CalculateScreenBounds();
|
CalculateScreenBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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;
|
||||||
|
|
||||||
|
// Reverse direction of all existing obstacles
|
||||||
|
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. Reversed direction of {_activeObstacles.Count} active obstacles.");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the count of currently active obstacles
|
/// Gets the count of currently active obstacles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user