diff --git a/Assets/Scripts/Camera/CameraShake.cs b/Assets/Scripts/Camera/CameraShake.cs new file mode 100644 index 0000000..4477f40 --- /dev/null +++ b/Assets/Scripts/Camera/CameraShake.cs @@ -0,0 +1,101 @@ +using System.Collections; +using UnityEngine; + +/// +/// Handles camera shake effects to simulate explosions or impacts. +/// The script shakes the camera for a specified duration after a delay +/// and plays an explosion sound effect. +/// +public class CameraShake : MonoBehaviour +{ + /// + /// The main camera to apply the shake effect to. + /// + public Camera mainCamera; + + /// + /// The audio source used to play sound effects. + /// + public AudioSource audioSource; + + /// + /// The audio clip to play during the shake effect. + /// + public AudioClip explosionSound; + + /// + /// Cached transform of the main camera for optimization. + /// + private Transform _cameraTransform; + + /// + /// Original position of the camera to reset after shaking. + /// + private Vector3 _originalPosition; + + /// + /// Initializes the camera shake effect by setting up the camera transform + /// and original position. Starts the shake with a delay. + /// + private void Awake() + { + // Ensure the main camera is assigned + if (mainCamera != null) + { + _cameraTransform = mainCamera.transform; // Cache the camera's transform + _originalPosition = _cameraTransform.localPosition; // Store the original position + StartDelayedShake(11f, 300f, 1f); // Start the shake effect with parameters + } + else + { + Debug.LogError("Main Camera is not assigned."); // Log an error if camera is not set + } + } + + /// + /// Starts the shake effect after a specified delay. + /// + /// Time in seconds to wait before starting the shake. + /// Total duration of the shake effect in seconds. + /// The intensity of the shake effect. + private void StartDelayedShake(float delay, float duration, float magnitude) + { + StartCoroutine(DelayedShakeCoroutine(delay, duration, magnitude)); // Start the coroutine for the shake effect + } + + /// + /// Coroutine to handle the shaking of the camera over time. + /// + /// Time in seconds to wait before starting the shake. + /// Total duration of the shake effect in seconds. + /// The initial intensity of the shake effect. + /// Yield instruction to control the coroutine's timing. + private IEnumerator DelayedShakeCoroutine(float delay, float duration, float magnitude) + { + yield return new WaitForSeconds(delay); // Wait for the specified delay + + float elapsed = 0.0f; // Track elapsed time + + audioSource.PlayOneShot(explosionSound); // Play the explosion sound + + // Perform the shake effect over the specified duration + while (elapsed < duration) + { + // Calculate random offsets for shaking + var x = Random.Range(-1f, 1f) * magnitude; + var y = Random.Range(-1f, 1f) * magnitude; + + // Update the camera's local position to create the shake effect + _cameraTransform.localPosition = new Vector3(x, y, _originalPosition.z); + + elapsed += Time.deltaTime; // Increment elapsed time + + // Gradually decrease the magnitude of shaking + magnitude = Mathf.Lerp(magnitude, 0, elapsed / duration); + yield return null; // Wait for the next frame + } + + // Reset the camera's position to its original state + _cameraTransform.localPosition = _originalPosition; + } +} diff --git a/Assets/Scripts/Camera/CutsceneController.cs b/Assets/Scripts/Camera/CutsceneController.cs new file mode 100644 index 0000000..ba12412 --- /dev/null +++ b/Assets/Scripts/Camera/CutsceneController.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +/// +/// Manages the cutscene sequence by controlling the cutscene camera's movement +/// along a spline for a specified duration, after which it switches back to the +/// player camera. +/// +public class CutsceneController : MonoBehaviour +{ + /// + /// The camera used for the cutscene. + /// + public Camera cutsceneCamera; + + /// + /// The camera used for regular gameplay. + /// + public Camera playerCamera; + + /// + /// The parent GameObject that controls the spline path for the cutscene. + /// + public Transform splineParent; + + /// + /// The speed at which the cutscene camera follows the spline. + /// + public float speed = 1.0f; + + /// + /// Duration of the cutscene in seconds. + /// + private float duration = 6.0f; + + /// + /// Time elapsed since the start of the cutscene. + /// + private float elapsedTime = 0f; + + /// + /// Starting position of the cutscene camera. + /// + private Vector3 startPosition; + + /// + /// Target position for the cutscene camera to move towards. + /// + private Vector3 targetPosition; + + /// + /// Initializes the cutscene by setting the appropriate cameras and calculating + /// the target position along the spline. + /// + void Start() + { + // Disable the player camera and enable the cutscene camera to start the cutscene + playerCamera.gameObject.SetActive(false); + cutsceneCamera.gameObject.SetActive(true); + + // Store the initial position of the cutscene camera + startPosition = cutsceneCamera.transform.position; + + // Set the target position to the position of the spline parent + targetPosition = splineParent.position; // Modify this to follow a specific point on your spline if needed + } + + /// + /// Updates the cutscene camera's position over time, and switches back to the + /// player camera once the cutscene duration is reached. + /// + void Update() + { + // Accumulate the time elapsed since the start of the cutscene + elapsedTime += Time.deltaTime; + + // Move the cutscene camera along the spline until the duration is reached + if (elapsedTime < duration) + { + // Calculate the interpolation factor (t) based on elapsed time + float t = elapsedTime / duration; + + // Move the camera towards the target position using linear interpolation + cutsceneCamera.transform.position = Vector3.Lerp(startPosition, targetPosition, t); + } + else + { + // Once the cutscene duration has elapsed, destroy the cutscene camera + // and re-enable the player camera + Destroy(cutsceneCamera.gameObject); + playerCamera.gameObject.SetActive(true); + + // Disable this script to prevent further updates + enabled = false; + } + } +} diff --git a/Assets/Scripts/CameraShake.cs b/Assets/Scripts/CameraShake.cs deleted file mode 100644 index b625a4d..0000000 --- a/Assets/Scripts/CameraShake.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections; -using UnityEngine; - -public class CameraShake : MonoBehaviour -{ - public Camera mainCamera; - public AudioSource audioSource; - public AudioClip explosionSound; - - private Transform _cameraTransform; - private Vector3 _originalPosition; - - private void Awake() - { - if (mainCamera != null) - { - _cameraTransform = mainCamera.transform; - _originalPosition = _cameraTransform.localPosition; - StartDelayedShake(11f, 300f, 1f); - } - else - { - Debug.LogError("Main Camera is not assigned."); - } - } - - private void StartDelayedShake(float delay, float duration, float magnitude) - { - StartCoroutine(DelayedShakeCoroutine(delay, duration, magnitude)); - } - - private IEnumerator DelayedShakeCoroutine(float delay, float duration, float magnitude) - { - yield return new WaitForSeconds(delay); - - var elapsed = 0.0f; - - audioSource.PlayOneShot(explosionSound); - - while (elapsed < duration) - { - var x = Random.Range(-1f, 1f) * magnitude; - var y = Random.Range(-1f, 1f) * magnitude; - - _cameraTransform.localPosition = new Vector3(x, y, _originalPosition.z); - - elapsed += Time.deltaTime; - - magnitude = Mathf.Lerp(magnitude, 0, elapsed / duration); - yield return null; - } - - _cameraTransform.localPosition = _originalPosition; - } -} \ No newline at end of file diff --git a/Assets/Scripts/FirstPersonController.cs b/Assets/Scripts/Character/FirstPersonController.cs similarity index 100% rename from Assets/Scripts/FirstPersonController.cs rename to Assets/Scripts/Character/FirstPersonController.cs diff --git a/Assets/Scripts/Health.cs b/Assets/Scripts/Character/Health.cs similarity index 52% rename from Assets/Scripts/Health.cs rename to Assets/Scripts/Character/Health.cs index 820ea4c..b64ff3f 100644 --- a/Assets/Scripts/Health.cs +++ b/Assets/Scripts/Character/Health.cs @@ -3,61 +3,94 @@ using UnityEngine; using UnityEngine.UI; +/// +/// Manages the health of the player, including taking damage and healing. +/// public class Health : MonoBehaviour { + /// + /// The player's current health value. + /// + [Tooltip("The player's health.")] public float health = 100f; + + /// + /// A list of possible damage values to take. + /// + [Tooltip("List of damage values that can be inflicted.")] public List damageValues = new(); + + /// + /// The index of the current damage value being used. + /// private int _currentDamageIndex; + + /// + /// The audio source for playing sound effects. + /// public AudioSource audioSource; + + /// + /// The sound played when healing. + /// public AudioClip healSound; + /// + /// The UI text element displaying the player's health. + /// public Text healthText; + /// + /// Coroutine for handling damage over time. + /// private Coroutine _damageOverTimeCoroutine; private void Start() { + // Initialize damage values damageValues.Add(50); damageValues.Add(30); damageValues.Add(19); damageValues.Add(1); + + // Update the health UI at the start UpdateHealthUI(); } private void OnTriggerEnter(Collider other) { + // Check if the player has collided with a Chelicerate if (other.CompareTag("Chelicerate")) { TakeDamage(); - _damageOverTimeCoroutine ??= StartCoroutine(DamageOverTime(3f, 0.5f)); } + // Check if the player has collided with a healing kit if (!other.CompareTag("Kit") || !(health < 100f)) return; StartCoroutine(Heal(5f)); - audioSource.PlayOneShot(healSound); + audioSource?.PlayOneShot(healSound); Destroy(other.gameObject); } private void OnTriggerExit(Collider other) { + // Stop damage over time if exiting a Chelicerate trigger if (!other.CompareTag("Chelicerate") || _damageOverTimeCoroutine == null) return; StopCoroutine(_damageOverTimeCoroutine); _damageOverTimeCoroutine = null; } + /// + /// Handles taking damage from enemies or other sources. + /// private void TakeDamage() { if (damageValues.Count > 0) { float damage = damageValues[_currentDamageIndex]; health -= damage; - - _currentDamageIndex++; - if (_currentDamageIndex >= damageValues.Count) - { - _currentDamageIndex = 0; - } + _currentDamageIndex = (_currentDamageIndex + 1) % damageValues.Count; // Loop through damage values if (health <= 0) { @@ -68,16 +101,22 @@ private void TakeDamage() } else { - Debug.Log("No more damage values available."); + Debug.LogWarning("No more damage values available."); } } + /// + /// Applies damage over time at a specified interval. + /// + /// Amount of damage to apply. + /// Time in seconds between each damage application. + /// An IEnumerator for the coroutine. private IEnumerator DamageOverTime(float damageAmount, float interval) { while (true) { health -= damageAmount; - health = Mathf.Max(health, 0f); + health = Mathf.Max(health, 0f); // Ensure health does not drop below 0 if (health <= 0) { @@ -90,6 +129,11 @@ private IEnumerator DamageOverTime(float damageAmount, float interval) } } + /// + /// Heals the player over a specified duration. + /// + /// Duration over which to heal. + /// An IEnumerator for the coroutine. private IEnumerator Heal(float duration) { var targetHealth = Mathf.Min(health + 50f, 100f); @@ -100,7 +144,7 @@ private IEnumerator Heal(float duration) while (timeElapsed < duration) { health += healedAmountPerSecond * Time.deltaTime; - health = Mathf.Max(health, 10f); + health = Mathf.Max(health, 10f); // Ensure health does not drop below 10 timeElapsed += Time.deltaTime; yield return null; } @@ -109,12 +153,20 @@ private IEnumerator Heal(float duration) UpdateHealthUI(); } + /// + /// Updates the health display UI. + /// private void UpdateHealthUI() { - if (healthText == null) return; - healthText.text = (int)health + "%"; + if (healthText != null) + { + healthText.text = $"{(int)health}%"; + } } + /// + /// Handles the player's death. + /// private void Die() { // Handle death logic here diff --git a/Assets/Scripts/Raycast.cs b/Assets/Scripts/Character/Raycast.cs similarity index 58% rename from Assets/Scripts/Raycast.cs rename to Assets/Scripts/Character/Raycast.cs index 95c49bc..ed839bd 100644 --- a/Assets/Scripts/Raycast.cs +++ b/Assets/Scripts/Character/Raycast.cs @@ -4,58 +4,94 @@ using UnityEngine.SceneManagement; using UnityEngine.UI; +/// +/// Manages item pickup and UI updates in the game using raycasting. +/// public class Raycast : MonoBehaviour { + /// + /// The main camera used for raycasting. + /// public Camera mainCamera; + + /// + /// The maximum distance for item pickup raycasting. + /// public float rayDistance = 3f; + + /// + /// The current count of items collected. + /// public int itemCount; + + /// + /// The goal count of items to collect. + /// public int goalCount = 8; + /// + /// Audio source for playing sound effects. + /// public AudioSource audioSource; + + /// + /// Sound effect played when an item is picked up. + /// public AudioClip itemPickupSound; + + /// + /// Sound effect played when the suit is equipped. + /// public AudioClip suitUpSound; + /// + /// UI elements representing equipment. + /// public Image head; public Image body; public Image oxygenTank; public Image oxygenTankCharge; - public Image legL; public Image legR; - public Image feetR; public Image feetL; - public Image breather; - public Image knifeUp; - public Image weightL; public Image weightR; - public Image gogglesRight; public Image gogglesLeft; + /// + /// Text element showing the current count of collected items. + /// public TextMeshProUGUI equipmentCount; private bool _isCountingDown; private void Update() { + // Check for interaction input to pick up items if (Input.GetKeyDown(KeyCode.E) && !_isCountingDown) { StartCoroutine(TryPickUpItem()); } } + /// + /// Attempts to pick up an item if it is in range. + /// private IEnumerator TryPickUpItem() { - var ray = mainCamera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0)); + Ray ray = mainCamera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0)); - if (!Physics.Raycast(ray, out var hit, rayDistance) || !hit.collider.CompareTag("elementos")) yield break; - var halo = hit.collider.GetComponent("Halo"); + // Check if the ray hits an object + if (!Physics.Raycast(ray, out var hit, rayDistance) || !hit.collider.CompareTag("elementos")) + yield break; - if (!halo) + // Optional halo check can be implemented as needed + var halo = hit.collider.GetComponent("Halo"); + if (halo == null) { _isCountingDown = true; Debug.DrawRay(ray.origin, ray.direction * rayDistance, Color.green, 4f); @@ -65,10 +101,13 @@ private IEnumerator TryPickUpItem() } PickUpItem(hit.collider); - _isCountingDown = false; } + /// + /// Handles the logic for picking up an item and updating the equipment UI. + /// + /// The collider of the item to pick up. private void PickUpItem(Collider itemCollider) { itemCount++; @@ -77,46 +116,47 @@ private void PickUpItem(Collider itemCollider) Destroy(itemCollider.gameObject); + // Update the equipment UI based on the item picked up foreach (Transform child in itemCollider.transform) { switch (child.tag) { case "oxygenTank": oxygenTank.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; case "body": body.color = Color.green; legL.color = Color.green; legR.color = Color.green; - audioSource.PlayOneShot(suitUpSound); + PlaySound(suitUpSound); break; case "goggles": gogglesLeft.color = Color.green; gogglesRight.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; case "feet": feetL.color = Color.green; feetR.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; case "weight": weightL.color = Color.green; weightR.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; case "oxygenTankCharge": oxygenTankCharge.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; case "breather": breather.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; case "knife": knifeUp.color = Color.green; - audioSource.PlayOneShot(itemPickupSound); + PlaySound(itemPickupSound); break; default: Debug.Log("No matching tag found."); @@ -124,12 +164,16 @@ private void PickUpItem(Collider itemCollider) } } - if (itemCount == goalCount) + // Check if the goal has been reached to load the next scene + if (itemCount >= goalCount) { SceneManager.LoadScene("Reparation"); } } + /// + /// Updates the color of the equipment count text based on the current item count. + /// private void UpdateEquipmentCountColor() { float progress = (float)itemCount / goalCount; @@ -142,4 +186,20 @@ private void UpdateEquipmentCountColor() _ => equipmentCount.color }; } + + /// + /// Plays the specified audio clip if the audio source is assigned. + /// + /// The audio clip to play. + private void PlaySound(AudioClip clip) + { + if (audioSource != null && clip != null) + { + audioSource.PlayOneShot(clip); + } + else + { + Debug.LogWarning("Audio source or clip is not assigned."); + } + } } diff --git a/Assets/Scripts/Character/Welder.cs b/Assets/Scripts/Character/Welder.cs new file mode 100644 index 0000000..d053188 --- /dev/null +++ b/Assets/Scripts/Character/Welder.cs @@ -0,0 +1,81 @@ +using UnityEngine; + +/// +/// Manages the welder object in the game, allowing the player to pick it up and use it. +/// +public class Welder : MonoBehaviour +{ + /// + /// The prefab of the welder that will be activated when picked up. + /// + [Tooltip("The prefab of the welder.")] + public GameObject welderPrefab; + + /// + /// The maximum distance the player can be from the welder to pick it up. + /// + [Tooltip("Maximum distance to pick up the welder.")] + public float rayDistance = 3f; + + /// + /// The camera that the player is using to view the scene. + /// + [Tooltip("The camera used for raycasting.")] + public Camera playerCamera; + + /// + /// Indicates whether the welder is currently in the player's hand. + /// + public bool WelderInHand { get; private set; } + + private void Start() + { + // Ensure the welder prefab is inactive at the start + if (welderPrefab != null) + { + welderPrefab.SetActive(false); + } + else + { + Debug.LogError("Welder prefab not assigned!"); + } + + // Assign the main camera if not already set + if (playerCamera != null) return; + playerCamera = Camera.main; + if (playerCamera == null) + { + Debug.LogError("No camera found in the scene."); + } + } + + private void Update() + { + // Check for the key press to pick up the welder + if (Input.GetKeyDown(KeyCode.E)) + { + TryPickUpWelder(); + } + } + + /// + /// Tries to pick up the welder if it is within range. + /// + private void TryPickUpWelder() + { + // Cast a ray from the center of the screen + var ray = playerCamera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)); + + // Check if the ray hits an object + if (!Physics.Raycast(ray, out RaycastHit hit, rayDistance)) return; + // Check if the hit object is tagged as "welder" + if (!hit.collider.CompareTag("welder")) return; + // Deactivate the welder in the world + hit.collider.gameObject.SetActive(false); + + // If the welder is not already in hand, activate the prefab + if (WelderInHand) return; + welderPrefab.SetActive(true); + WelderInHand = true; + } +} diff --git a/Assets/Scripts/Creatures/Chelicerate.cs b/Assets/Scripts/Creatures/Chelicerate.cs index 940616a..94f1881 100644 --- a/Assets/Scripts/Creatures/Chelicerate.cs +++ b/Assets/Scripts/Creatures/Chelicerate.cs @@ -1,11 +1,38 @@ using UnityEngine; +/// +/// Represents a Chelicerate that swims in a circular path and interacts with the player. +/// public class Chelicerate : MonoBehaviour { + /// + /// The speed at which the Chelicerate swims. + /// + [Tooltip("The speed at which the Chelicerate swims.")] public float swimSpeed = 2f; + + /// + /// The maximum distance from the center within which the Chelicerate swims. + /// + [Tooltip("The maximum swimming radius.")] public float swimRadius = 5f; + + /// + /// The damage dealt to the player on overlap. + /// + [Tooltip("The damage dealt to the player.")] public float damage = 10f; + + /// + /// The interval at which the Chelicerate changes its swimming direction. + /// + [Tooltip("The time interval for changing direction.")] public float changeDirectionInterval = 2f; + + /// + /// The speed at which the Chelicerate rotates to face its movement direction. + /// + [Tooltip("The speed of rotation towards the movement direction.")] public float rotationSpeed = 5f; private Vector2 _direction; @@ -18,39 +45,82 @@ private void Start() } private void Update() + { + Move(); + CheckDirectionChange(); + KeepWithinBounds(); + RotateTowardsDirection(); + } + + /// + /// Moves the Chelicerate in its current direction. + /// + private void Move() { transform.Translate(_direction * (swimSpeed * Time.deltaTime)); + } + /// + /// Checks if it's time to change direction and calls ChangeDirection if needed. + /// + private void CheckDirectionChange() + { _timer -= Time.deltaTime; if (_timer <= 0f) { ChangeDirection(); _timer = changeDirectionInterval; } + } + /// + /// Keeps the Chelicerate within the defined swim radius. + /// + private void KeepWithinBounds() + { if (Vector2.Distance(transform.position, Vector2.zero) > swimRadius) { _direction = -_direction; } + } + /// + /// Rotates the Chelicerate towards its movement direction. + /// + private void RotateTowardsDirection() + { if (_direction == Vector2.zero) return; + var angle = Mathf.Atan2(_direction.y, _direction.x) * Mathf.Rad2Deg; var targetRotation = Quaternion.Euler(new Vector3(0, 0, angle)); transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); } + /// + /// Changes the direction of the Chelicerate to a random angle. + /// private void ChangeDirection() { - // Set a random horizontal direction + // Set a random horizontal direction with a random angle var angle = Random.Range(0f, 360f); - _direction = new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), 0).normalized; // Ensure y-component is zero + _direction = new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad)).normalized; // Include y-component for 2D movement } + /// + /// Handles collision with the player. + /// + /// The collider of the object this Chelicerate collided with. private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Player")) { - Debug.Log("Overlap"); + Debug.Log("Overlap with Player"); + // Here you can implement damage to the player if necessary + // PlayerHealth playerHealth = other.GetComponent(); + // if (playerHealth != null) + // { + // playerHealth.TakeDamage(damage); + // } } } -} \ No newline at end of file +} diff --git a/Assets/Scripts/Creatures/Fish.cs b/Assets/Scripts/Creatures/Fish.cs index 88e02d5..4c5a634 100644 --- a/Assets/Scripts/Creatures/Fish.cs +++ b/Assets/Scripts/Creatures/Fish.cs @@ -1,37 +1,58 @@ -using System.Collections; -using System.Collections.Generic; using UnityEngine; using UnityEngine.Splines; +/// +/// Controls the movement of a fish along a specified spline path. +/// public class Fish : MonoBehaviour { - public GameObject splineObject; // Reference to the GameObject that holds the SplineContainer - public float swimSpeed = 1f; // Speed along the spline - public float rotationSpeed = 2f; // Speed of rotation to face the spline direction - public bool loop = true; // Should the fish loop back to the start of the spline? + /// + /// Reference to the GameObject that holds the SplineContainer. + /// + [Tooltip("Reference to the GameObject that holds the SplineContainer.")] + public GameObject splineObject; + + /// + /// Speed of the fish along the spline. + /// + [Tooltip("Speed along the spline.")] + public float swimSpeed = 1f; + + /// + /// Speed of rotation to face the spline direction. + /// + [Tooltip("Speed of rotation to face the spline direction.")] + public float rotationSpeed = 2f; + + /// + /// Should the fish loop back to the start of the spline? + /// + [Tooltip("Should the fish loop back to the start of the spline?")] + public bool loop = true; + + /// + /// Offset to correct fish orientation. + /// + [Tooltip("Offset to correct fish orientation.")] + public Vector3 rotationOffset = new Vector3(0f, -90f, 0f); private float _progress; // Progress along the spline (0 to 1) private SplineContainer _splineContainer; private Spline _spline; - // Offset to correct fish orientation - public Vector3 rotationOffset = new Vector3(0f, -90f, 0f); // 90-degree Y-axis offset to face spline direction correctly - private void Start() { - // Check if splineObject is assigned, then get the SplineContainer component - if (splineObject != null) + // Validate splineObject and retrieve SplineContainer component + if (splineObject == null) { - _splineContainer = splineObject.GetComponent(); - if (_splineContainer == null) - { - Debug.LogError("No SplineContainer found on the referenced GameObject."); - return; - } + Debug.LogError("No GameObject with a SplineContainer assigned to Fish."); + return; } - else + + _splineContainer = splineObject.GetComponent(); + if (_splineContainer == null) { - Debug.LogError("No GameObject with a SplineContainer assigned to Fish."); + Debug.LogError("No SplineContainer found on the referenced GameObject."); return; } @@ -44,11 +65,12 @@ private void Update() if (_spline == null) return; // Move fish along the spline - _progress += swimSpeed * Time.deltaTime / _spline.GetLength(); // Normalize speed across spline length + _progress += (swimSpeed * Time.deltaTime) / _spline.GetLength(); // Normalize speed across spline length + // Check if we need to loop or clamp progress if (_progress > 1f) { - _progress = loop ? 0f : 1f; // Loop or clamp progress + _progress = loop ? 0f : 1f; } // Get the global position and tangent from the spline @@ -70,11 +92,14 @@ private void Update() private void OnDrawGizmos() { - // Draw the spline path in the editor (optional) + // Draw the spline path in the editor if (_splineContainer == null || _splineContainer.Spline == null) return; + Gizmos.color = Color.cyan; Spline spline = _splineContainer.Spline; - for (float t = 0; t < 1; t += 0.01f) + + // Draw spheres along the spline for visualization + for (float t = 0; t <= 1; t += 0.01f) { Vector3 point = spline.EvaluatePosition(t); Gizmos.DrawSphere(point, 0.05f); diff --git a/Assets/Scripts/FixLogic.cs b/Assets/Scripts/Logic/FixLogic.cs similarity index 99% rename from Assets/Scripts/FixLogic.cs rename to Assets/Scripts/Logic/FixLogic.cs index abfa766..b73fcba 100644 --- a/Assets/Scripts/FixLogic.cs +++ b/Assets/Scripts/Logic/FixLogic.cs @@ -62,7 +62,7 @@ private void OnTriggerExit(Collider other) private void Update() { - if (welder != null && !welder.welderInHand) + if (welder != null && !welder.WelderInHand) { Debug.Log("Welder not in hand. Cannot fix leaks."); return; diff --git a/Assets/Scripts/WaterLogic.cs b/Assets/Scripts/Logic/WaterLogic.cs similarity index 100% rename from Assets/Scripts/WaterLogic.cs rename to Assets/Scripts/Logic/WaterLogic.cs diff --git a/Assets/Scripts/UI/Sea.cs b/Assets/Scripts/UI/Sea.cs index 9fa5d14..0d4c065 100644 --- a/Assets/Scripts/UI/Sea.cs +++ b/Assets/Scripts/UI/Sea.cs @@ -1,11 +1,34 @@ using UnityEngine; using TMPro; +/// +/// Manages the ocean's logic, including player oxygen and health levels, +/// and displays the current depth on the UI. +/// public class Sea : MonoBehaviour { + /// + /// Reference to the WaterLogic component managing water-related mechanics. + /// + [Tooltip("Reference to the WaterLogic component.")] public WaterLogic waterLogic; + + /// + /// The UI GameObject containing all UI elements. + /// + [Tooltip("The UI GameObject containing UI elements.")] public GameObject ui; + + /// + /// Reference to the player's health component. + /// + [Tooltip("Reference to the player's Health component.")] public Health health; + + /// + /// TextMeshProUGUI component displaying the player's depth. + /// + [Tooltip("Text component displaying the player's depth.")] public TextMeshProUGUI depthText; private TextMeshProUGUI _oxygenText; @@ -28,12 +51,21 @@ private void Start() return; } - _oxygenText = canvas.GetComponentInChildren(); - _healthText = canvas.GetComponentsInChildren()[1]; + // Fetch TextMeshProUGUI components for oxygen and health + var textComponents = canvas.GetComponentsInChildren(); + + if (textComponents.Length < 2) + { + Debug.LogError("Not enough TextMeshProUGUI components found in the child of Canvas."); + return; + } + + _oxygenText = textComponents[0]; + _healthText = textComponents[1]; if (_oxygenText == null) { - Debug.LogError("No TextMeshProUGUI component found in the child of Canvas."); + Debug.LogError("No TextMeshProUGUI component found for oxygen."); return; } @@ -42,6 +74,7 @@ private void Start() Debug.LogError("WaterLogic reference is missing."); } + // Find the player transform _playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; if (_playerTransform == null) { @@ -51,8 +84,25 @@ private void Start() private void Update() { - if (!waterLogic || !_oxygenText) return; + // Check for missing references to prevent errors during runtime + if (waterLogic == null || _oxygenText == null || _healthText == null || _playerTransform == null) + return; + // Update oxygen display + UpdateOxygenDisplay(); + + // Update health display + UpdateHealthDisplay(); + + // Update depth display + UpdateDepthDisplay(); + } + + /// + /// Updates the oxygen display and changes its color based on the current oxygen level. + /// + private void UpdateOxygenDisplay() + { _oxygenText.text = $"{waterLogic.currentOxygen}"; _oxygenText.color = waterLogic.currentOxygen switch { @@ -61,7 +111,13 @@ private void Update() <= 30 => Color.yellow, _ => Color.green }; + } + /// + /// Updates the health display and changes its color based on the current health level. + /// + private void UpdateHealthDisplay() + { _healthText.text = $"{health.health}"; _healthText.color = health.health switch { @@ -70,8 +126,13 @@ private void Update() <= 50 => Color.yellow, _ => Color.green }; + } - if (_playerTransform == null) return; + /// + /// Updates the depth display based on the player's position. + /// + private void UpdateDepthDisplay() + { float depth = -_playerTransform.position.y; depth = Mathf.Max(0, depth); depthText.text = depth.ToString("F0"); diff --git a/Assets/Scripts/Welder.cs b/Assets/Scripts/Welder.cs deleted file mode 100644 index ccff2b9..0000000 --- a/Assets/Scripts/Welder.cs +++ /dev/null @@ -1,50 +0,0 @@ -using UnityEngine; - -public class Welder : MonoBehaviour -{ - public GameObject welderPrefab; - public float rayDistance = 3f; - public Camera playerCamera; - - public bool welderInHand; - - private void Start() - { - if (welderPrefab != null) - { - welderPrefab.SetActive(false); - } - else - { - Debug.LogError("Welder prefab not assigned!"); - } - - if (playerCamera == null) - { - playerCamera = Camera.main; - } - } - - private void Update() - { - if (Input.GetKeyDown(KeyCode.E)) - { - TryPickUpWelder(); - } - } - - private void TryPickUpWelder() - { - var ray = playerCamera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)); - - if (!Physics.Raycast(ray, out var hit, rayDistance)) return; - - if (!hit.collider.CompareTag("welder")) return; - - hit.collider.gameObject.SetActive(false); - - if (welderInHand) return; - welderPrefab.SetActive(true); - welderInHand = true; - } -} \ No newline at end of file