1
0
forked from cgvr/DeltaVR

ShapeScanner multiple configurations, configurable in editor

This commit is contained in:
2026-01-14 14:02:10 +02:00
parent 33a40c987a
commit 96839e0e82
9 changed files with 448 additions and 70 deletions

View File

@@ -76,6 +76,8 @@ public class ShapeDetectionMinigameController : MonoBehaviour
//spawnedObject.AddComponent<NetworkObject>();
//spawnedObject.AddComponent<NetworkTransform>();
MeshCollider spawnedObjectCollider = spawnedObject.GetComponent<MeshCollider>();
spawnedObjectCollider.convex = false;
spawnedObject.transform.parent = spawnedObjectParent.transform;
spawnedObject.transform.position = spawnedObjectParent.transform.position;
spawnedObject.tag = shapeScannerTag;

View File

@@ -1,68 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
[System.Serializable]
[Serializable]
public class BoolRow
{
public bool[] cells;
public List<bool> cells = new List<bool>();
}
[Serializable]
public class ShapeScannerConfiguration
{
public int columns = 6;
public float requiredCorrectPercentage = 80.0f;
public List<BoolRow> rows = new List<BoolRow>();
}
public class ShapeScanner : MonoBehaviour
{
public List<BoolRow> configuration;
public List<ShapeScannerConfiguration> configurations = new List<ShapeScannerConfiguration>();
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;
public TextMeshProUGUI displayText;
private List<GameObject> existingRays;
private float raySpawnDistanceX;
private float raySpawnDistanceZ;
private int currentConfiguration;
private int rayCount;
private int correctRayStates;
private void Awake()
{
correctRayStates = 0;
}
// Start is called before the first frame update
void Start()
{
float raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x;
float raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z;
existingRays = new List<GameObject>();
raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x;
raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z;
int rayRowCount = configuration.Count;
for (int i = 0; i < rayRowCount; i++)
{
float rayPosX = raySpawnCorner1.localPosition.x + i * raySpawnDistanceX / (rayRowCount - 1);
for (int j = 0; j < rayRowCount; j++)
{
rayCount++;
// 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;
bool rayCollisionRequired = configuration[i].cells[j];
if (rayCollisionRequired)
{
ray.Initialize(this, rayCollisionRequired, requiredAndActive, requiredAndPassive);
} else
{
ray.Initialize(this, rayCollisionRequired, notRequiredAndActive, notRequiredAndPassive);
IncrementCorrectRayCount();
}
}
}
currentConfiguration = 0;
InitializeConfiguration();
}
// Update is called once per frame
@@ -71,21 +60,82 @@ public class ShapeScanner : MonoBehaviour
}
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++;
UpdateDisplay();
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();
UpdateDisplay(calculateCorrectPercentage());
}
private void UpdateDisplay()
private void UpdateDisplay(float percentage)
{
int percentage = Mathf.RoundToInt((float) correctRayStates / rayCount * 100);
displayText.text = percentage.ToString() + " %";
correctPercentageDisplay.text = Mathf.Round(percentage).ToString() + " %";
}
private void UpdateCurrentConfigurationDisplay(int confNumber)
{
currentConfigurationDisplay.text = confNumber.ToString() + " / " + configurations.Count;
}
}