using System; using System.Collections.Generic; using System.Linq; using TMPro; using UnityEngine; [Serializable] public class BoolRow { public List cells = new List(); } [Serializable] public class ShapeScannerConfiguration { public int columns = 6; public float requiredCorrectPercentage = 80.0f; public List rows = new List(); } public class ShapeScanner : MonoBehaviour { public List configurations = new List(); public ShapeScannerRay rayPrefab; public Transform raySpawnCorner1; public Transform raySpawnCorner2; public Transform rayParent; public TextMeshProUGUI currentConfigurationDisplay; public TextMeshProUGUI correctPercentageDisplay; public Material requiredAndActive; public Material requiredAndPassive; public Material notRequiredAndActive; public Material notRequiredAndPassive; private List existingRays; private float raySpawnDistanceX; private float raySpawnDistanceZ; private int currentConfiguration; private int rayCount; private int correctRayStates; // Start is called before the first frame update void Start() { existingRays = new List(); raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x; raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z; currentConfiguration = 0; InitializeConfiguration(); } // Update is called once per frame void Update() { } private void InitializeConfiguration() { // Delete all existing rays first foreach (GameObject ray in existingRays) { Destroy(ray); } ShapeScannerConfiguration configuration = configurations[currentConfiguration]; int rayRowCount = configuration.rows.Count; for (int i = 0; i < rayRowCount; i++) { float rayPosX = raySpawnCorner1.localPosition.x + i * raySpawnDistanceX / (rayRowCount - 1); for (int j = 0; j < rayRowCount; j++) { // Local position float rayPosZ = raySpawnCorner1.localPosition.z + j * raySpawnDistanceZ / (rayRowCount - 1); Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ); ShapeScannerRay ray = Instantiate(rayPrefab, rayParent); ray.transform.localPosition = rayPos; existingRays.Add(ray.gameObject); bool rayCollisionRequired = configuration.rows[i].cells[j]; if (rayCollisionRequired) { ray.Initialize(this, rayCollisionRequired, requiredAndActive, requiredAndPassive); } else { ray.Initialize(this, rayCollisionRequired, notRequiredAndActive, notRequiredAndPassive); } } } // Count total rays and required collision rays rayCount = configuration.rows.SelectMany(row => row.cells).Count(); correctRayStates = configuration.rows.SelectMany(row => row.cells).Count(cell => !cell); UpdateDisplay(calculateCorrectPercentage()); } private float calculateCorrectPercentage() { return Mathf.RoundToInt((float)correctRayStates / rayCount * 100); } public void IncrementCorrectRayCount() { correctRayStates++; float correctPercentage = calculateCorrectPercentage(); if (correctPercentage >= configurations[currentConfiguration].requiredCorrectPercentage) { UpdateCurrentConfigurationDisplay(currentConfiguration + 1); if (currentConfiguration + 1 < configurations.Count) { currentConfiguration++; InitializeConfiguration(); } else { Debug.Log("Shape checker completed"); } } UpdateDisplay(correctPercentage); } public void DecrementCorrectRayCount() { correctRayStates--; UpdateDisplay(calculateCorrectPercentage()); } private void UpdateDisplay(float percentage) { correctPercentageDisplay.text = Mathf.Round(percentage).ToString() + " %"; } private void UpdateCurrentConfigurationDisplay(int confNumber) { currentConfigurationDisplay.text = confNumber.ToString() + " / " + configurations.Count; } }