using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpherePatternUnlock : MonoBehaviour { [System.Serializable] public class SphereKey { public GameObject sphere; public bool isCorrect; public Material defaultMaterial; public Material selectedMaterial; public Material correctMaterial; public Material incorrectMaterial; [HideInInspector] public bool isSelected = false; } [SerializeField] private SphereKey[] sphereKeys; [SerializeField] private int requiredCorrectSelections = 3; [SerializeField] private bool randomizeCorrectPattern = true; [SerializeField] private float resetDelay = 2f; [Header("Light Control")] [SerializeField] private Light lightToControl; [SerializeField] private bool startLightEnabled = false; [Header("Audio Feedback")] [SerializeField] private AudioSource audioSource; [SerializeField] private AudioClip correctSound; [SerializeField] private AudioClip incorrectSound; [SerializeField] private AudioClip successSound; private int correctSelections = 0; private int totalSelections = 0; private bool isUnlocked = false; private Coroutine resetCoroutine; private void Start() { InitializeSpheres(); // Set initial light state if (lightToControl != null) { lightToControl.enabled = startLightEnabled; } } private void InitializeSpheres() { if (randomizeCorrectPattern) { SetRandomCorrectPattern(); } // Initialize all spheres with default material foreach (SphereKey key in sphereKeys) { if (key.sphere != null) { MeshRenderer renderer = key.sphere.GetComponent(); if (renderer != null && key.defaultMaterial != null) { renderer.material = key.defaultMaterial; } // Add click handler to each sphere SphereClickHandler clickHandler = key.sphere.GetComponent(); if (clickHandler == null) { clickHandler = key.sphere.AddComponent(); } clickHandler.patternUnlock = this; clickHandler.sphereKey = key; } } correctSelections = 0; totalSelections = 0; isUnlocked = false; } private void SetRandomCorrectPattern() { // Reset all to incorrect foreach (SphereKey key in sphereKeys) { key.isCorrect = false; } // Randomly select correct spheres List indices = new List(); for (int i = 0; i < sphereKeys.Length; i++) { indices.Add(i); } // Shuffle indices for (int i = 0; i < indices.Count; i++) { int temp = indices[i]; int randomIndex = Random.Range(i, indices.Count); indices[i] = indices[randomIndex]; indices[randomIndex] = temp; } // Set first N as correct for (int i = 0; i < Mathf.Min(requiredCorrectSelections, indices.Count); i++) { sphereKeys[indices[i]].isCorrect = true; Debug.Log($"Sphere {indices[i]} is correct"); } } public void OnSphereClicked(SphereKey key) { if (isUnlocked || key.isSelected) return; MeshRenderer renderer = key.sphere.GetComponent(); if (renderer == null) return; key.isSelected = true; totalSelections++; if (key.isCorrect) { // Handle correct selection correctSelections++; renderer.material = key.correctMaterial; if (audioSource != null && correctSound != null) audioSource.PlayOneShot(correctSound); // Check if pattern is complete if (correctSelections >= requiredCorrectSelections) { OnPatternCompleted(true); } } else { // Handle incorrect selection renderer.material = key.incorrectMaterial; if (audioSource != null && incorrectSound != null) audioSource.PlayOneShot(incorrectSound); // Auto-reset after delay if (resetCoroutine != null) StopCoroutine(resetCoroutine); resetCoroutine = StartCoroutine(ResetAfterDelay(resetDelay)); } // Check if all selections are used up if (totalSelections >= requiredCorrectSelections) { // Check if successful bool success = (correctSelections >= requiredCorrectSelections); if (!success) { OnPatternCompleted(false); } } } private void OnPatternCompleted(bool success) { if (isUnlocked) return; if (success) { isUnlocked = true; Debug.Log("🎉 Pattern unlocked successfully!"); // Turn on the light if (lightToControl != null) { lightToControl.enabled = true; } if (audioSource != null && successSound != null) audioSource.PlayOneShot(successSound); } else { Debug.Log("❌ Incorrect pattern!"); // Auto-reset after delay if (resetCoroutine != null) StopCoroutine(resetCoroutine); resetCoroutine = StartCoroutine(ResetAfterDelay(resetDelay)); } } private IEnumerator ResetAfterDelay(float delay) { yield return new WaitForSeconds(delay); ResetPattern(); } public void ResetPattern() { foreach (SphereKey key in sphereKeys) { key.isSelected = false; MeshRenderer renderer = key.sphere.GetComponent(); if (renderer != null && key.defaultMaterial != null) { renderer.material = key.defaultMaterial; } } if (randomizeCorrectPattern && !isUnlocked) { SetRandomCorrectPattern(); } correctSelections = 0; totalSelections = 0; } public void ResetCompletely() { if (lightToControl != null) { lightToControl.enabled = startLightEnabled; } isUnlocked = false; ResetPattern(); } } // Helper component for click detection public class SphereClickHandler : MonoBehaviour { [HideInInspector] public SpherePatternUnlock patternUnlock; [HideInInspector] public SpherePatternUnlock.SphereKey sphereKey; private void OnMouseDown() { if (patternUnlock != null && sphereKey != null) { patternUnlock.OnSphereClicked(sphereKey); } } }